<!doctype html><html lang="en">
 <head>
  <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
  <title>P3313R0: Impacts of noexept on ARM table based exception metadata</title>
<style data-fill-with="stylesheet">/******************************************************************************
 *                   Style sheet for the W3C specifications                   *
 *
 * Special classes handled by this style sheet include:
 *
 * Indices
 *   - .toc for the Table of Contents (<ol class="toc">)
 *     + <span class="secno"> for the section numbers
 *   - #toc for the Table of Contents (<nav id="toc">)
 *   - ul.index for Indices (<a href="#ref">term</a><span>, in § N.M</span>)
 *   - table.index for Index Tables (e.g. for properties or elements)
 *
 * Structural Markup
 *   - table.data for general data tables
 *     -> use 'scope' attribute, <colgroup>, <thead>, and <tbody> for best results !
 *     -> use <table class='complex data'> for extra-complex tables
 *     -> use <td class='long'> for paragraph-length cell content
 *     -> use <td class='pre'> when manual line breaks/indentation would help readability
 *   - dl.switch for switch statements
 *   - ol.algorithm for algorithms (helps to visualize nesting)
 *   - .figure and .caption (HTML4) and figure and figcaption (HTML5)
 *     -> .sidefigure for right-floated figures
 *   - ins/del
 *     -> ins/del.c### for candidate and proposed changes (amendments)
 *
 * Code
 *   - pre and code
 *
 * Special Sections
 *   - .note       for informative notes             (div, p, span, aside, details)
 *   - .example    for informative examples          (div, p, pre, span)
 *   - .issue      for issues                        (div, p, span)
 *   - .advisement for loud normative statements     (div, p, strong)
 *   - .annoying-warning for spec obsoletion notices (div, aside, details)
 *   - .correction for "candidate corrections"       (div, aside, details, section)
 *   - .addition   for "candidate additions"         (div, aside, details, section)
 *   - .correction.proposed for "proposed corrections" (div, aside, details, section)
 *   - .addition.proposed   for "proposed additions"   (div, aside, details, section)
 *
 * Definition Boxes
 *   - pre.def   for WebIDL definitions
 *   - table.def for tables that define other entities (e.g. CSS properties)
 *   - dl.def    for definition lists that define other entitles (e.g. HTML elements)
 *
 * Numbering
 *   - .secno for section numbers in .toc and headings (<span class='secno'>3.2</span>)
 *   - .marker for source-inserted example/figure/issue numbers (<span class='marker'>Issue 4</span>)
 *   - ::before styled for CSS-generated issue/example/figure numbers:
 *     -> Documents wishing to use this only need to add
 *        figcaption::before,
 *        .caption::before { content: "Figure "  counter(figure) " ";  }
 *        .example::before { content: "Example " counter(example) " "; }
 *        .issue::before   { content: "Issue "   counter(issue) " ";   }
 *
 * Header Stuff (ignore, just don't conflict with these classes)
 *   - .head for the header
 *   - .copyright for the copyright
 *
 * Outdated warning for old specs
 *
 * Miscellaneous
 *   - .overlarge for things that should be as wide as possible, even if
 *     that overflows the body text area. This can be used on an item or
 *     on its container, depending on the effect desired.
 *     Note that this styling basically doesn't help at all when printing,
 *     since A4 paper isn't much wider than the max-width here.
 *     It's better to design things to fit into a narrower measure if possible.
 *
 *   - js-added ToC jump links (see fixup.js)
 *
 ******************************************************************************/

/* color variables included separately for reliability */

/******************************************************************************/
/*                                    Body                                    */
/******************************************************************************/

	html {
	}

	body {
		counter-reset: example figure issue;

		/* Layout */
		max-width: 50em;			  /* limit line length to 50em for readability   */
		margin: 0 auto;				/* center text within page                    */
		padding: 1.6em 1.5em 2em 50px; /* assume 16px font size for downlevel clients */
		padding: 1.6em 1.5em 2em calc(26px + 1.5em); /* leave space for status flag    */

		/* Typography */
		line-height: 1.5;
		font-family: sans-serif;
		widows: 2;
		orphans: 2;
		word-wrap: break-word;
		overflow-wrap: break-word;
		hyphens: auto;

		color: black;
		color: var(--text);
		background: white top left fixed no-repeat;
		background: var(--bg) top left fixed no-repeat;
		background-size: 25px auto;
	}


/******************************************************************************/
/*                         Front Matter & Navigation                          */
/******************************************************************************/

/** Header ********************************************************************/

	div.head { margin-bottom: 1em; }
	div.head hr { border-style: solid; }

	div.head h1 {
		font-weight: bold;
		margin: 0 0 .1em;
		font-size: 220%;
	}

	div.head h2 { margin-bottom: 1.5em;}

/** W3C Logo ******************************************************************/

	.head .logo {
		float: right;
		margin: 0.4rem 0 0.2rem .4rem;
	}

	.head img[src*="logos/W3C"] {
		display: block;
		border: solid #1a5e9a;
		border: solid var(--logo-bg);
		border-width: .65rem .7rem .6rem;
		border-radius: .4rem;
		background: #1a5e9a;
		background: var(--logo-bg);
		color: white;
		color: var(--logo-text);
		font-weight: bold;
	}

	.head a:hover > img[src*="logos/W3C"],
	.head a:focus > img[src*="logos/W3C"] {
		opacity: .8;
	}

	.head a:active > img[src*="logos/W3C"] {
		background: #c00;
		background: var(--logo-active-bg);
		border-color: #c00;
		border-color: var(--logo-active-bg);
	}

	/* see also additional rules in Link Styling section */

/** Copyright *****************************************************************/

	p.copyright,
	p.copyright small { font-size: small; }

/** Back to Top / ToC Toggle **************************************************/

	@media print {
		#toc-nav {
			display: none;
		}
	}
	@media not print {
		#toc-nav {
			position: fixed;
			z-index: 3;
			bottom: 0; left: 0;
			margin: 0;
			min-width: 1.33em;
			border-top-right-radius: 2rem;
			box-shadow: 0 0 2px;
			font-size: 1.5em;
		}
		#toc-nav > a {
			display: block;
			white-space: nowrap;

			height: 1.33em;
			padding: .1em 0.3em;
			margin: 0;

			box-shadow: 0 0 2px;
			border: none;
			border-top-right-radius: 1.33em;

			color: #707070;
			color: var(--tocnav-normal-text);
			background: white;
			background: var(--tocnav-normal-bg);
		}
		#toc-nav > a:hover,
		#toc-nav > a:focus {
			color: black;
			color: var(--tocnav-hover-text);
			background: #f8f8f8;
			background: var(--tocnav-hover-bg);
		}
		#toc-nav > a:active {
			color: #c00;
			color: var(--tocnav-active-text);
			background: white;
			background: var(--tocnav-active-bg);
		}

		#toc-nav > #toc-jump {
			padding-bottom: 2em;
			margin-bottom: -1.9em;
		}

		/* statusbar gets in the way on keyboard focus; remove once browsers fix */
		#toc-nav > a[href="#toc"]:not(:hover):focus:last-child {
			padding-bottom: 1.5rem;
		}

		#toc-nav:not(:hover) > a:not(:focus) > span + span {
			/* Ideally this uses :focus-within on #toc-nav */
			display: none;
		}
		#toc-nav > a > span + span {
			padding-right: 0.2em;
		}
	}

/** ToC Sidebar ***************************************************************/

	/* Floating sidebar */
	@media screen {
		body.toc-sidebar #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			max-width: 80%;
			max-width: calc(100% - 2em - 26px);
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			color: black;
			color: var(--tocsidebar-text);
			background: inherit;
			background-color: #f7f8f9;
			background-color: var(--tocsidebar-bg);
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
			box-shadow: -.1em 0 .25em var(--tocsidebar-shadow) inset;
		}
		body.toc-sidebar #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
			color: var(--tocsidebar-heading-text);
		}
		body.toc-sidebar #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	/* Hide main scroller when only the ToC is visible anyway */
	@media screen and (max-width: 28em) {
		body.toc-sidebar {
			overflow: hidden;
		}
	}

	/* Sidebar with its own space */
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			color: black;
			color: var(--tocsidebar-text);
			background: inherit;
			background-color: #f7f8f9;
			background-color: var(--tocsidebar-bg);
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
			box-shadow: -.1em 0 .25em var(--tocsidebar-shadow) inset;
		}
		body:not(.toc-inline) #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
			color: var(--tocsidebar-heading-text);
		}

		body:not(.toc-inline) {
			padding-left: 29em;
		}
		/* See also Overflow section at the bottom */

		body:not(.toc-inline) #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) {
			margin: 0 4em;
		}
	}

/******************************************************************************/
/*                                Sectioning                                  */
/******************************************************************************/

/** Headings ******************************************************************/

	h1, h2, h3, h4, h5, h6, dt {
		page-break-after: avoid;
		page-break-inside: avoid;
		font: 100% sans-serif;   /* Reset all font styling to clear out UA styles */
		font-family: inherit;	/* Inherit the font family. */
		line-height: 1.2;		/* Keep wrapped headings compact */
		hyphens: manual;		/* Hyphenated headings look weird */
	}

	h2, h3, h4, h5, h6 {
		margin-top: 3rem;
	}

	h1, h2, h3 {
		color: #005A9C;
		color: var(--heading-text);
	}

	h1 { font-size: 170%; }
	h2 { font-size: 140%; }
	h3 { font-size: 120%; }
	h4 { font-weight: bold; }
	h5 { font-style: italic; }
	h6 { font-variant: small-caps; }
	dt { font-weight: bold; }

/** Subheadings ***************************************************************/

	h1 + h2,
	#profile-and-date {
		/* #profile-and-date is a subtitle in an H2 under the H1 */
		margin-top: 0;
	}
	h2 + h3,
	h3 + h4,
	h4 + h5,
	h5 + h6 {
		margin-top: 1.2em; /* = 1 x line-height */
	}

/** Section divider ***********************************************************/

	:not(.head) > :not(.head) + hr {
		font-size: 1.5em;
		text-align: center;
		margin: 1em auto;
		height: auto;
		color: black;
		color: var(--hr-text);
		border: transparent solid 0;
		background: transparent;
	}
	:not(.head) > hr::before {
		content: "\2727\2003\2003\2727\2003\2003\2727";
	}

/******************************************************************************/
/*                            Paragraphs and Lists                            */
/******************************************************************************/

	p {
		margin: 1em 0;
	}

	dd > p:first-child,
	li > p:first-child {
		margin-top: 0;
	}

	ul, ol {
		margin-left: 0;
		padding-left: 2em;
	}

	li {
		margin: 0.25em 0 0.5em;
		padding: 0;
	}

	dl dd {
		margin: 0 0 .5em 2em;
	}

	.head dd + dd { /* compact for header */
		margin-top: -.5em;
	}

	/* Style for algorithms */
	ol.algorithm ol:not(.algorithm),
	.algorithm > ol ol:not(.algorithm) {
	border-left: 0.5em solid #DEF;
	border-left: 0.5em solid var(--algo-border);
	}

	/* Put nice boxes around each algorithm. */
	[data-algorithm]:not(.heading) {
	 padding: .5em;
	 border: thin solid #ddd;
	 border: thin solid var(--algo-border);
	 border-radius: .5em;
	 margin: .5em calc(-0.5em - 1px);
	}
	[data-algorithm]:not(.heading) > :first-child {
	 margin-top: 0;
	}
	[data-algorithm]:not(.heading) > :last-child {
	 margin-bottom: 0;
	}

	/* Style for switch/case <dl>s */
	dl.switch > dd > ol.only,
	dl.switch > dd > .only > ol {
	margin-left: 0;
	}
	dl.switch > dd > ol.algorithm,
	dl.switch > dd > .algorithm > ol {
	margin-left: -2em;
	}
	dl.switch {
	padding-left: 2em;
	}
	dl.switch > dt {
	text-indent: -1.5em;
	margin-top: 1em;
	}
	dl.switch > dt + dt {
	margin-top: 0;
	}
	dl.switch > dt::before {
	content: '\21AA';
	padding: 0 0.5em 0 0;
	display: inline-block;
	width: 1em;
	text-align: right;
	line-height: 0.5em;
	}

/** Terminology Markup ********************************************************/


/******************************************************************************/
/*                                 Inline Markup                              */
/******************************************************************************/

/** Terminology Markup ********************************************************/
	dfn   { /* Defining instance */
		font-weight: bolder;
	}
	a > i { /* Instance of term */
		font-style: normal;
	}
	dt dfn code, code.idl {
		font-size: inherit;
	}
	dfn var {
		font-style: normal;
	}

/** Change Marking ************************************************************/

	del {
		color: #aa0000;
		color: var(--del-text);
		background: transparent;
		background: var(--del-bg);
		text-decoration: line-through;
	}
	ins {
		color: #006100;
		color: var(--ins-text);
		background: transparent;
		background: var(--ins-bg);
		text-decoration: underline;
	}

	/* for amendments (candidate/proposed changes) */

	.amendment ins, .correction ins, .addition ins,
	ins[class^=c] {
		text-decoration-style: dotted;
	}
	.amendment del, .correction del, .addition del,
	del[class^=c] {
		text-decoration-style: dotted;
	}
	.amendment.proposed ins, .correction.proposed ins, .addition.proposed ins,
	ins[class^=c].proposed {
		text-decoration-style: double;
	}
	.amendment.proposed del, .correction.proposed del, .addition.proposed del,
	del[class^=c].proposed {
		text-decoration-style: double;
	}

/** Miscellaneous improvements to inline formatting ***************************/

	sup {
		vertical-align: super;
		font-size: 80%
	}

/******************************************************************************/
/*                                    Code                                    */
/******************************************************************************/

/** General monospace/pre rules ***********************************************/

	pre, code, samp {
		font-family: Menlo, Consolas, "DejaVu Sans Mono", Monaco, monospace;
		font-size: .9em;
		hyphens: none;
		text-transform: none;
		text-align: left;
		text-align: start;
		font-variant: normal;
		orphans: 3;
		widows: 3;
		page-break-before: avoid;
	}
	pre code,
	code code {
		font-size: 100%;
	}

	pre {
		margin-top: 1em;
		margin-bottom: 1em;
		overflow: auto;
	}

/** Inline Code fragments *****************************************************/

	/* Do something nice. */

/******************************************************************************/
/*                                    Links                                   */
/******************************************************************************/

/** General Hyperlinks ********************************************************/

	/* We hyperlink a lot, so make it less intrusive */
	a[href] {
		color: #034575;
		color: var(--a-normal-text);
		text-decoration: underline #707070;
		text-decoration: underline var(--a-normal-underline);
		text-decoration-skip-ink: none;
	}
	a:visited {
		color: #034575;
		color: var(--a-visited-text);
		text-decoration-color: #bbb;
		text-decoration-color: var(--a-visited-underline);
	}

	/* Indicate interaction with the link */
	a[href]:focus,
	a[href]:hover {
		text-decoration-thickness: 2px;
	}
	a[href]:active {
		color: #c00;
		color: var(--a-active-text);
		text-decoration-color: #c00;
		text-decoration-color: var(--a-active-underline);
	}

	/* Backout above styling for W3C logo */
	.head .logo,
	.head .logo a {
		border: none;
		text-decoration: none;
		background: transparent;
	}

/******************************************************************************/
/*                                    Images                                  */
/******************************************************************************/

	img {
		border-style: none;
	}

	img, svg {
		/* Intentionally not color-scheme aware. */
		background: white;
	}

	/* For autogen numbers, add
	  .caption::before, figcaption::before { content: "Figure " counter(figure) ". "; }
	*/

	figure, .figure, .sidefigure {
		page-break-inside: avoid;
		text-align: center;
		margin: 2.5em 0;
	}
	.figure img,	.sidefigure img,	figure img,
	.figure object, .sidefigure object, figure object {
		max-width: 100%;
		margin: auto;
		height: auto;
	}
	.figure pre, .sidefigure pre, figure pre {
		text-align: left;
		display: table;
		margin: 1em auto;
	}
	.figure table, figure table {
		margin: auto;
	}
	@media screen and (min-width: 20em) {
		.sidefigure {
			float: right;
			width: 50%;
			margin: 0 0 0.5em 0.5em;
		}
	}
	.caption, figcaption, caption {
		font-style: italic;
		font-size: 90%;
	}
	.caption::before, figcaption::before, figcaption > .marker {
		font-weight: bold;
	}
	.caption, figcaption {
		counter-increment: figure;
	}

	/* DL list is indented 2em, but figure inside it is not */
	dd > .figure, dd > figure { margin-left: -2em; }

/******************************************************************************/
/*                             Colored Boxes                                  */
/******************************************************************************/

	.issue, .note, .example, .assertion, .advisement, blockquote,
	.amendment, .correction, .addition {
		margin: 1em auto;
		padding: .5em;
		border: .5em;
		border-left-style: solid;
		page-break-inside: avoid;
	}
	span.issue, span.note {
		padding: .1em .5em .15em;
		border-right-style: solid;
	}

	blockquote > :first-child,
	.note  > p:first-child,
	.issue > p:first-child,
	.amendment > p:first-child,
	.correction > p:first-child,
	.addition > p:first-child {
		margin-top: 0;
	}
	blockquote > :last-child,
	.note  > p:last-child,
	.issue > p:last-child,
	.amendment > p:last-child,
	.correction > p:last-child,
	.addition > p:last-child {
		margin-bottom: 0;
	}


	.issue::before, .issue > .marker,
	.example::before, .example > .marker,
	.note::before, .note > .marker,
	details.note > summary > .marker,
	.amendment::before, .amendment > .marker,
	details.amendment > summary > .marker,
	.addition::before, .addition > .marker,
	addition.amendment > summary > .marker,
	.correction::before, .correction > .marker,
	correction.amendment > summary > .marker
	{
		text-transform: uppercase;
		padding-right: 1em;
	}

	.example::before, .example > .marker {
		display: block;
		padding-right: 0em;
	}

/** Blockquotes ***************************************************************/

	blockquote {
		border-color: silver;
		border-color: var(--blockquote-border);
		background: transparent;
		background: var(--blockquote-bg);
		color: currentcolor;
		color: var(--blockquote-text);
	}

/** Open issue ****************************************************************/

	.issue {
		border-color: #e05252;
		border-color: var(--issue-border);
		background: #fbe9e9;
		background: var(--issue-bg);
		color: black;
		color: var(--issue-text);
		counter-increment: issue;
		overflow: auto;
	}
	.issue::before, .issue > .marker {
		color: #831616;
		color: var(--issueheading-text);
	}
	/* Add .issue::before { content: "Issue " counter(issue) " "; } for autogen numbers,
	  or use class="marker" to mark up the issue number in source. */

/** Example *******************************************************************/

	.example {
		border-color: #e0cb52;
		border-color: var(--example-border);
		background: #fcfaee;
		background: var(--example-bg);
		color: black;
		color: var(--example-text);
		counter-increment: example;
		overflow: auto;
		clear: both;
	}
	.example::before, .example > .marker {
		color: #574b0f;
		color: var(--exampleheading-text);
	}
	/* Add .example::before { content: "Example " counter(example) " "; } for autogen numbers,
	  or use class="marker" to mark up the example number in source. */

/** Non-normative Note ********************************************************/

	.note {
		border-color: #52e052;
		border-color: var(--note-border);
		background: #e9fbe9;
		background: var(--note-bg);
		color: black;
		color: var(--note-text);
		overflow: auto;
	}

	.note::before, .note > .marker,
	details.note > summary {
		color: hsl(120, 70%, 30%);
		color: var(--noteheading-text);
	}
	/* Add .note::before { content: "Note "; } for autogen label,
	  or use class="marker" to mark up the label in source. */

	details.note[open] > summary {
		border-bottom: 1px silver solid;
		border-bottom: 1px var(--notesummary-underline) solid;
	}

/** Assertion Box *************************************************************/
	/*  for assertions in algorithms */

	.assertion {
		border-color: #AAA;
		border-color: var(--assertion-border);
		background: #EEE;
		background: var(--assertion-bg);
		color: black;
		color: var(--assertion-text);
	}

/** Advisement Box ************************************************************/
	/*  for attention-grabbing normative statements */

	.advisement {
		border-color: orange;
		border-color: var(--advisement-border);
		border-style: none solid;
		background: #fec;
		background: var(--advisement-bg);
		color: black;
		color: var(--advisement-text);
	}
	strong.advisement {
		display: block;
		text-align: center;
	}
	.advisement::before, .advisement > .marker {
		color: #b35f00;
		color: var(--advisementheading-text);
	}

/** Amendment Box *************************************************************/

	.amendment, .correction, .addition {
		border-color: #330099;
		border-color: var(--amendment-border);
		background: #F5F0FF;
		background: var(--amendment-bg);
		color: black;
		color: var(--amendment-text);
	}
	.amendment.proposed, .correction.proposed, .addition.proposed {
		border-style: solid;
		border-block-width: 0.25em;
	}
	.amendment::before, .amendment > .marker,
	details.amendment > summary::before, details.amendment > summary > .marker,
	.correction::before, .correction > .marker,
	details.correction > summary::before, details.correction > summary > .marker,
	.addition::before, .addition > .marker,
	details.addition > summary::before, details.addition > summary > .marker {
		color: #220066;
		color: var(--amendmentheading-text);
	}
	.amendment.proposed::before, .amendment.proposed > .marker,
	details.amendment.proposed > summary::before, details.amendment.proposed > summary > .marker,
	.correction.proposed::before, .correction.proposed > .marker,
	details.correction.proposed > summary::before, details.correction.proposed > summary > .marker,
	.addition.proposed::before, .addition.proposed > .marker,
	details.addition.proposed > summary::before, details.addition.proposed > summary > .marker {
		font-weight: bold;
	}

/** Spec Obsoletion Notice ****************************************************/
	/* obnoxious obsoletion notice for older/abandoned specs. */

	details {
		display: block;
	}
	summary {
		font-weight: bolder;
	}

	.annoying-warning:not(details),
	details.annoying-warning:not([open]) > summary,
	details.annoying-warning[open] {
		background: hsla(40,100%,50%,0.95);
		background: var(--warning-bg);
		color: black;
		color: var(--warning-text);
		padding: .75em 1em;
		border: red;
		border: var(--warning-border);
		border-style: solid none;
		box-shadow: 0 2px 8px black;
		text-align: center;
	}
	.annoying-warning :last-child {
		margin-bottom: 0;
	}

@media not print {
	details.annoying-warning[open] {
		position: fixed;
		left: 0;
		right: 0;
		bottom: 2em;
		z-index: 1000;
	}
}

	details.annoying-warning:not([open]) > summary {
		text-align: center;
	}

/** Entity Definition Boxes ***************************************************/

	.def {
		padding: .5em 1em;
		background: #def;
		background: var(--def-bg);
		margin: 1.2em 0;
		border-left: 0.5em solid #8ccbf2;
		border-left: 0.5em solid var(--def-border);
		color: black;
		color: var(--def-text);
	}

/******************************************************************************/
/*                                    Tables                                  */
/******************************************************************************/

	th, td {
		text-align: left;
		text-align: start;
	}

/** Property/Descriptor Definition Tables *************************************/

	table.def {
		/* inherits .def box styling, see above */
		width: 100%;
		border-spacing: 0;
	}

	table.def td,
	table.def th {
		padding: 0.5em;
		vertical-align: baseline;
		border-bottom: 1px solid #bbd7e9;
		border-bottom: 1px solid var(--defrow-border);
	}

	table.def > tbody > tr:last-child th,
	table.def > tbody > tr:last-child td {
		border-bottom: 0;
	}

	table.def th {
		font-style: italic;
		font-weight: normal;
		padding-left: 1em;
		width: 3em;
	}

	/* For when values are extra-complex and need formatting for readability */
	table td.pre {
		white-space: pre-wrap;
	}

	/* A footnote at the bottom of a def table */
	table.def td.footnote {
		padding-top: 0.6em;
	}
	table.def td.footnote::before {
		content: " ";
		display: block;
		height: 0.6em;
		width: 4em;
		border-top: thin solid;
	}

/** Data tables (and properly marked-up index tables) *************************/
	/*
		<table class="data"> highlights structural relationships in a table
		when correct markup is used (e.g. thead/tbody, th vs. td, scope attribute)

		Use class="complex data" for particularly complicated tables --
		(This will draw more lines: busier, but clearer.)

		Use class="long" on table cells with paragraph-like contents
		(This will adjust text alignment accordingly.)
		Alternately use class="longlastcol" on tables, to have the last column assume "long".
	*/

	table {
		word-wrap: normal;
		overflow-wrap: normal;
		hyphens: manual;
	}

	table.data,
	table.index {
		margin: 1em auto;
		border-collapse: collapse;
		border: hidden;
		width: 100%;
	}
	table.data caption,
	table.index caption {
		max-width: 50em;
		margin: 0 auto 1em;
	}

	table.data td,  table.data th,
	table.index td, table.index th {
		padding: 0.5em 1em;
		border-width: 1px;
		border-color: silver;
		border-color: var(--datacell-border);
		border-top-style: solid;
	}

	table.data thead td:empty {
		padding: 0;
		border: 0;
	}

	table.data  thead,
	table.index thead,
	table.data  tbody,
	table.index tbody {
		border-bottom: 2px solid;
	}

	table.data colgroup,
	table.index colgroup {
		border-left: 2px solid;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		border-right: 2px solid;
		border-top: 1px solid silver;
		border-top: 1px solid var(--datacell-border);
		padding-right: 1em;
	}

	table.data th[colspan],
	table.data td[colspan] {
		text-align: center;
	}

	table.complex.data th,
	table.complex.data td {
		border: 1px solid silver;
		border: 1px solid var(--datacell-border);
		text-align: center;
	}

	table.data.longlastcol td:last-child,
	table.data td.long {
		vertical-align: baseline;
		text-align: left;
	}

	table.data img {
		vertical-align: middle;
	}


/*
Alternate table alignment rules

	table.data,
	table.index {
		text-align: center;
	}

	table.data  thead th[scope="row"],
	table.index thead th[scope="row"] {
		text-align: right;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		text-align: right;
	}

Possible extra rowspan handling

	table.data  tbody th[rowspan]:not([rowspan='1']),
	table.index tbody th[rowspan]:not([rowspan='1']),
	table.data  tbody td[rowspan]:not([rowspan='1']),
	table.index tbody td[rowspan]:not([rowspan='1']) {
		border-left: 1px solid silver;
	}

	table.data  tbody th[rowspan]:first-child,
	table.index tbody th[rowspan]:first-child,
	table.data  tbody td[rowspan]:first-child,
	table.index tbody td[rowspan]:first-child{
		border-left: 0;
		border-right: 1px solid silver;
	}
*/

/******************************************************************************/
/*                                  Indices                                   */
/******************************************************************************/


/** Table of Contents *********************************************************/

	.toc a {
		/* More spacing; use padding to make it part of the click target. */
		padding: 0.1rem 1px 0;
		/* Larger, more consistently-sized click target */
		display: block;
		/* Switch to using border-bottom for underlines */
		text-decoration: none;
		border-bottom: 1px solid;
		/* Reverse color scheme */
		color: black;
		color: var(--toclink-text);
		border-color: #3980b5;
		border-color: var(--toclink-underline);
	}
	.toc a:visited {
		color: black;
		color: var(--toclink-visited-text);
		border-color: #054572;
		border-color: var(--toclink-visited-underline);
	}
	.toc a:focus,
	.toc a:hover {
		background: rgba(75%, 75%, 75%, .25);
		background: var(--a-hover-bg);
		border-bottom-width: 3px;
		margin-bottom: -2px;
	}
	.toc a:not(:focus):not(:hover) {
		/* Allow colors to cascade through from link styling */
		border-bottom-color: transparent;
	}

	.toc, .toc ol, .toc ul, .toc li {
		list-style: none; /* Numbers must be inlined into source */
		/* because generated content isn't search/selectable and markers can't do multilevel yet */
		margin:  0;
		padding: 0;
	}
	.toc {
		line-height: 1.1em;
	}

	/* ToC not indented until third level, but font style & margins show hierarchy */
	.toc > li			{ font-weight: bold;   }
	.toc > li li		 { font-weight: normal; }
	.toc > li li li	  { font-size:   95%;	}
	.toc > li li li li	{ font-size:   90%;	}
	.toc > li li li li li { font-size:   85%;	}

	/* @supports not (display:grid) { */
		.toc > li			{ margin: 1.5rem 0;	}
		.toc > li li		 { margin: 0.3rem 0;	}
		.toc > li li li	  { margin-left: 2rem;   }

		/* Section numbers in a column of their own */
		.toc .secno {
			float: left;
			width: 4rem;
			white-space: nowrap;
		}
		.toc > li li li li .secno { font-size: 85%; }
		.toc > li li li li li .secno { font-size: 100%; }

		.toc li {
			clear: both;
		}

		:not(li) > .toc			 { margin-left:  5rem; }
		.toc .secno				 { margin-left: -5rem; }
		.toc > li li li .secno	  { margin-left: -7rem; }
		.toc > li li li li .secno	{ margin-left: -9rem; }
		.toc > li li li li li .secno { margin-left: -11rem; }

		/* Tighten up indentation in narrow ToCs */
		@media (max-width: 30em) {
			:not(li) > .toc			 { margin-left:  4rem; }
			.toc .secno				 { margin-left: -4rem; }
			.toc > li li li			 { margin-left:  1rem; }
			.toc > li li li .secno	  { margin-left: -5rem; }
			.toc > li li li li .secno	{ margin-left: -6rem; }
			.toc > li li li li li .secno { margin-left: -7rem; }
		}
		/* Loosen it on wide screens */
		@media screen and (min-width: 78em) {
			body:not(.toc-inline) :not(li) > .toc			 { margin-left:  4rem; }
			body:not(.toc-inline) .toc .secno				 { margin-left: -4rem; }
			body:not(.toc-inline) .toc > li li li			 { margin-left:  1rem; }
			body:not(.toc-inline) .toc > li li li .secno	  { margin-left: -5rem; }
			body:not(.toc-inline) .toc > li li li li .secno	{ margin-left: -6rem; }
			body:not(.toc-inline) .toc > li li li li li .secno { margin-left: -7rem; }
	}
	/* } */

	@supports (display:grid) and (display:contents) {
		/* Use #toc over .toc to override non-@supports rules. */
		#toc {
			display: grid;
			align-content: start;
			grid-template-columns: auto 1fr;
			grid-column-gap: 1rem;
			column-gap: 1rem;
			grid-row-gap: .6rem;
			row-gap: .6rem;
		}
		#toc h2 {
			grid-column: 1 / -1;
			margin-bottom: 0;
		}
		#toc ol,
		#toc li,
		#toc a {
			display: contents;
			/* Switch <a> to subgrid when supported */
		}
		#toc span {
			margin: 0;
		}
		#toc > .toc > li > a > span {
			/* The spans of the top-level list,
			  comprising the first items of each top-level section. */
			margin-top: 1.1rem;
		}
		#toc#toc .secno { /* Ugh, need more specificity to override base.css */
			grid-column: 1;
			width: auto;
			margin-left: 0;
		}
		#toc .content {
			grid-column: 2;
			width: auto;
			margin-right: 1rem;
			border-bottom: 3px solid transparent;
			margin-bottom: -3px;
		}
		#toc .content:hover,
		#toc .content:focus {
			background: rgba(75%, 75%, 75%, .25);
			background: var(--a-hover-bg);
			border-bottom-color: #054572;
			border-bottom-color: var(--toclink-underline);
		}
		#toc li li li .content {
			margin-left: 1rem;
		}
		#toc li li li li .content {
			margin-left: 2rem;
		}
	}


/** Index *********************************************************************/

	/* Index Lists: Layout */
	ul.index	  { margin-left: 0; columns: 15em; text-indent: 1em hanging; }
	ul.index li	{ margin-left: 0; list-style: none; break-inside: avoid; }
	ul.index li li { margin-left: 1em; }
	ul.index dl	{ margin-top: 0; }
	ul.index dt	{ margin: .2em 0 .2em 20px;}
	ul.index dd	{ margin: .2em 0 .2em 40px;}
	/* Index Lists: Typography */
	ul.index ul,
	ul.index dl { font-size: smaller; }
	@media not print {
		ul.index li a + span {
			white-space: nowrap;
			color: transparent; }
		ul.index li a:hover + span,
		ul.index li a:focus + span {
			color: #707070;
			color: var(--indexinfo-text);
		}
	}

/** Index Tables *****************************************************/
	/* See also the data table styling section, which this effectively subclasses */

	table.index {
		font-size: small;
		border-collapse: collapse;
		border-spacing: 0;
		text-align: left;
		margin: 1em 0;
	}

	table.index td,
	table.index th {
		padding: 0.4em;
	}

	table.index tr:hover td:not([rowspan]),
	table.index tr:hover th:not([rowspan]) {
		color: black;
		color: var(--indextable-hover-text);
		background: #f7f8f9;
		background: var(--indextable-hover-bg);
	}

	/* The link in the first column in the property table (formerly a TD) */
	table.index th:first-child a {
		font-weight: bold;
	}

/** Outdated warning **********************************************************/

.outdated-spec {
	color: black;
	color: var(--outdatedspec-text);
	background-color: rgba(0,0,0,0.5);
	background-color: var(--outdatedspec-bg);
}

.outdated-warning {
	position: fixed;
	bottom: 50%;
	left: 0;
	right: 0;
	margin: 0 auto;
	width: 50%;
	background: maroon;
	background: var(--outdated-bg);
	color: white;
	color: var(--outdated-text);
	border-radius: 1em;
	box-shadow: 0 0 1em red;
	box-shadow: 0 0 1em var(--outdated-shadow);
	padding: 2em;
	text-align: center;
	z-index: 2;
}

.outdated-warning a {
	color: currentcolor;
	background: transparent;
}

.edited-rec-warning {
	background: darkorange;
	background: var(--editedrec-bg);
	box-shadow: 0 0 1em;
}

.outdated-warning button {
	color: var(--outdated-text);
	border-radius: 1em;
	box-shadow: 0 0 1em red;
	box-shadow: 0 0 1em var(--outdated-shadow);
	padding: 2em;
	text-align: center;
	z-index: 2;
}

.outdated-warning a {
	color: currentcolor;
	background: transparent;
}

.edited-rec-warning {
	background: darkorange;
	background: var(--editedrec-bg);
	box-shadow: 0 0 1em;
}

.outdated-warning button {
	position: absolute;
	top: 0;
	right:0;
	margin: 0;
	border: 0;
	padding: 0.25em 0.5em;
	background: transparent;
	color: white;
	color: var(--outdated-text);
	font:1em sans-serif;
	text-align:center;
}

.outdated-warning span {
	display: block;
}

.outdated-collapsed {
	bottom: 0;
	border-radius: 0;
	width: 100%;
	padding: 0;
}

/******************************************************************************/
/*                                    Print                                   */
/******************************************************************************/

	@media print {
		/* Pages have their own margins. */
		html {
			margin: 0;
		}
		/* Serif for print. */
		body {
			font-family: serif;
		}

		.outdated-warning {
			position: absolute;
			border-style: solid;
			border-color: red;
		}

		.outdated-warning input {
			display: none;
		}
	}
	@page {
		margin: 1.5cm 1.1cm;
	}



/******************************************************************************/
/*                             Overflow Control                               */
/******************************************************************************/

	.figure .caption, .sidefigure .caption, figcaption {
		/* in case figure is overlarge, limit caption to 50em */
		max-width: 50rem;
		margin-left: auto;
		margin-right: auto;
	}
	.overlarge {
		/* Magic to create good item positioning:
		  "content column" is 50ems wide at max; less on smaller screens.
		  Extra space (after ToC + content) is empty on the right.

		  1. When item < content column, centers item in column.
		  2. When content < item < available, left-aligns.
		  3. When item > available, fills available + scroll bar.
		*/
		display: grid;
		grid-template-columns: minmax(0, 50em);
	}
	.overlarge > table {
		/* limit preferred width of table */
		max-width: 50em;
		margin-left: auto;
		margin-right: auto;
	}

	@media (min-width: 55em) {
		.overlarge {
			margin-right: calc(13px + 26.5rem - 50vw);
			max-width: none;
		}
	}
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) .overlarge {
			/* 30.5em body padding 50em content area */
			margin-right: calc(40em - 50vw) !important;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) .overlarge {
			/* 4em html margin 30.5em body padding 50em content area */
			margin-right: calc(84.5em - 100vw) !important;
		}
	}

	@media not print {
		.overlarge {
			overflow-x: auto;
			/* See Lea Verou's explanation background-attachment:
			* http://lea.verou.me/2012/04/background-attachment-local/
			*
			background: top left  / 4em 100% linear-gradient(to right,  #ffffff, rgba(255, 255, 255, 0)) local,
						top right / 4em 100% linear-gradient(to left, #ffffff, rgba(255, 255, 255, 0)) local,
						top left  / 1em 100% linear-gradient(to right,  #c3c3c5, rgba(195, 195, 197, 0)) scroll,
						top right / 1em 100% linear-gradient(to left, #c3c3c5, rgba(195, 195, 197, 0)) scroll,
						white;
			background-repeat: no-repeat;
			*/
		}
	}
</style>
<style>
    table, th, td {
      border: 1px solid black;
      border-collapse: collapse;
      vertical-align: top;
    }
    th, td {
      border-left: none;
      border-right: none;
      padding: 0px 10px;
    }
    th {
      text-align: center;
    }

    del { background: #fcc; color: #000; text-decoration: line-through; }
    ins { background: #cfc; color: #000; }
    blockquote .highlight:not(.idl) { background: initial; margin: initial; padding: 0.5em }
    blockquote ul { background: inherit; }
    blockquote code.highlight:not(.idl) { padding: initial; }
    blockquote c-[a] { color: inherit; } /* Keyword.Declaration */
    blockquote c-[b] { color: inherit; } /* Keyword.Type */
    blockquote c-[c] { color: inherit; } /* Comment */
    blockquote c-[d] { color: inherit; } /* Comment.Multiline */
    blockquote c-[e] { color: inherit; } /* Name.Attribute */
    blockquote c-[f] { color: inherit; } /* Name.Tag */
    blockquote c-[g] { color: inherit; } /* Name.Variable */
    blockquote c-[k] { color: inherit; } /* Keyword */
    blockquote c-[l] { color: inherit; } /* Literal */
    blockquote c-[m] { color: inherit; } /* Literal.Number */
    blockquote c-[n] { color: inherit; } /* Name */
    blockquote c-[o] { color: inherit; } /* Operator */
    blockquote c-[p] { color: inherit; } /* Punctuation */
    blockquote c-[s] { color: inherit; } /* Literal.String */
    blockquote c-[t] { color: inherit; } /* Literal.String.Single */
    blockquote c-[u] { color: inherit; } /* Literal.String.Double */
    blockquote c-[cp] { color: inherit; } /* Comment.Preproc */
    blockquote c-[c1] { color: inherit; } /* Comment.Single */
    blockquote c-[cs] { color: inherit; } /* Comment.Special */
    blockquote c-[kc] { color: inherit; } /* Keyword.Constant */
    blockquote c-[kn] { color: inherit; } /* Keyword.Namespace */
    blockquote c-[kp] { color: inherit; } /* Keyword.Pseudo */
    blockquote c-[kr] { color: inherit; } /* Keyword.Reserved */
    blockquote c-[ld] { color: inherit; } /* Literal.Date */
    blockquote c-[nc] { color: inherit; } /* Name.Class */
    blockquote c-[no] { color: inherit; } /* Name.Constant */
    blockquote c-[nd] { color: inherit; } /* Name.Decorator */
    blockquote c-[ni] { color: inherit; } /* Name.Entity */
    blockquote c-[ne] { color: inherit; } /* Name.Exception */
    blockquote c-[nf] { color: inherit; } /* Name.Function */
    blockquote c-[nl] { color: inherit; } /* Name.Label */
    blockquote c-[nn] { color: inherit; } /* Name.Namespace */
    blockquote c-[py] { color: inherit; } /* Name.Property */
    blockquote c-[ow] { color: inherit; } /* Operator.Word */
    blockquote c-[mb] { color: inherit; } /* Literal.Number.Bin */
    blockquote c-[mf] { color: inherit; } /* Literal.Number.Float */
    blockquote c-[mh] { color: inherit; } /* Literal.Number.Hex */
    blockquote c-[mi] { color: inherit; } /* Literal.Number.Integer */
    blockquote c-[mo] { color: inherit; } /* Literal.Number.Oct */
    blockquote c-[sb] { color: inherit; } /* Literal.String.Backtick */
    blockquote c-[sc] { color: inherit; } /* Literal.String.Char */
    blockquote c-[sd] { color: inherit; } /* Literal.String.Doc */
    blockquote c-[se] { color: inherit; } /* Literal.String.Escape */
    blockquote c-[sh] { color: inherit; } /* Literal.String.Heredoc */
    blockquote c-[si] { color: inherit; } /* Literal.String.Interpol */
    blockquote c-[sx] { color: inherit; } /* Literal.String.Other */
    blockquote c-[sr] { color: inherit; } /* Literal.String.Regex */
    blockquote c-[ss] { color: inherit; } /* Literal.String.Symbol */
    blockquote c-[vc] { color: inherit; } /* Name.Variable.Class */
    blockquote c-[vg] { color: inherit; } /* Name.Variable.Global */
    blockquote c-[vi] { color: inherit; } /* Name.Variable.Instance */
    blockquote c-[il] { color: inherit; } /* Literal.Number.Integer.Long */
  </style>
  <meta content="Bikeshed version d765c696b, updated Fri Mar 8 15:58:52 2024 -0800" name="generator">
  <link href="https://wg21.link/P3313R0" rel="canonical">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
  <meta content="f3c22e0846a3ce75c8ed7c8840c23038278eaf69" name="revision">
<style>/* Boilerplate: style-autolinks */
.css.css, .property.property, .descriptor.descriptor {
    color: var(--a-normal-text);
    font-size: inherit;
    font-family: inherit;
}
.css::before, .property::before, .descriptor::before {
    content: "‘";
}
.css::after, .property::after, .descriptor::after {
    content: "’";
}
.property, .descriptor {
    /* Don't wrap property and descriptor names */
    white-space: nowrap;
}
.type { /* CSS value <type> */
    font-style: italic;
}
pre .property::before, pre .property::after {
    content: "";
}
[data-link-type="property"]::before,
[data-link-type="propdesc"]::before,
[data-link-type="descriptor"]::before,
[data-link-type="value"]::before,
[data-link-type="function"]::before,
[data-link-type="at-rule"]::before,
[data-link-type="selector"]::before,
[data-link-type="maybe"]::before {
    content: "‘";
}
[data-link-type="property"]::after,
[data-link-type="propdesc"]::after,
[data-link-type="descriptor"]::after,
[data-link-type="value"]::after,
[data-link-type="function"]::after,
[data-link-type="at-rule"]::after,
[data-link-type="selector"]::after,
[data-link-type="maybe"]::after {
    content: "’";
}

[data-link-type].production::before,
[data-link-type].production::after,
.prod [data-link-type]::before,
.prod [data-link-type]::after {
    content: "";
}

[data-link-type=element],
[data-link-type=element-attr] {
    font-family: Menlo, Consolas, "DejaVu Sans Mono", monospace;
    font-size: .9em;
}
[data-link-type=element]::before { content: "<" }
[data-link-type=element]::after  { content: ">" }

[data-link-type=biblio] {
    white-space: pre;
}

</style>
<style>/* Boilerplate: style-colors */
/* Any --*-text not paired with a --*-bg is assumed to have a transparent bg */
:root {
    color-scheme: light dark;

    --text: black;
    --bg: white;

    --unofficial-watermark: url(https://www.w3.org/StyleSheets/TR/2016/logos/UD-watermark);

    --logo-bg: #1a5e9a;
    --logo-active-bg: #c00;
    --logo-text: white;

    --tocnav-normal-text: #707070;
    --tocnav-normal-bg: var(--bg);
    --tocnav-hover-text: var(--tocnav-normal-text);
    --tocnav-hover-bg: #f8f8f8;
    --tocnav-active-text: #c00;
    --tocnav-active-bg: var(--tocnav-normal-bg);

    --tocsidebar-text: var(--text);
    --tocsidebar-bg: #f7f8f9;
    --tocsidebar-shadow: rgba(0,0,0,.1);
    --tocsidebar-heading-text: hsla(203,20%,40%,.7);

    --toclink-text: var(--text);
    --toclink-underline: #3980b5;
    --toclink-visited-text: var(--toclink-text);
    --toclink-visited-underline: #054572;

    --heading-text: #005a9c;

    --hr-text: var(--text);

    --algo-border: #def;

    --del-text: red;
    --del-bg: transparent;
    --ins-text: #080;
    --ins-bg: transparent;

    --a-normal-text: #034575;
    --a-normal-underline: #bbb;
    --a-visited-text: var(--a-normal-text);
    --a-visited-underline: #707070;
    --a-hover-bg: rgba(75%, 75%, 75%, .25);
    --a-active-text: #c00;
    --a-active-underline: #c00;

    --blockquote-border: silver;
    --blockquote-bg: transparent;
    --blockquote-text: currentcolor;

    --issue-border: #e05252;
    --issue-bg: #fbe9e9;
    --issue-text: var(--text);
    --issueheading-text: #831616;

    --example-border: #e0cb52;
    --example-bg: #fcfaee;
    --example-text: var(--text);
    --exampleheading-text: #574b0f;

    --note-border: #52e052;
    --note-bg: #e9fbe9;
    --note-text: var(--text);
    --noteheading-text: hsl(120, 70%, 30%);
    --notesummary-underline: silver;

    --assertion-border: #aaa;
    --assertion-bg: #eee;
    --assertion-text: black;

    --advisement-border: orange;
    --advisement-bg: #fec;
    --advisement-text: var(--text);
    --advisementheading-text: #b35f00;

    --warning-border: red;
    --warning-bg: hsla(40,100%,50%,0.95);
    --warning-text: var(--text);

    --amendment-border: #330099;
    --amendment-bg: #F5F0FF;
    --amendment-text: var(--text);
    --amendmentheading-text: #220066;

    --def-border: #8ccbf2;
    --def-bg: #def;
    --def-text: var(--text);
    --defrow-border: #bbd7e9;

    --datacell-border: silver;

    --indexinfo-text: #707070;

    --indextable-hover-text: black;
    --indextable-hover-bg: #f7f8f9;

    --outdatedspec-bg: rgba(0, 0, 0, .5);
    --outdatedspec-text: black;
    --outdated-bg: maroon;
    --outdated-text: white;
    --outdated-shadow: red;

    --editedrec-bg: darkorange;
}

</style>
<style>/* Boilerplate: style-counters */
body {
    counter-reset: example figure issue;
}
.issue {
    counter-increment: issue;
}
.issue:not(.no-marker)::before {
    content: "Issue " counter(issue);
}

.example {
    counter-increment: example;
}
.example:not(.no-marker)::before {
    content: "Example " counter(example);
}
.invalid.example:not(.no-marker)::before,
.illegal.example:not(.no-marker)::before {
    content: "Invalid Example" counter(example);
}

figcaption {
    counter-increment: figure;
}
figcaption:not(.no-marker)::before {
    content: "Figure " counter(figure) " ";
}
</style>
<style>/* Boilerplate: style-issues */
a[href].issue-return {
    float: right;
    float: inline-end;
    color: var(--issueheading-text);
    font-weight: bold;
    text-decoration: none;
}
</style>
<style>/* Boilerplate: style-md-lists */
/* This is a weird hack for me not yet following the commonmark spec
   regarding paragraph and lists. */
[data-md] > :first-child {
    margin-top: 0;
}
[data-md] > :last-child {
    margin-bottom: 0;
}
</style>
<style>/* Boilerplate: style-selflinks */
:root {
    --selflink-text: white;
    --selflink-bg: gray;
    --selflink-hover-text: black;
}
.heading, .issue, .note, .example, li, dt {
    position: relative;
}
a.self-link {
    position: absolute;
    top: 0;
    left: calc(-1 * (3.5rem - 26px));
    width: calc(3.5rem - 26px);
    height: 2em;
    text-align: center;
    border: none;
    transition: opacity .2s;
    opacity: .5;
}
a.self-link:hover {
    opacity: 1;
}
.heading > a.self-link {
    font-size: 83%;
}
.example > a.self-link,
.note > a.self-link,
.issue > a.self-link {
    /* These blocks are overflow:auto, so positioning outside
       doesn't work. */
    left: auto;
    right: 0;
}
li > a.self-link {
    left: calc(-1 * (3.5rem - 26px) - 2em);
}
dfn > a.self-link {
    top: auto;
    left: auto;
    opacity: 0;
    width: 1.5em;
    height: 1.5em;
    background: var(--selflink-bg);
    color: var(--selflink-text);
    font-style: normal;
    transition: opacity .2s, background-color .2s, color .2s;
}
dfn:hover > a.self-link {
    opacity: 1;
}
dfn > a.self-link:hover {
    color: var(--selflink-hover-text);
}

a.self-link::before            { content: "¶"; }
.heading > a.self-link::before { content: "§"; }
dfn > a.self-link::before      { content: "#"; }
</style>
<style>/* Boilerplate: style-syntax-highlighting */
code.highlight { padding: .1em; border-radius: .3em; }
pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; }

.highlight:not(.idl) { background: rgba(0, 0, 0, .03); }
c-[a] { color: #990055 } /* Keyword.Declaration */
c-[b] { color: #990055 } /* Keyword.Type */
c-[c] { color: #708090 } /* Comment */
c-[d] { color: #708090 } /* Comment.Multiline */
c-[e] { color: #0077aa } /* Name.Attribute */
c-[f] { color: #669900 } /* Name.Tag */
c-[g] { color: #222222 } /* Name.Variable */
c-[k] { color: #990055 } /* Keyword */
c-[l] { color: #000000 } /* Literal */
c-[m] { color: #000000 } /* Literal.Number */
c-[n] { color: #0077aa } /* Name */
c-[o] { color: #999999 } /* Operator */
c-[p] { color: #999999 } /* Punctuation */
c-[s] { color: #a67f59 } /* Literal.String */
c-[t] { color: #a67f59 } /* Literal.String.Single */
c-[u] { color: #a67f59 } /* Literal.String.Double */
c-[cp] { color: #708090 } /* Comment.Preproc */
c-[c1] { color: #708090 } /* Comment.Single */
c-[cs] { color: #708090 } /* Comment.Special */
c-[kc] { color: #990055 } /* Keyword.Constant */
c-[kn] { color: #990055 } /* Keyword.Namespace */
c-[kp] { color: #990055 } /* Keyword.Pseudo */
c-[kr] { color: #990055 } /* Keyword.Reserved */
c-[ld] { color: #000000 } /* Literal.Date */
c-[nc] { color: #0077aa } /* Name.Class */
c-[no] { color: #0077aa } /* Name.Constant */
c-[nd] { color: #0077aa } /* Name.Decorator */
c-[ni] { color: #0077aa } /* Name.Entity */
c-[ne] { color: #0077aa } /* Name.Exception */
c-[nf] { color: #0077aa } /* Name.Function */
c-[nl] { color: #0077aa } /* Name.Label */
c-[nn] { color: #0077aa } /* Name.Namespace */
c-[py] { color: #0077aa } /* Name.Property */
c-[ow] { color: #999999 } /* Operator.Word */
c-[mb] { color: #000000 } /* Literal.Number.Bin */
c-[mf] { color: #000000 } /* Literal.Number.Float */
c-[mh] { color: #000000 } /* Literal.Number.Hex */
c-[mi] { color: #000000 } /* Literal.Number.Integer */
c-[mo] { color: #000000 } /* Literal.Number.Oct */
c-[sb] { color: #a67f59 } /* Literal.String.Backtick */
c-[sc] { color: #a67f59 } /* Literal.String.Char */
c-[sd] { color: #a67f59 } /* Literal.String.Doc */
c-[se] { color: #a67f59 } /* Literal.String.Escape */
c-[sh] { color: #a67f59 } /* Literal.String.Heredoc */
c-[si] { color: #a67f59 } /* Literal.String.Interpol */
c-[sx] { color: #a67f59 } /* Literal.String.Other */
c-[sr] { color: #a67f59 } /* Literal.String.Regex */
c-[ss] { color: #a67f59 } /* Literal.String.Symbol */
c-[vc] { color: #0077aa } /* Name.Variable.Class */
c-[vg] { color: #0077aa } /* Name.Variable.Global */
c-[vi] { color: #0077aa } /* Name.Variable.Instance */
c-[il] { color: #000000 } /* Literal.Number.Integer.Long */

</style>
 <body class="h-entry">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">P3313R0<br>Impacts of noexept on ARM table based exception metadata</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="profile-and-date"><span class="content">Draft Technical Report, <time class="dt-updated" datetime="2024-05-22">2024-05-22</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="https://wg21.link/P3313R0">https://wg21.link/P3313R0</a>
     <dt class="editor">Author:
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:khalil.estell@sjsu.edu">Khalil Estell</a>
     <dt>Audience:
     <dd>LEWG, LWG
     <dt>Project:
     <dd>ISO/IEC 14882 Programming Languages — C++, ISO/IEC JTC1/SC22/WG21
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <div class="p-summary" data-fill-with="abstract">
   <h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2>
   <p>C++ exceptions serve as the core mechanism for propagating errors
from their detection points to respective handlers. The <code class="highlight"><c- k>noexcept</c-></code> keyword informs the compiler that a function is guaranteed to not
emit exceptions. This assurance is purported to enable compilers to
undertake specific optimizations that can enhance code gen
significantly. This paper examines the influence of the noexcept
keyword on the management of exception metadata and cleanup landing
pads, specifically within the framework of "zero-cost" table-based
Itanium exception handling mechanisms utilized by the ARM Exception
Handling ABI (ARM EHABI). This study shows that the current
strategies for selecting exception metadata for functions by the GCC
toolchain is often suboptimal. The propose improvements include
better selection of exception metadata for functions, grouping
functions with identical exception metadata so they can be merged,
and link-time analysis to determine the implicit noexcept status of
functions. This approach would provide the desired effect of using
noexcept in as many places as possible without the cost of marking
each function as such.</p>
  </div>
  <nav data-fill-with="table-of-contents" id="toc">
   <h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
   <ol class="toc" role="directory">
    <li><a href="#objective"><span class="secno">1</span> <span class="content">Objective</span></a>
    <li>
     <a href="#background"><span class="secno">2</span> <span class="content">Background</span></a>
     <ol class="toc">
      <li><a href="#arm-exception-index"><span class="secno">2.1</span> <span class="content">ARM Exception Index</span></a>
      <li><a href="#arm-unwind-instructions"><span class="secno">2.2</span> <span class="content">ARM Unwind Instructions</span></a>
      <li><a href="#arm-personality-routine"><span class="secno">2.3</span> <span class="content">ARM Personality Routine</span></a>
      <li><a href="#lsda"><span class="secno">2.4</span> <span class="content">GCC Language Specific Data Area (LSDA)</span></a>
      <li><a href="#dtor-landing-pads"><span class="secno">2.5</span> <span class="content">Destructor landing pads</span></a>
      <li><a href="#catch-landing-pads"><span class="secno">2.6</span> <span class="content">Catch landing pads</span></a>
     </ol>
    <li>
     <a href="#methods"><span class="secno">3</span> <span class="content">Methods</span></a>
     <ol class="toc">
      <li><a href="#rank"><span class="secno">3.1</span> <span class="content">Function Exception Rank</span></a>
      <li><a href="#setup"><span class="secno">3.2</span> <span class="content">Experimental Setup</span></a>
     </ol>
    <li>
     <a href="#results"><span class="secno">4</span> <span class="content">Results</span></a>
     <ol class="toc">
      <li><a href="#exhibit-1"><span class="secno">4.1</span> <span class="content">Exhibit 1: Leaf Function</span></a>
      <li><a href="#exhibit-2"><span class="secno">4.2</span> <span class="content">Exhibit 2: Calling only noexcept functions</span></a>
      <li><a href="#exhibit-3"><span class="secno">4.3</span> <span class="content">Exhibit 3: Calling both except and noexcept functions</span></a>
      <li><a href="#exhibit-4"><span class="secno">4.4</span> <span class="content">Exhibit 4: Functions calling only except function</span></a>
      <li><a href="#exhibit-5"><span class="secno">4.5</span> <span class="content">Exhibit 5: Calling only noexcept in try/catch block</span></a>
      <li><a href="#exhibit-6"><span class="secno">4.6</span> <span class="content">Exhibit 6: Calling both except &amp; noexcept in try/catch block</span></a>
      <li><a href="#exhibit-7"><span class="secno">4.7</span> <span class="content">Exhibit 7: Calling only except in try/catch block</span></a>
      <li><a href="#exhibit-8"><span class="secno">4.8</span> <span class="content">Exhibit 8: Leaf class function</span></a>
      <li><a href="#exhibit-9"><span class="secno">4.9</span> <span class="content">Exhibit 9: Calling only noexcept with non-trivially destructable objects present</span></a>
      <li><a href="#exhibit-10"><span class="secno">4.10</span> <span class="content">Exhibit 10: Calling only except with non-trivially destructable objects present</span></a>
      <li><a href="#exhibit-11"><span class="secno">4.11</span> <span class="content">Exhibit 11</span></a>
      <li><a href="#lsda-data"><span class="secno">4.12</span> <span class="content">LSDA Data</span></a>
      <li><a href="#cleanup-landing-pads"><span class="secno">4.13</span> <span class="content">Cleanup Landing Pads</span></a>
     </ol>
    <li>
     <a href="#analysis"><span class="secno">5</span> <span class="content">Analysis</span></a>
     <ol class="toc">
      <li><a href="#leaf-functions"><span class="secno">5.1</span> <span class="content">Leaf Functions</span></a>
      <li><a href="#calling-only-noexcept-functions"><span class="secno">5.2</span> <span class="content">Calling only noexcept functions</span></a>
      <li><a href="#compiler-making-bad-decisions"><span class="secno">5.3</span> <span class="content">Compiler Making Bad Choices</span></a>
      <li><a href="#except-poisoning"><span class="secno">5.4</span> <span class="content">Except Poisoning</span></a>
      <li><a href="#reducing-cleanup-landing-pads"><span class="secno">5.5</span> <span class="content">Reducing Cleanup Landing Pads</span></a>
      <li><a href="#eliminating-try-catch-blocks"><span class="secno">5.6</span> <span class="content">Eliminating Try/Catch Blocks</span></a>
     </ol>
    <li>
     <a href="#conclusion"><span class="secno">6</span> <span class="content">Conclusion</span></a>
     <ol class="toc">
      <li><a href="#improve-selection"><span class="secno">6.1</span> <span class="content">Improve data structure selection</span></a>
      <li><a href="#group-functions"><span class="secno">6.2</span> <span class="content">Group functions with identical exception entries</span></a>
      <li><a href="#deduce-noexcept"><span class="secno">6.3</span> <span class="content">Deduce <code class="highlight"><c- k>noexcept</c-></code> in Functions</span></a>
     </ol>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="objective"><span class="secno">1. </span><span class="content">Objective</span><a class="self-link" href="#objective"></a></h2>
   <p>The primary goal of this study is to evaluate the impact of the noexcept
keyword and the invocation of noexcept functions under various conditions.
Specifically, the research aims to assess how noexcept influences an
application’s binary size through modifications in the exception index,
exception table, and the code generation of the function.</p>
   <p>The following questions will be addressed:</p>
   <ol>
    <li data-md>
     <p>How does labeling a function as noexcept alter its metadata?</p>
    <li data-md>
     <p>What changes occur in a function’s metadata when it calls noexcept
functions?</p>
    <li data-md>
     <p>What implications arise when a try block exclusively calls noexcept
functions?</p>
    <li data-md>
     <p>How does the interaction with noexcept functions affect functions that
manage objects with non-trivial destructors?</p>
   </ol>
   <p>The research will conclude with recommendations for optimizing code generation.</p>
   <h2 class="heading settled" data-level="2" id="background"><span class="secno">2. </span><span class="content">Background</span><a class="self-link" href="#background"></a></h2>
   <p>This paper will focus on the Itanium table based exceptions on ARM as used by
GCC. This choice comes from the author’s experience with this form of exception
handling and this architecture. The insights provided here should be consistent
with other forms of table based exception handling. All data related to the
exception data structures can be found at this link: <a href="https://github.com/ARM-software/abi-aa/blob/main/ehabi32/ehabi32.rst"> ARM-software/abi-aa: ehabi32.rst </a></p>
   <p>The GCC LSDA is an exception to this which can be found in the document <a href="https://itanium-cxx-abi.github.io/cxx-abi/exceptions.pdf"> HP Exception Handling Tables aC++ A.01.15. </a></p>
   <h3 class="heading settled" data-level="2.1" id="arm-exception-index"><span class="secno">2.1. </span><span class="content">ARM Exception Index</span><a class="self-link" href="#arm-exception-index"></a></h3>
   <p>In the ARM Exception Handling ABI, each function involved in exception
unwinding is assigned a unique entry within the exception index. This entry
comprises two 32-bit words:</p>
   <ul>
    <li data-md>
     <p>The first word represents a position-relative, 31-bit offset to the
function’s starting address.</p>
    <li data-md>
     <p>The second word contains either inline unwind instructions or a
position-relative, 31-bit offset to the function’s exception metadata.</p>
   </ul>
<pre class="language-c++ highlight"><c- k>struct</c-> <c- nc>arm_index_entry</c->
<c- p>{</c->
 <c- n>std</c-><c- o>::</c-><c- b>uint32_t</c-> <c- n>function</c-><c- p>;</c->
 <c- n>std</c-><c- o>::</c-><c- b>uint32_t</c-> <c- n>content</c-><c- p>;</c->
<c- p>};</c->
</pre>
   <p>The placement of each entry is relative to the position of its corrisponding
function in the <code class="highlight"><c- p>.</c-><c- n>text</c-></code> section of the program. For example if the <code class="highlight"><c- p>.</c-><c- n>text</c-></code> section starts with function <code class="highlight"><c- n>foo</c-></code>, then function <code class="highlight"><c- n>bar</c-></code>, then function <code class="highlight"><c- n>baz</c-></code>,
then the exception index’s first entries be for <code class="highlight"><c- n>foo</c-></code>, <code class="highlight"><c- n>bar</c-></code> and <code class="highlight"><c- n>baz</c-></code> in that
order. The index MUST be binary searchable using the program counter as
the search term. The goal is to find the index entry associated with the
function that the program counter is currently within the bounds of. This is
checked by performing the following this expression:</p>
<pre class="language-C++ highlight"><c- b>void</c-><c- o>*</c-> <c- n>entry_function_address</c-> <c- o>=</c-> <c- n>to_absolute_address</c-><c- p>(</c-><c- o>&amp;</c-><c- n>entry</c-><c- p>[</c-><c- n>i</c-><c- p>].</c-><c- n>function</c-><c- p>);</c->
<c- b>void</c-><c- o>*</c-> <c- n>next_entry_function_address</c-> <c- o>=</c-> <c- n>to_absolute_address</c-><c- p>(</c-><c- o>&amp;</c-><c- n>entry</c-><c- p>[</c-><c- n>i</c-> <c- o>+</c-> <c- mi>1</c-><c- p>].</c-><c- n>function</c-><c- p>);</c->

<c- k>if</c-> <c- p>(</c-><c- n>entry_function_address</c-> <c- o>&lt;=</c-> <c- n>PC</c-> <c- o>&amp;&amp;</c-> <c- n>PC</c-> <c- o>&lt;</c-> <c- n>next_entry_function_address</c-><c- p>)</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>entry</c-><c- p>[</c-><c- n>i</c-><c- p>];</c->
<c- p>}</c->
</pre>
   <p>The interpretation of the content field is determined by the status of the 31st
bit:</p>
   <ul>
    <li data-md>
     <p>If the 31st bit is set to <code class="highlight"><c- mi>1</c-></code>, the content field holds inline unwind
instructions, accommodating up to three bytes of such instructions.</p>
    <li data-md>
     <p>If the content is exactly <code class="highlight"><c- mh>0x1</c-></code>, it signifies the <code class="highlight"><c- n>CANNOT</c-> <c- n>UNWIND</c-></code> flag,
instructing the exception runtime that unwinding cannot proceed for this
function. The runtime will terminate.</p>
    <li data-md>
     <p>If the 31st bit is <code class="highlight"><c- mi>0</c-></code>, the remaining bits represent a <code class="highlight"><c- n>prel31</c-></code> offset, a
31-bit position-relative offset.</p>
   </ul>
   <p>To compute the absolute address from a <code class="highlight"><c- n>prel31</c-></code> offset, perform the following
steps:</p>
   <ol>
    <li data-md>
     <p>Sign-extend the value from 31 bits to a full 32-bit integer.</p>
    <li data-md>
     <p>Convert the result into a <code class="highlight"><c- b>int32_t</c-></code> to obtain the correct 32-bit signed
offset.</p>
    <li data-md>
     <p>Add this offset to the base address of the content field within the
exception index.</p>
   </ol>
   <p>This process yields the absolute address where the function’s exception
metadata is located.</p>
   <h3 class="heading settled" data-level="2.2" id="arm-unwind-instructions"><span class="secno">2.2. </span><span class="content">ARM Unwind Instructions</span><a class="self-link" href="#arm-unwind-instructions"></a></h3>
   <p>ARM EHABI unwind instructions are compactly encoded in single-byte increments.
In contrast, ARM THUMB2 instructions, utilized by the Cortex M series of
microcontrollers, range from 2 to 4 bytes in size, with a typical ARM
instruction occupying 4 bytes. Consequently, unwind instructions are
significantly smaller, ranging from half to a quarter the size of standard
instructions. This compact size is sufficient for executing all necessary tasks
involved in unwinding a frame, which include:</p>
   <ol>
    <li data-md>
     <p>Deallocating local variables by adjusting the stack pointer.</p>
    <li data-md>
     <p>Restoring general-purpose registers from the stack to the CPU.</p>
    <li data-md>
     <p>Transferring special-purpose register contents from the stack to the
appropriate coprocessor.</p>
   </ol>
   <p>Below are some of the common unwind instructions:</p>
   <table>
    <caption>ARM Unwind Instructions</caption>
    <tbody>
     <tr>
      <th>Instruction (binary)
      <th>Explanation
     <tr>
      <td>00xxxxxx
      <td> vsp = vsp + (xxxxxx &lt; &lt; 2) + 4. Covers range 0x04 - 0x100 inclusive 
     <tr>
      <td>10000000 00000000
      <td>Refuse to unwind (for example, out of a cleanup)
     <tr>
      <td>10100nnn
      <td>Pop r4-r[4+nnn]
     <tr>
      <td>10101nnn
      <td>Pop r4-r[4+nnn], r14
     <tr>
      <td>10110001 0000iiii
      <td>Pop integer registers under mask {r3, r2, r1, r0}
     <tr>
      <td>10110000
      <td>Finish
   </table>
   <h3 class="heading settled" data-level="2.3" id="arm-personality-routine"><span class="secno">2.3. </span><span class="content">ARM Personality Routine</span><a class="self-link" href="#arm-personality-routine"></a></h3>
   <p>There are three forms of ARM personality:</p>
   <ul>
    <li data-md>
     <p><strong>SU16</strong>: short unwind with 16-bit descriptor scope.</p>
    <li data-md>
     <p><strong>LU16</strong>: long unwind with 16-bit descriptor scope.</p>
    <li data-md>
     <p><strong>LU32</strong>: long unwind with 32-bit descriptor scope.</p>
   </ul>
   <p>Personality data descriptors detail regions within a function and the actions to take if the program counter is within one of these regions.</p>
   <p>This document does not cover the ARM specific cleanup and catch descriptors as GCC typically employs a generic, cross-platform, and compressed representation of this data known as the GCC C++ LSDA (Language Specific Data Area).</p>
   <p>No ARM personality routines can exceed 7 bytes of unwind instructions, as detailed in <a href="https://github.com/ARM-software/abi-aa/blob/main/ehabi32/ehabi32.rst">Appendix C of ehabi32.rst</a>.</p>
   <p><strong>SU16 Layout</strong>:</p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- p>[</c-><c- mi>31</c-><c- p>]</c-></code>: Personality indicator. Set to 1 if the data is a personality. Set to 0 if the content is a prel31 offset to additional data.</p>
    <li data-md>
     <p><code class="highlight"><c- p>[</c-><c- mi>30</c-><c- o>:</c-><c- mi>28</c-><c- p>]</c-></code>: Reserved.</p>
    <li data-md>
     <p><code class="highlight"><c- p>[</c-><c- mi>27</c-><c- o>:</c-><c- mi>24</c-><c- p>]</c-></code>: Personality index. For SU16, this is 0.</p>
    <li data-md>
     <p><code class="highlight"><c- p>[</c-><c- mi>23</c-><c- o>:</c-><c- mi>16</c-><c- p>]</c-></code>: Unwind instruction 1.</p>
    <li data-md>
     <p><code class="highlight"><c- p>[</c-><c- mi>15</c-><c- o>:</c-><c- mi>8</c-><c- p>]</c-></code>: Unwind instruction 2.</p>
    <li data-md>
     <p><code class="highlight"><c- p>[</c-><c- mi>7</c-><c- o>:</c-><c- mi>0</c-><c- p>]</c-></code>: Unwind instruction 3.</p>
   </ul>
   <p><strong>LU16 &amp; LU32 Layout</strong>:</p>
   <ul>
    <li data-md>
     <p><strong>First word</strong>:</p>
     <ul>
      <li data-md>
       <p><code class="highlight"><c- p>[</c-><c- mi>31</c-><c- p>]</c-></code>: Personality indicator. Set to 1 if the data is a personality. Set to 0 if the content is a prel31 offset to additional data.</p>
      <li data-md>
       <p><code class="highlight"><c- p>[</c-><c- mi>30</c-><c- o>:</c-><c- mi>28</c-><c- p>]</c-></code>: Reserved.</p>
      <li data-md>
       <p><code class="highlight"><c- p>[</c-><c- mi>27</c-><c- o>:</c-><c- mi>24</c-><c- p>]</c-></code>: Personality index, can be 0, 1, or 2.</p>
      <li data-md>
       <p><code class="highlight"><c- p>[</c-><c- mi>23</c-><c- o>:</c-><c- mi>16</c-><c- p>]</c-></code>: Number of words following this one. Valid values are 1 or 2.</p>
      <li data-md>
       <p><code class="highlight"><c- p>[</c-><c- mi>15</c-><c- o>:</c-><c- mi>8</c-><c- p>]</c-></code>: Unwind instruction 1.</p>
      <li data-md>
       <p><code class="highlight"><c- p>[</c-><c- mi>7</c-><c- o>:</c-><c- mi>0</c-><c- p>]</c-></code>: Unwind instruction 2.</p>
     </ul>
    <li data-md>
     <p><strong>Second word</strong>:</p>
     <ul>
      <li data-md>
       <p><code class="highlight"><c- p>[</c-><c- mi>31</c-><c- o>:</c-><c- mi>24</c-><c- p>]</c-></code>: Unwind instruction 3.</p>
      <li data-md>
       <p><code class="highlight"><c- p>[</c-><c- mi>23</c-><c- o>:</c-><c- mi>16</c-><c- p>]</c-></code>: Unwind instruction 4.</p>
      <li data-md>
       <p><code class="highlight"><c- p>[</c-><c- mi>15</c-><c- o>:</c-><c- mi>8</c-><c- p>]</c-></code>: Unwind instruction 5.</p>
      <li data-md>
       <p><code class="highlight"><c- p>[</c-><c- mi>7</c-><c- o>:</c-><c- mi>0</c-><c- p>]</c-></code>: Unwind instruction 6.</p>
     </ul>
    <li data-md>
     <p><strong>Third word (if applicable)</strong>:</p>
     <ul>
      <li data-md>
       <p><code class="highlight"><c- p>[</c-><c- mi>31</c-><c- o>:</c-><c- mi>24</c-><c- p>]</c-></code>: Unwind instruction 7.</p>
      <li data-md>
       <p><code class="highlight"><c- p>[</c-><c- mi>23</c-><c- o>:</c-><c- mi>16</c-><c- p>]</c-></code>: <code class="highlight"><c- mh>0xB0</c-></code> (finish).</p>
      <li data-md>
       <p><code class="highlight"><c- p>[</c-><c- mi>15</c-><c- o>:</c-><c- mi>8</c-><c- p>]</c-></code>: <code class="highlight"><c- mh>0xB0</c-></code> (finish).</p>
      <li data-md>
       <p><code class="highlight"><c- p>[</c-><c- mi>7</c-><c- o>:</c-><c- mi>0</c-><c- p>]</c-></code>: <code class="highlight"><c- mh>0xB0</c-></code> (finish).</p>
     </ul>
   </ul>
   <h3 class="heading settled" data-level="2.4" id="lsda"><span class="secno">2.4. </span><span class="content">GCC Language Specific Data Area (LSDA)</span><a class="self-link" href="#lsda"></a></h3>
   <p>The ARM Exception Handling ABI (EHABI) for exception handling allows the
integration of non-personality data as exception data, facilitating support for
language-specific exception handling mechanisms. The EHABI permits the
inclusion of custom language-specific data areas within the exception tables, a
feature extensively utilized by GCC to substitute the default
architecture-specific descriptors with its own. This functionality derives from
a feature in the Itanium ABI, enabling various languages to implement their own
functions for unwinding specific call frames. Consequently, not only can C++
exceptions be managed using GCC’s language-specific data area, but other
languages such as Java can also employ this area to control their exceptions.</p>
   <p>For GCC’s LSDA (Language Specific Data Area) format:</p>
   <ol>
    <li data-md>
     <p><strong>Personality Function:</strong> 32-bit value with the MSB set to 0. It contains a <code class="highlight"><c- n>prel31</c-></code> offset to the function’s handler, typically <code class="highlight"><c- n>__gxx_personality_v0</c-></code> in GCC.</p>
    <li data-md>
     <p><strong>Personality Data:</strong> Architecture-specific unwind instructions.</p>
    <li data-md>
     <p><strong>Header:</strong> A variable-length sequence of bytes that delineates where DWARF
information is located, the end of the type table, and the extent of the
call site region. Entries in the DWARF location and type table can be
marked with an omit flag <code class="highlight"><c- mh>0xFF</c-></code> to indicate their absence.</p>
    <li data-md>
     <p><strong>Call Site Table:</strong> Details the regions of the function associated with
try scopes and cleanup. This table specifies the areas of the function that
have particular actions assigned, as well as the location of the landing
pad if an action is taken.</p>
    <li data-md>
     <p><strong>Action Table:</strong> Lists the indices to the types that can be caught for
each call site region and specifies whether cleanup is required.</p>
    <li data-md>
     <p><strong>Type Table:</strong> Contains a unique set of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>type_info</c-></code> addresses for the
types that can be caught within the function.</p>
   </ol>
   <p>To gain a deeper understanding of how these regions are structured, refer to: <a href="https://itanium-cxx-abi.github.io/cxx-abi/exceptions.pdf"> HP Exception Handling Tables aC++ A.01.15. </a></p>
   <h3 class="heading settled" data-level="2.5" id="dtor-landing-pads"><span class="secno">2.5. </span><span class="content">Destructor landing pads</span><a class="self-link" href="#dtor-landing-pads"></a></h3>
   <figure>
<pre class="language-asm highlight">08001140 &lt;<c- nl>dtor:</c->:<c- nf>except_calls_all_except</c-><c- p>()</c->><c- p>:</c->
 8001140:  <c- nf>b500</c->        <c- no>push</c->  <c- p>{</c-><c- no>lr</c-><c- p>}</c->
 8001142:  <c- nf>b085</c->        <c- no>sub</c->  <c- no>sp</c-><c- p>,</c-> <c- mi>#20</c->
 8001144:  <c- nf>f7ff</c-> <c- no>ff76</c->   <c- no>bl</c->  <c- mi>8001034</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c-><c- no>action</c-><c- p>()</c-> <c- p>[</c-><c- no>clone</c-> <c- no>.constprop.0</c-><c- p>]</c->>
 8001148:  <c- nf>f7ff</c-> <c- no>ff74</c->   <c- no>bl</c->  <c- mi>8001034</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c-><c- no>action</c-><c- p>()</c-> <c- p>[</c-><c- no>clone</c-> <c- no>.constprop.0</c-><c- p>]</c->>
 800114<c- nl>c:</c->  <c- nf>f7ff</c-> <c- no>ff72</c->   <c- no>bl</c->  <c- mi>8001034</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c-><c- no>action</c-><c- p>()</c-> <c- p>[</c-><c- no>clone</c-> <c- no>.constprop.0</c-><c- p>]</c->>
 8001150:  <c- nf>f7ff</c-> <c- no>ff70</c->   <c- no>bl</c->  <c- mi>8001034</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c-><c- no>action</c-><c- p>()</c-> <c- p>[</c-><c- no>clone</c-> <c- no>.constprop.0</c-><c- p>]</c->>
 8001154:  <c- nf>f7ff</c-> <c- no>ff6e</c->   <c- no>bl</c->  <c- mi>8001034</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c-><c- no>action</c-><c- p>()</c-> <c- p>[</c-><c- no>clone</c-> <c- no>.constprop.0</c-><c- p>]</c->>
 8001158:  <c- nf>f7ff</c-> <c- no>ff6c</c->   <c- no>bl</c->  <c- mi>8001034</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c-><c- no>action</c-><c- p>()</c-> <c- p>[</c-><c- no>clone</c-> <c- no>.constprop.0</c-><c- p>]</c->>
 800115<c- nl>c:</c->  <c- nf>a803</c->        <c- no>add</c->  <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#12</c->
 800115<c- nl>e:</c->  <c- nf>f7ff</c-> <c- no>ff99</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
 8001162:  <c- nf>a802</c->        <c- no>add</c->  <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#8</c->
 8001164:  <c- nf>f7ff</c-> <c- no>ff96</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
 8001168:  <c- nf>a801</c->        <c- no>add</c->  <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#4</c->
 800116<c- nl>a:</c->  <c- nf>b005</c->        <c- no>add</c->  <c- no>sp</c-><c- p>,</c-> <c- mi>#20</c->
 800116<c- nl>c:</c->  <c- nf>f85d</c-> <c- no>eb04</c->   <c- no>ldr.w</c->  <c- no>lr</c-><c- p>,</c-> <c- p>[</c-><c- no>sp</c-><c- p>],</c-> <c- mi>#4</c->
 8001170:  <c- nf>f7ff</c-> <c- no>bf90</c->   <c- no>b.w</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
 8001174:  <c- nf>e005</c->        <c- no>b.n</c->  <c- mi>8001182</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>except_calls_all_except</c-><c- p>()</c->+<c- mi>0x42</c->>
 8001176:  <c- nf>a803</c->        <c- no>add</c->  <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#12</c->
 8001178:  <c- nf>f7ff</c-> <c- no>ff8c</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
 800117<c- nl>c:</c->  <c- nf>a802</c->        <c- no>add</c->  <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#8</c->
 800117<c- nl>e:</c->  <c- nf>f7ff</c-> <c- no>ff89</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
 8001182:  <c- nf>a801</c->        <c- no>add</c->  <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#4</c->
 8001184:  <c- nf>f7ff</c-> <c- no>ff86</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
 8001188:  <c- nf>f000</c-> <c- no>fb26</c->   <c- no>bl</c->  <c- mh>80017d8</c-> <c- p>&lt;</c-><c- no>__cxa_end_cleanup</c-><c- p>></c->
 800118<c- nl>c:</c->  <c- nf>e7f6</c->        <c- no>b.n</c->  <c- mi>800117</c-><c- no>c</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>except_calls_all_except</c-><c- p>()</c->+<c- mi>0x3c</c->>
 800118<c- nl>e:</c->  <c- nf>bf00</c->        <c- no>nop</c->
</pre>
    <figcaption>Full Function with Destructor Cleanup Region</figcaption>
   </figure>
   <figure>
<pre class="language-asm highlight">8001176:  <c- nf>a803</c->        <c- no>add</c->  <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#12</c->
8001178:  <c- nf>f7ff</c-> <c- no>ff8c</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
800117<c- nl>c:</c->  <c- nf>a802</c->        <c- no>add</c->  <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#8</c->
800117<c- nl>e:</c->  <c- nf>f7ff</c-> <c- no>ff89</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
8001182:  <c- nf>a801</c->        <c- no>add</c->  <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#4</c->
8001184:  <c- nf>f7ff</c-> <c- no>ff86</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
8001188:  <c- nf>f000</c-> <c- no>fb26</c->   <c- no>bl</c->  <c- mh>80017d8</c-> <c- p>&lt;</c-><c- no>__cxa_end_cleanup</c-><c- p>></c->
</pre>
    <figcaption>Isolated Destructor Cleanup Region</figcaption>
   </figure>
   <p>Within this function, there are designated regions that the exception runtime
targets to execute destructors for the current frame. The figures above depict
ARM Thumb2 instructions. These instructions specifically load the address of an
object from the stack into <code class="highlight"><c- n>R0</c-></code>, which acts as the register for the first
parameter in a function call, then the object’s destructor is invoked. This
process is the reverse of the construction sequence of the objects. The Itanium
API utilized to re-enter the exception unwind flow after all necessary
destructors are called is <code class="highlight"><c- n>__cxa_end_cleanup</c-><c- p>()</c-></code>. The point at which the program
counter re-enters the function is influenced by the scope where the exception
propagation originated.</p>
   <h3 class="heading settled" data-level="2.6" id="catch-landing-pads"><span class="secno">2.6. </span><span class="content">Catch landing pads</span><a class="self-link" href="#catch-landing-pads"></a></h3>
   <figure>
<pre class="language-asm highlight">80004<c- nl>fa:</c-> 2901        <c- nf>cmp</c-> <c- no>r1</c-><c- p>,</c-> <c- mi>#1</c->
80004<c- nl>fc:</c-> <c- nf>d001</c->        <c- no>beq.n</c-> <c- mh>8000502</c-> <c- p>&lt;</c-><c- no>main</c-><c- p>+</c-><c- mi>0x18</c-><c- p>></c->
80004<c- nl>fe:</c-> <c- nf>f001</c-> <c- no>f98f</c->   <c- no>bl</c->  <c- mh>8001820</c-> <c- p>&lt;</c-><c- no>__cxa_end_cleanup</c-><c- p>></c->
8000502: <c- nf>f001</c-> <c- no>fa51</c->   <c- no>bl</c->  <c- mh>80019a8</c-> <c- p>&lt;</c-><c- no>__cxa_begin_catch</c-><c- p>></c->
8000506: 4<c- nf>a8f</c->        <c- no>ldr</c-> <c- no>r2</c-><c- p>,</c-> <c- p>[</c-><c- no>pc</c-><c- p>,</c-> <c- mi>#572</c-><c- p>]</c->  @ <c- p>(</c-><c- mh>8000744</c-> <c- p>&lt;</c-><c- no>main</c-><c- p>+</c-><c- mi>0x25a</c-><c- p>>)</c->
8000508: 6<c- nf>c53</c->        <c- no>ldr</c-> <c- no>r3</c-><c- p>,</c-> <c- p>[</c-><c- no>r2</c-><c- p>,</c-> <c- mi>#68</c-><c- p>]</c-> @ <c- mi>0x44</c->
800050<c- nl>a:</c-> 3301        <c- nf>adds</c->  <c- no>r3</c-><c- p>,</c-> <c- mi>#1</c->
800050<c- nl>c:</c-> 6453        <c- nf>str</c-> <c- no>r3</c-><c- p>,</c-> <c- p>[</c-><c- no>r2</c-><c- p>,</c-> <c- mi>#68</c-><c- p>]</c-> @ <c- mi>0x44</c->
800050<c- nl>e:</c-> <c- nf>f001</c-> <c- no>fa8b</c->   <c- no>bl</c->  <c- mh>8001a28</c-> <c- p>&lt;</c-><c- no>__cxa_end_catch</c-><c- p>></c->
</pre>
    <figcaption>Catch landing pad example</figcaption>
   </figure>
   <p>According to Itanium, catch chains should be transformed into switch-case-like
blocks. The unwinder sets <code class="highlight"><c- n>R0</c-></code> with the exception object and <code class="highlight"><c- n>R1</c-></code> with the case
number for the corresponding block. The initial instruction in the assembly
above, comparing <code class="highlight"><c- n>R1</c-></code> with the number 1, determines the path of execution. If
the comparison fails, the sequence proceeds to execute <code class="highlight"><c- n>__cxa_end_cleanup</c-></code>,
continuing the exception propagation. If the comparison is successful, the flow
transitions to <code class="highlight"><c- n>__cxa_begin_catch</c-></code>, executes the catch block, and concludes
with <code class="highlight"><c- n>__cxa_end_catch</c-></code>.</p>
   <h2 class="heading settled" data-level="3" id="methods"><span class="secno">3. </span><span class="content">Methods</span><a class="self-link" href="#methods"></a></h2>
   <p>To fulfill the objectives of this paper, a C++ application will be designed
with a set of functions featuring noexcept and "except" functions in different
usages. "except" in this case as a short hand for non-noexcept function. This
application will self-assess during runtime by examining its exception table
entries and the exception table. The investigation aims to provide insights
into:</p>
   <ul>
    <li data-md>
     <p>Function exception rank</p>
    <li data-md>
     <p>LSDA size and the sizes of its sections (when applicable)</p>
   </ul>
   <h3 class="heading settled" data-level="3.1" id="rank"><span class="secno">3.1. </span><span class="content">Function Exception Rank</span><a class="self-link" href="#rank"></a></h3>
   <p>"function exception rank" refers to a classification scheme for functions based
on their exception metadata’s memory demands. This ranking system identifies:</p>
   <ol>
    <li data-md>
     <p><strong>No index entry</strong>: Indicates absence of an index table entry for functions
where the compiler ascertains no exception propagation, utilizing zero
memory.</p>
    <li data-md>
     <p><strong>Inlined index data:</strong> Involves direct inlining of unwind information into
the index entry, negating the need for additional exception table space.
This configuration employs an SU16 personality, consistently occupying 8
bytes due to ARM exception index ABI specifications.</p>
    <li data-md>
     <p><strong>Table unwind instructions:</strong> Applies when unwind details cannot be
condensed into the 4-byte content section of the index, requiring 16 to 20
bytes—8 bytes for the index and 8 to 12 bytes for unwind instructions.</p>
    <li data-md>
     <p><strong>GCC LSDA:</strong> Positioned in the exception table, this data structure,
although memory-intensive, effectively manages try/catch blocks and cleanup
areas, starting at 28 bytes and increasing based on complexity.</p>
   </ol>
   <h3 class="heading settled" data-level="3.2" id="setup"><span class="secno">3.2. </span><span class="content">Experimental Setup</span><a class="self-link" href="#setup"></a></h3>
   <ul>
    <li data-md>
     <p><strong>Toolchain</strong>: Arm Gnu Toolchain 12.3</p>
    <li data-md>
     <p><strong>Instruction Set</strong>: ARM THUMB 2</p>
    <li data-md>
     <p><strong>Target Processor</strong>: Cortex M3 (executed on an stm32f103c8 microcontroller)</p>
    <li data-md>
     <p><strong>libc</strong>: picolibc (to re-enable exception handling in the compiler)</p>
    <li data-md>
     <p><strong>Project URL</strong>: <a href="https://github.com/kammce/cpp-papers/tree/main/noexcept">https://github.com/kammce/cpp-papers/tree/main/noexcept</a></p>
    <li data-md>
     <p><strong>Debugging Technology</strong>: <code class="highlight"><c- n>PyOCD</c-></code> + <code class="highlight"><c- n>ST</c-><c- o>-</c-><c- n>Link</c-> <c- n>V2</c-></code></p>
   </ul>
   <p>All C++ functions in or used by an exhibit in the results section will be
marked as <code class="highlight"><c- p>[[</c-><c- n>gnu</c-><c- o>::</c-><c- n>noinline</c-><c- p>]]</c-></code> in order to prevent the compiler from inlining
the functions.</p>
   <p>The <code class="highlight"><c- o>/</c-><c- k>noexcept</c-></code> directory in the repo provides a README file explaining how to
build and execute the code.</p>
   <h2 class="heading settled" data-level="4" id="results"><span class="secno">4. </span><span class="content">Results</span><a class="self-link" href="#results"></a></h2>
   <p>All functions with the prefix "noexcept" are noexcept functions.</p>
   <p>There exists an array called side_effect which is a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>array</c-></code> of <code class="highlight"><c- k>volatile</c-> <c- n>std</c-><c- o>::</c-><c- b>uint32_t</c-></code> numbers. This is to prevent the compiler from deducing
the results of functions and garbage collecting most of the code.</p>
   <p>Any exhibits with multiple rankings has been found to change their ranking
depending on the position of the function in the code. For example, if the
compiler sees that function A is inlined noexcept and the next function in the
code (or symbol table) is function B and it has the same inline noexcept entry,
the compiler will merge the two enteries and make a single entry for function
B’s. Because the next entry will be the next function with differing exception
content, the when the binary search is performed to find the required entry,
anything between function B and the next entry will have the same information.
During unwinding, the selected entry will be function A if function B ever has
an exception propagation reaches it. The behavior is the same, regardless.
There maybe exhibits where this behavior also exists but was not tested in this
paper.</p>
   <h3 class="heading settled" data-level="4.1" id="exhibit-1"><span class="secno">4.1. </span><span class="content">Exhibit 1: Leaf Function</span><a class="self-link" href="#exhibit-1"></a></h3>
   <p>Definition of <code class="highlight"><c- n>my_struct_t</c-></code>:</p>
<pre class="language-C++ highlight"><c- k>struct</c-> <c- nc>my_struct_t</c->
<c- p>{</c->
  <c- b>int</c-> <c- n>a</c-><c- p>;</c->
  <c- b>int</c-> <c- n>b</c-><c- p>;</c->
  <c- b>int</c-> <c- n>c</c-><c- p>;</c->
<c- p>};</c->
</pre>
   <figure>
    <table>
     <tbody>
      <tr>
       <td>
<pre class="language-C++ highlight"><c- b>void</c-> <c- nf>noexcept_initialize</c-><c- p>(</c-><c- n>my_struct_t</c-><c- o>&amp;</c-> <c- n>my_struct</c-><c- p>)</c-> <c- n>noexcept</c->
<c- p>{</c->
    <c- n>my_struct</c-><c- p>.</c-><c- n>a</c-> <c- o>=</c-> <c- mi>17</c-><c- p>;</c->
    <c- n>my_struct</c-><c- p>.</c-><c- n>b</c-> <c- o>=</c-> <c- mi>22</c-><c- p>;</c->
    <c- n>my_struct</c-><c- p>.</c-><c- n>c</c-> <c- o>=</c-> <c- mi>33</c-><c- p>;</c->
<c- p>}</c->
</pre>
       <td>
<pre class="language-C++ highlight"><c- b>void</c-> <c- nf>initialize</c-><c- p>(</c-><c- n>my_struct_t</c-><c- o>&amp;</c-> <c- n>my_struct</c-><c- p>)</c->
<c- p>{</c->
    <c- n>my_struct</c-><c- p>.</c-><c- n>a</c-> <c- o>=</c-> <c- mi>5</c-><c- p>;</c->
    <c- n>my_struct</c-><c- p>.</c-><c- n>b</c-> <c- o>=</c-> <c- mi>15</c-><c- p>;</c->
    <c- n>my_struct</c-><c- p>.</c-><c- n>c</c-> <c- o>=</c-> <c- mi>15</c-><c- p>;</c->
<c- p>}</c->
</pre>
      <tr>
       <td> Rank 1: no entry <br> Rank 2: inlined noexcept 
       <td> Rank 1: no entry <br> Rank 2: inlined noexcept 
    </table>
    <figcaption>Leaf Functions</figcaption>
   </figure>
   <h3 class="heading settled" data-level="4.2" id="exhibit-2"><span class="secno">4.2. </span><span class="content">Exhibit 2: Calling only noexcept functions</span><a class="self-link" href="#exhibit-2"></a></h3>
   <figure>
    <table>
     <tbody>
      <tr>
       <td>
<pre class="language-C++ highlight"><c- b>void</c->
<c- nf>noexcept_calls_all_noexcept</c-><c- p>()</c-> <c- n>noexcept</c->
<c- p>{</c->
    <c- n>noexcept_bar</c-><c- p>();</c->
    <c- n>noexcept_baz</c-><c- p>();</c->
    <c- n>noexcept_qaz</c-><c- p>();</c->
<c- p>}</c->
</pre>
       <td>
<pre class="language-C++ highlight"><c- b>void</c->
<c- nf>except_calls_all_noexcept</c-><c- p>()</c->
<c- p>{</c->
    <c- n>noexcept_bar</c-><c- p>();</c->
    <c- n>noexcept_baz</c-><c- p>();</c->
    <c- n>noexcept_qaz</c-><c- p>();</c->
<c- p>}</c->
</pre>
      <tr>
       <td> Rank 2: inlined noexcept 
       <td> Rank 1: No entry
        Rank 2: inlined noexcept 
    </table>
    <figcaption>Calling all noexcept functions</figcaption>
   </figure>
   <h3 class="heading settled" data-level="4.3" id="exhibit-3"><span class="secno">4.3. </span><span class="content">Exhibit 3: Calling both except and noexcept functions</span><a class="self-link" href="#exhibit-3"></a></h3>
   <figure>
    <table>
     <tbody>
      <tr>
       <td>
<pre class="language-C++ highlight"><c- b>void</c->
<c- nf>noexcept_calls_mixed</c-><c- p>()</c-> <c- n>noexcept</c->
<c- p>{</c->
    <c- n>noexcept_bar</c-><c- p>();</c->
    <c- n>baz</c-><c- p>();</c->
    <c- n>noexcept_qaz</c-><c- p>();</c->
<c- p>}</c->
</pre>
       <td>
<pre class="language-C++ highlight"><c- b>void</c->
<c- nf>except_calls_mixed</c-><c- p>()</c->
<c- p>{</c->
    <c- n>noexcept_bar</c-><c- p>();</c->
    <c- n>baz</c-><c- p>();</c->
    <c- n>noexcept_qaz</c-><c- p>();</c->
<c- p>}</c->
</pre>
      <tr>
       <td> Rank 4: GCC LSDA 
       <td> Rank 3: Table Personality 
    </table>
    <figcaption>Calling a mix of except &amp; noexcept functions</figcaption>
   </figure>
   <h3 class="heading settled" data-level="4.4" id="exhibit-4"><span class="secno">4.4. </span><span class="content">Exhibit 4: Functions calling only except function</span><a class="self-link" href="#exhibit-4"></a></h3>
   <figure>
    <table>
     <tbody>
      <tr>
       <td>
<pre class="language-C++ highlight"><c- b>void</c->
<c- nf>noexcept_calls_all_except</c-><c- p>()</c-> <c- n>noexcept</c->
<c- p>{</c->
    <c- n>bar</c-><c- p>();</c->
    <c- n>baz</c-><c- p>();</c->
    <c- n>qaz</c-><c- p>();</c->
<c- p>}</c->
</pre>
       <td>
<pre class="language-C++ highlight"><c- b>void</c->
<c- nf>except_calls_all_except</c-><c- p>()</c->
<c- p>{</c->
    <c- n>bar</c-><c- p>();</c->
    <c- n>baz</c-><c- p>();</c->
    <c- n>qaz</c-><c- p>();</c->
<c- p>}</c->
</pre>
      <tr>
       <td> Rank 4: GCC LSDA 
       <td> Rank 3: Table Personality 
    </table>
    <figcaption>Calling only except functions</figcaption>
   </figure>
   <h3 class="heading settled" data-level="4.5" id="exhibit-5"><span class="secno">4.5. </span><span class="content">Exhibit 5: Calling only noexcept in try/catch block</span><a class="self-link" href="#exhibit-5"></a></h3>
   <figure>
    <table>
     <tbody>
      <tr>
       <td>
<pre class="language-C++ highlight"><c- b>void</c->
<c- nf>noexcept_calls_all_noexcept_in_try_catch</c-><c- p>()</c-> <c- n>noexcept</c->
<c- p>{</c->
    <c- n>try</c-> <c- p>{</c->
        <c- n>noexcept_bar</c-><c- p>();</c->
        <c- n>noexcept_baz</c-><c- p>();</c->
    <c- p>}</c-> <c- n>catch</c-> <c- p>(...)</c-> <c- p>{</c->
        <c- n>side_effect</c-><c- p>[</c-><c- mi>9</c-><c- p>]</c-> <c- o>=</c-> <c- n>side_effect</c-><c- p>[</c-><c- mi>9</c-><c- p>]</c-> <c- o>+</c-> <c- mi>1</c-><c- p>;</c->
    <c- p>}</c->
<c- p>}</c->
</pre>
       <td>
<pre class="language-C++ highlight"><c- b>void</c->
<c- nf>except_calls_all_noexcept_in_try_catch</c-><c- p>()</c->
<c- p>{</c->
    <c- n>try</c-> <c- p>{</c->
        <c- n>noexcept_bar</c-><c- p>();</c->
        <c- n>noexcept_baz</c-><c- p>();</c->
    <c- p>}</c-> <c- n>catch</c-> <c- p>(...)</c-> <c- p>{</c->
        <c- n>side_effect</c-><c- p>[</c-><c- mi>9</c-><c- p>]</c-> <c- o>=</c-> <c- n>side_effect</c-><c- p>[</c-><c- mi>9</c-><c- p>]</c-> <c- o>+</c-> <c- mi>1</c-><c- p>;</c->
    <c- p>}</c->
<c- p>}</c->
</pre>
      <tr>
       <td> Rank 2: Inlined noexcept 
       <td> Rank 1: No entry 
    </table>
    <figcaption>Calling only noexcept in try scope</figcaption>
   </figure>
   <h3 class="heading settled" data-level="4.6" id="exhibit-6"><span class="secno">4.6. </span><span class="content">Exhibit 6: Calling both except &amp; noexcept in try/catch block</span><a class="self-link" href="#exhibit-6"></a></h3>
   <figure>
    <table>
     <tbody>
      <tr>
       <td>
<pre class="language-C++ highlight"><c- b>void</c->
<c- nf>noexcept_calls_mixed_in_try_catch</c-><c- p>()</c-> <c- n>noexcept</c->
<c- p>{</c->
    <c- n>try</c-> <c- p>{</c->
        <c- n>bar</c-><c- p>();</c->
        <c- n>noexcept_baz</c-><c- p>();</c->
    <c- p>}</c-> <c- n>catch</c-> <c- p>(...)</c-> <c- p>{</c->
        <c- n>side_effect</c-><c- p>[</c-><c- mi>15</c-><c- p>]</c-> <c- o>=</c-> <c- n>side_effect</c-><c- p>[</c-><c- mi>15</c-><c- p>]</c-> <c- o>+</c-> <c- mi>1</c-><c- p>;</c->
    <c- p>}</c->
<c- p>}</c->
</pre>
       <td>
<pre class="language-C++ highlight"><c- b>void</c->
<c- nf>except_calling_mixed_in_try_catch</c-><c- p>()</c->
<c- p>{</c->
    <c- n>try</c-> <c- p>{</c->
        <c- n>bar</c-><c- p>();</c->
        <c- n>noexcept_baz</c-><c- p>();</c->
    <c- p>}</c-> <c- n>catch</c-> <c- p>(...)</c-> <c- p>{</c->
        <c- n>side_effect</c-><c- p>[</c-><c- mi>22</c-><c- p>]</c-> <c- o>=</c-> <c- n>side_effect</c-><c- p>[</c-><c- mi>22</c-><c- p>]</c-> <c- o>+</c-> <c- mi>1</c-><c- p>;</c->
    <c- p>}</c->
<c- p>}</c->
</pre>
      <tr>
       <td> Rank 4: GCC LSDA 
       <td> Rank 4: GCC LSDA 
    </table>
    <figcaption>Calling mixed function types in a try scope</figcaption>
   </figure>
   <h3 class="heading settled" data-level="4.7" id="exhibit-7"><span class="secno">4.7. </span><span class="content">Exhibit 7: Calling only except in try/catch block</span><a class="self-link" href="#exhibit-7"></a></h3>
   <figure>
    <table>
     <tbody>
      <tr>
       <td>
<pre class="language-C++ highlight"><c- b>void</c->
<c- nf>noexcept_calls_except_in_try_catch</c-><c- p>()</c-> <c- n>noexcept</c->
<c- p>{</c->
    <c- n>try</c-> <c- p>{</c->
        <c- n>bar</c-><c- p>();</c->
        <c- n>baz</c-><c- p>();</c->
    <c- p>}</c-> <c- n>catch</c-> <c- p>(...)</c-> <c- p>{</c->
        <c- n>side_effect</c-><c- p>[</c-><c- mi>17</c-><c- p>]</c-> <c- o>=</c-> <c- n>side_effect</c-><c- p>[</c-><c- mi>17</c-><c- p>]</c-> <c- o>+</c-> <c- mi>1</c-><c- p>;</c->
    <c- p>}</c->
<c- p>}</c->
</pre>
       <td>
<pre class="language-C++ highlight"><c- b>void</c->
<c- nf>except_calls_except_in_try_catch</c-><c- p>()</c->
<c- p>{</c->
    <c- n>try</c-> <c- p>{</c->
        <c- n>bar</c-><c- p>();</c->
        <c- n>baz</c-><c- p>();</c->
    <c- p>}</c-> <c- n>catch</c-> <c- p>(...)</c-> <c- p>{</c->
        <c- n>side_effect</c-><c- p>[</c-><c- mi>8</c-><c- p>]</c-> <c- o>=</c-> <c- n>side_effect</c-><c- p>[</c-><c- mi>8</c-><c- p>]</c-> <c- o>+</c-> <c- mi>1</c-><c- p>;</c->
    <c- p>}</c->
<c- p>}</c->
</pre>
      <tr>
       <td> Rank 4: GCC LSDA 
       <td> Rank 4: GCC LSDA 
    </table>
    <figcaption>Calling only except functions in a try scope</figcaption>
   </figure>
   <h3 class="heading settled" data-level="4.8" id="exhibit-8"><span class="secno">4.8. </span><span class="content">Exhibit 8: Leaf class function</span><a class="self-link" href="#exhibit-8"></a></h3>
   <figure>
    <table>
     <tbody>
      <tr>
       <td>
<pre class="language-C++ highlight"><c- n>my_class</c-><c- o>::</c-><c- n>state_t</c->
<c- nf>my_class::noexcept_state</c-><c- p>()</c-> <c- n>noexcept</c->
<c- p>{</c->
    <c- k>return</c-> <c- n>m_state</c-><c- p>;</c->
<c- p>}</c->
</pre>
       <td>
<pre class="language-C++ highlight"><c- n>my_class</c-><c- o>::</c-><c- n>state_t</c->
<c- nf>my_class::state</c-><c- p>()</c->
<c- p>{</c->
    <c- k>return</c-> <c- n>m_state</c-><c- p>;</c->
<c- p>}</c->
</pre>
      <tr>
       <td> Rank 1: No entry 
       <td> Rank 1: No entry 
    </table>
    <figcaption>Typical function getter</figcaption>
   </figure>
   <h3 class="heading settled" data-level="4.9" id="exhibit-9"><span class="secno">4.9. </span><span class="content">Exhibit 9: Calling only noexcept with non-trivially destructable objects present</span><a class="self-link" href="#exhibit-9"></a></h3>
   <figure>
    <table>
     <tbody>
      <tr>
       <td>
<pre class="language-C++ highlight"><c- n>namespace</c-> <c- n>dtor</c-> <c- p>{</c->
<c- b>void</c->
<c- nf>noexcept_calls_all_noexcept</c-><c- p>()</c-> <c- n>noexcept</c->
<c- p>{</c->
    <c- n>non_trivial_dtor</c-> <c- n>obj1</c-><c- p>;</c->
    <c- n>obj1</c-><c- p>.</c-><c- n>noexcept_action</c-><c- p>();</c->
    <c- n>non_trivial_dtor</c-> <c- n>obj2</c-><c- p>;</c->
    <c- n>obj1</c-><c- p>.</c-><c- n>noexcept_action</c-><c- p>();</c->
    <c- n>obj2</c-><c- p>.</c-><c- n>noexcept_action</c-><c- p>();</c->
    <c- n>non_trivial_dtor</c-> <c- n>obj3</c-><c- p>;</c->
    <c- n>obj1</c-><c- p>.</c-><c- n>noexcept_action</c-><c- p>();</c->
    <c- n>obj2</c-><c- p>.</c-><c- n>noexcept_action</c-><c- p>();</c->
    <c- n>obj3</c-><c- p>.</c-><c- n>noexcept_action</c-><c- p>();</c->
<c- p>}</c->
<c- p>}</c->
</pre>
       <td>
<pre class="language-C++ highlight"><c- n>namespace</c-> <c- n>dtor</c-> <c- p>{</c->
<c- b>void</c->
<c- nf>except_calls_all_noexcept</c-><c- p>()</c->
<c- p>{</c->
    <c- n>non_trivial_dtor</c-> <c- n>obj1</c-><c- p>;</c->
    <c- n>obj1</c-><c- p>.</c-><c- n>noexcept_action</c-><c- p>();</c->
    <c- n>non_trivial_dtor</c-> <c- n>obj2</c-><c- p>;</c->
    <c- n>obj1</c-><c- p>.</c-><c- n>noexcept_action</c-><c- p>();</c->
    <c- n>obj2</c-><c- p>.</c-><c- n>noexcept_action</c-><c- p>();</c->
    <c- n>non_trivial_dtor</c-> <c- n>obj3</c-><c- p>;</c->
    <c- n>obj1</c-><c- p>.</c-><c- n>noexcept_action</c-><c- p>();</c->
    <c- n>obj2</c-><c- p>.</c-><c- n>noexcept_action</c-><c- p>();</c->
    <c- n>obj3</c-><c- p>.</c-><c- n>noexcept_action</c-><c- p>();</c->
<c- p>}</c->
<c- p>}</c->
</pre>
      <tr>
       <td> Rank 1: No Entry 
       <td> Rank 1: No Entry 
    </table>
    <figcaption> Calling only noexcept functions with non-trivially destructable objects
  present. </figcaption>
   </figure>
   <h3 class="heading settled" data-level="4.10" id="exhibit-10"><span class="secno">4.10. </span><span class="content">Exhibit 10: Calling only except with non-trivially destructable objects present</span><a class="self-link" href="#exhibit-10"></a></h3>
   <figure>
    <table>
     <tbody>
      <tr>
       <td>
<pre class="language-C++ highlight"><c- n>namespace</c-> <c- n>dtor</c-> <c- p>{</c->
<c- b>void</c->
<c- nf>noexcept_calls_all_except</c-><c- p>()</c-> <c- n>noexcept</c->
<c- p>{</c->
    <c- n>non_trivial_dtor</c-> <c- n>obj1</c-><c- p>;</c->
    <c- n>obj1</c-><c- p>.</c-><c- n>action</c-><c- p>();</c->
    <c- n>non_trivial_dtor</c-> <c- n>obj2</c-><c- p>;</c->
    <c- n>obj1</c-><c- p>.</c-><c- n>action</c-><c- p>();</c->
    <c- n>obj2</c-><c- p>.</c-><c- n>action</c-><c- p>();</c->
    <c- n>non_trivial_dtor</c-> <c- n>obj3</c-><c- p>;</c->
    <c- n>obj1</c-><c- p>.</c-><c- n>action</c-><c- p>();</c->
    <c- n>obj2</c-><c- p>.</c-><c- n>action</c-><c- p>();</c->
    <c- n>obj3</c-><c- p>.</c-><c- n>action</c-><c- p>();</c->
<c- p>}</c->
<c- p>}</c->
</pre>
       <td>
<pre class="language-C++ highlight"><c- n>namespace</c-> <c- n>dtor</c-> <c- p>{</c->
<c- b>void</c->
<c- nf>except_calls_all_except</c-><c- p>()</c->
<c- p>{</c->
    <c- n>non_trivial_dtor</c-> <c- n>obj1</c-><c- p>;</c->
    <c- n>obj1</c-><c- p>.</c-><c- n>action</c-><c- p>();</c->
    <c- n>non_trivial_dtor</c-> <c- n>obj2</c-><c- p>;</c->
    <c- n>obj1</c-><c- p>.</c-><c- n>action</c-><c- p>();</c->
    <c- n>obj2</c-><c- p>.</c-><c- n>action</c-><c- p>();</c->
    <c- n>non_trivial_dtor</c-> <c- n>obj3</c-><c- p>;</c->
    <c- n>obj1</c-><c- p>.</c-><c- n>action</c-><c- p>();</c->
    <c- n>obj2</c-><c- p>.</c-><c- n>action</c-><c- p>();</c->
    <c- n>obj3</c-><c- p>.</c-><c- n>action</c-><c- p>();</c->
<c- p>}</c->
<c- p>}</c->
</pre>
      <tr>
       <td> Rank 4: GCC LSDA 
       <td> Rank 4: GCC LSDA 
    </table>
    <figcaption> Calling only except with non-trivially destructable objects present </figcaption>
   </figure>
   <h3 class="heading settled" data-level="4.11" id="exhibit-11"><span class="secno">4.11. </span><span class="content">Exhibit 11</span><a class="self-link" href="#exhibit-11"></a></h3>
   <p>In this experiment, the function that is noexcept is moved down for each of the
following functions. So in experiment 2, the first class function call to obj1
will become <code class="highlight"><c- n>noexcept_action</c-><c- p>()</c-></code> and the second call after constructing obj2
will be <code class="highlight"><c- n>action</c-><c- p>()</c-></code>. All other calls will be <code class="highlight"><c- n>noexcept_action</c-><c- p>()</c-></code>.</p>
<pre class="language-C++ highlight"><c- n>namespace</c-> <c- n>dtor</c-> <c- p>{</c->
<c- b>void</c->
<c- nf>noexcept_calls_experiment1</c-><c- p>()</c-> <c- n>noexcept</c->
<c- p>{</c->
    <c- n>non_trivial_dtor</c-> <c- n>obj1</c-><c- p>;</c->
    <c- n>obj1</c-><c- p>.</c-><c- n>action</c-><c- p>();</c-> <c- c1>// experiment 1: calls action()</c->
    <c- n>non_trivial_dtor</c-> <c- n>obj2</c-><c- p>;</c->
    <c- n>obj1</c-><c- p>.</c-><c- n>noexcept_action</c-><c- p>();</c-> <c- c1>// experiment 2: calls action()</c->
    <c- n>obj2</c-><c- p>.</c-><c- n>noexcept_action</c-><c- p>();</c-> <c- c1>// experiment 3: calls action()</c->
    <c- n>non_trivial_dtor</c-> <c- n>obj3</c-><c- p>;</c->
    <c- n>obj1</c-><c- p>.</c-><c- n>noexcept_action</c-><c- p>();</c-> <c- c1>// experiment 4: calls action()</c->
    <c- n>obj2</c-><c- p>.</c-><c- n>noexcept_action</c-><c- p>();</c-> <c- c1>// experiment 5: calls action()</c->
    <c- n>obj3</c-><c- p>.</c-><c- n>noexcept_action</c-><c- p>();</c-> <c- c1>// experiment 6: calls action()</c->
<c- p>}</c->
<c- p>}</c->
</pre>
   <ul>
    <li data-md>
     <p>Noexcept:</p>
     <ul>
      <li data-md>
       <p>Experiment 1-7: Rank 4 GCC LSDA</p>
     </ul>
    <li data-md>
     <p>Except:</p>
     <ul>
      <li data-md>
       <p>Experiment 1-7: Rank 4 GCC LSDA</p>
     </ul>
   </ul>
   <h3 class="heading settled" data-level="4.12" id="lsda-data"><span class="secno">4.12. </span><span class="content">LSDA Data</span><a class="self-link" href="#lsda-data"></a></h3>
   <p>The data below is sorted by total size. The total size only accounts for the
size of the memory in the LSDA region. It does not include the exception index
entry nor the cleanup region in the function.</p>
   <table border="1">
    <thead>
     <tr>
      <th>Function Name
      <th>Total Size
      <th>Max Action Offset
      <th>Type Table Offset
      <th>Call Site count
      <th>Call Site size
      <th>Action Table count
      <th>Action Table size
      <th>Type Table count
      <th>Type Table size
    <tbody>
     <tr>
      <td>except_calling_mixed_in_try_catch
      <td>34
      <td>1
      <td>17
      <td>2
      <td>8
      <td>3
      <td>6
      <td>1
      <td>4
     <tr>
      <td>except_calls_except_in_try_catch
      <td>34
      <td>1
      <td>17
      <td>2
      <td>8
      <td>3
      <td>6
      <td>1
      <td>4
     <tr>
      <td>dtor::except_calls_all_except
      <td>32
      <td>0
      <td>0
      <td>4
      <td>16
      <td>0
      <td>0
      <td>0
      <td>0
     <tr>
      <td>dtor::except_calls_experiment7
      <td>32
      <td>0
      <td>0
      <td>4
      <td>16
      <td>0
      <td>0
      <td>0
      <td>0
     <tr>
      <td>noexcept_calls_mixed_in_try_catch
      <td>30
      <td>1
      <td>13
      <td>1
      <td>4
      <td>3
      <td>6
      <td>1
      <td>4
     <tr>
      <td>noexcept_calls_except_in_try_catch
      <td>30
      <td>1
      <td>13
      <td>1
      <td>4
      <td>3
      <td>6
      <td>1
      <td>4
     <tr>
      <td>dtor::except_calls_experiment1
      <td>24
      <td>0
      <td>0
      <td>2
      <td>8
      <td>0
      <td>0
      <td>0
      <td>0
     <tr>
      <td>dtor::except_calls_experiment2
      <td>24
      <td>0
      <td>0
      <td>2
      <td>8
      <td>0
      <td>0
      <td>0
      <td>0
     <tr>
      <td>dtor::except_calls_experiment3
      <td>24
      <td>0
      <td>0
      <td>2
      <td>8
      <td>0
      <td>0
      <td>0
      <td>0
     <tr>
      <td>dtor::except_calls_experiment4
      <td>24
      <td>0
      <td>0
      <td>2
      <td>8
      <td>0
      <td>0
      <td>0
      <td>0
     <tr>
      <td>dtor::except_calls_experiment5
      <td>24
      <td>0
      <td>0
      <td>2
      <td>8
      <td>0
      <td>0
      <td>0
      <td>0
     <tr>
      <td>dtor::except_calls_experiment6
      <td>24
      <td>0
      <td>0
      <td>2
      <td>8
      <td>0
      <td>0
      <td>0
      <td>0
     <tr>
      <td>noexcept_calls_mixed
      <td>16
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
     <tr>
      <td>noexcept_calls_all_except
      <td>16
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
     <tr>
      <td>dtor::noexcept_calls_all_except
      <td>16
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
     <tr>
      <td>dtor::noexcept_calls_experiment1
      <td>16
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
     <tr>
      <td>dtor::noexcept_calls_experiment2
      <td>16
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
     <tr>
      <td>dtor::noexcept_calls_experiment3
      <td>16
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
     <tr>
      <td>dtor::noexcept_calls_experiment4
      <td>16
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
     <tr>
      <td>dtor::noexcept_calls_experiment5
      <td>16
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
     <tr>
      <td>dtor::noexcept_calls_experiment6
      <td>16
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
     <tr>
      <td>dtor::noexcept_calls_experiment7
      <td>16
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
      <td>0
   </table>
   <h3 class="heading settled" data-level="4.13" id="cleanup-landing-pads"><span class="secno">4.13. </span><span class="content">Cleanup Landing Pads</span><a class="self-link" href="#cleanup-landing-pads"></a></h3>
   <div class="note" role="note">
    <p>None of the <code class="highlight"><c- k>noexcept</c-></code> functions had cleanup landing pads.</p>
   </div>
<pre class="language-asm highlight">08001140 &lt;<c- nl>dtor:</c->:<c- nf>except_calls_all_except</c-><c- p>()</c->><c- p>:</c->
<c- c1># ...</c->
8001176: <c- nf>a803</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#12</c->
8001178: <c- nf>f7ff</c-> <c- no>ff8c</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
800117<c- nl>c:</c-> <c- nf>a802</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#8</c->
800117<c- nl>e:</c-> <c- nf>f7ff</c-> <c- no>ff89</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
8001182: <c- nf>a801</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#4</c->
8001184: <c- nf>f7ff</c-> <c- no>ff86</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
8001188: <c- nf>f000</c-> <c- no>fb26</c->   <c- no>bl</c->  <c- mh>80017d8</c-> <c- p>&lt;</c-><c- no>__cxa_end_cleanup</c-><c- p>></c->
</pre>
<pre class="language-asm highlight">080012<c- nf>fc</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>except_calls_experiment1</c-><c- p>()</c->><c- p>:</c->
<c- c1># ...</c->
8001330: <c- nf>a801</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#4</c->
8001332: <c- nf>f7ff</c-> <c- no>feaf</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
8001336: <c- nf>f000</c-> <c- no>fa4f</c->   <c- no>bl</c->  <c- mh>80017d8</c-> <c- p>&lt;</c-><c- no>__cxa_end_cleanup</c-><c- p>></c->
</pre>
<pre class="language-asm highlight">0800133<c- nf>c</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>except_calls_experiment2</c-><c- p>()</c->><c- p>:</c->
<c- c1># ...</c->
8001370: <c- nf>a802</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#8</c->
8001372: <c- nf>f7ff</c-> <c- no>fe8f</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
8001376: <c- nf>a801</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#4</c->
8001378: <c- nf>f7ff</c-> <c- no>fe8c</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
800137<c- nl>c:</c-> <c- nf>f000</c-> <c- no>fa2c</c->   <c- no>bl</c->  <c- mh>80017d8</c-> <c- p>&lt;</c-><c- no>__cxa_end_cleanup</c-><c- p>></c->
</pre>
<pre class="language-asm highlight">08001380 &lt;<c- nl>dtor:</c->:<c- nf>except_calls_experiment3</c-><c- p>()</c->><c- p>:</c->
<c- c1># ...</c->
80013<c- nl>b4:</c-> <c- nf>a802</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#8</c->
80013<c- nl>b6:</c-> <c- nf>f7ff</c-> <c- no>fe6d</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
80013<c- nl>ba:</c-> <c- nf>a801</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#4</c->
80013<c- nl>bc:</c-> <c- nf>f7ff</c-> <c- no>fe6a</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
80013<c- nl>c0:</c-> <c- nf>f000</c-> <c- no>fa0a</c->   <c- no>bl</c->  <c- mh>80017d8</c-> <c- p>&lt;</c-><c- no>__cxa_end_cleanup</c-><c- p>></c->
</pre>
<pre class="language-asm highlight">080013<c- nf>c4</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>except_calls_experiment4</c-><c- p>()</c->><c- p>:</c->
<c- c1># ...</c->
80013<c- nl>f8:</c-> <c- nf>a803</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#12</c->
80013<c- nl>fa:</c-> <c- nf>f7ff</c-> <c- no>fe4b</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
80013<c- nl>fe:</c-> <c- nf>a802</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#8</c->
8001400: <c- nf>f7ff</c-> <c- no>fe48</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
8001404: <c- nf>a801</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#4</c->
8001406: <c- nf>f7ff</c-> <c- no>fe45</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
800140<c- nl>a:</c-> <c- nf>f000</c-> <c- no>f9e5</c->   <c- no>bl</c->  <c- mh>80017d8</c-> <c- p>&lt;</c-><c- no>__cxa_end_cleanup</c-><c- p>></c->
</pre>
<pre class="language-asm highlight">08001410 &lt;<c- nl>dtor:</c->:<c- nf>except_calls_experiment5</c-><c- p>()</c->><c- p>:</c->
<c- c1># ...</c->
8001444: <c- nf>a803</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#12</c->
8001446: <c- nf>f7ff</c-> <c- no>fe25</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
800144<c- nl>a:</c-> <c- nf>a802</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#8</c->
800144<c- nl>c:</c-> <c- nf>f7ff</c-> <c- no>fe22</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
8001450: <c- nf>a801</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#4</c->
8001452: <c- nf>f7ff</c-> <c- no>fe1f</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
8001456: <c- nf>f000</c-> <c- no>f9bf</c->   <c- no>bl</c->  <c- mh>80017d8</c-> <c- p>&lt;</c-><c- no>__cxa_end_cleanup</c-><c- p>></c->
</pre>
<pre class="language-asm highlight">0800145<c- nf>c</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>except_calls_experiment6</c-><c- p>()</c->><c- p>:</c->
<c- c1># ...</c->
8001490: <c- nf>a803</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#12</c->
8001492: <c- nf>f7ff</c-> <c- no>fdff</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
8001496: <c- nf>a802</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#8</c->
8001498: <c- nf>f7ff</c-> <c- no>fdfc</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
800149<c- nl>c:</c-> <c- nf>a801</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#4</c->
800149<c- nl>e:</c-> <c- nf>f7ff</c-> <c- no>fdf9</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
80014<c- nl>a2:</c-> <c- nf>f000</c-> <c- no>f999</c->   <c- no>bl</c->  <c- mh>80017d8</c-> <c- p>&lt;</c-><c- no>__cxa_end_cleanup</c-><c- p>></c->
</pre>
<pre class="language-asm highlight">080014<c- nf>a8</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>except_calls_experiment7</c-><c- p>()</c->><c- p>:</c->
<c- c1># ...</c->
80014<c- nl>de:</c-> <c- nf>a803</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#12</c->
80014<c- nl>e0:</c-> <c- nf>f7ff</c-> <c- no>fdd8</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
80014<c- nl>e4:</c-> <c- nf>a802</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#8</c->
80014<c- nl>e6:</c-> <c- nf>f7ff</c-> <c- no>fdd5</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
80014<c- nl>ea:</c-> <c- nf>a801</c->        <c- no>add</c-> <c- no>r0</c-><c- p>,</c-> <c- no>sp</c-><c- p>,</c-> <c- mi>#4</c->
80014<c- nl>ec:</c-> <c- nf>f7ff</c-> <c- no>fdd2</c->   <c- no>bl</c->  <c- mi>8001094</c-> &lt;<c- no>dtor</c-><c- p>::</c-><c- no>non_trivial_dtor</c-><c- p>::</c->~<c- no>non_trivial_dtor</c-><c- p>()</c->>
80014<c- nl>f0:</c-> <c- nf>f000</c-> <c- no>f972</c->   <c- no>bl</c->  <c- mh>80017d8</c-> <c- p>&lt;</c-><c- no>__cxa_end_cleanup</c-><c- p>></c->
</pre>
   <p>The cleanup regions follow a very consistent pattern. Set <code class="highlight"><c- n>R0</c-></code> to the address
of the object to be destroyed and call the destructor. It takes 2 bytes to load <code class="highlight"><c- n>R0</c-></code>, 4 bytes to call a destructor, and 4 bytes to call <code class="highlight"><c- n>__cxa_end_cleanup</c-></code>.
So the total cost in bytes for the number of objects that must be destroyed in
a frame is <code class="highlight"><c- n>size</c-><c- p>(</c-><c- n>n</c-><c- p>)</c-> <c- o>=</c-> <c- mi>4</c-> <c- o>+</c-> <c- mi>6</c-><c- n>n</c-></code>.</p>
   <h2 class="heading settled" data-level="5" id="analysis"><span class="secno">5. </span><span class="content">Analysis</span><a class="self-link" href="#analysis"></a></h2>
   <h3 class="heading settled" data-level="5.1" id="leaf-functions"><span class="secno">5.1. </span><span class="content">Leaf Functions</span><a class="self-link" href="#leaf-functions"></a></h3>
   <p>Consider <a href="#exhibit-1">§ 4.1 Exhibit 1: Leaf Function</a> and <a href="#exhibit-8">§ 4.8 Exhibit 8: Leaf class function</a>. Both exhibits contain leaf
functions. <a href="#exhibit-8">§ 4.8 Exhibit 8: Leaf class function</a> has no exception index entry. This makes sense since
the function does not throw an exception and does not call any other functions.
There is no possibility that an exception will ever propagate from such a
function. Thus their index entries can be omitted from the table.</p>
   <p>If the functions of <a href="#exhibit-1">§ 4.1 Exhibit 1: Leaf Function</a> are moved between other functions that have
exception index entries, then they will both get exception index entries with
an inlined noexcept marker. GCC is able to deduce that the <code class="highlight"><c- n>initialize</c-></code> functions never calls other functions and thus is de facto noexcept. But
rather than eliminate the entry, the compiler decides to provide an entry for
both.</p>
   <p>These entries do not need to exist and being able to omit them would free up 8
bytes of space per function. This seems like an opportunity for the compiler to
be improved.</p>
   <h3 class="heading settled" data-level="5.2" id="calling-only-noexcept-functions"><span class="secno">5.2. </span><span class="content">Calling only noexcept functions</span><a class="self-link" href="#calling-only-noexcept-functions"></a></h3>
   <p><a href="#exhibit-2">§ 4.2 Exhibit 2: Calling only noexcept functions</a> contains functions calling only noexcept functions. The noexcept
function in this exhibit gets a rank 4 whereas the except function just gets a
rank 3. In both cases, the compiler should have opted to omit the exception
data entirely. These functions are never reachable via exception propagation.</p>
   <p>The compiler has chosen data structures for these two functions way above what
is necessary for them.</p>
   <h3 class="heading settled" data-level="5.3" id="compiler-making-bad-decisions"><span class="secno">5.3. </span><span class="content">Compiler Making Bad Choices</span><a class="self-link" href="#compiler-making-bad-decisions"></a></h3>
   <p><a href="#exhibit-3">§ 4.3 Exhibit 3: Calling both except and noexcept functions</a> and <a href="#exhibit-4">§ 4.4 Exhibit 4: Functions calling only except function</a> match each other in their rankings. Both
either use an except function or a mix of except and noexcept functions. None
of the functions require cleanup or have any catch blocks.</p>
   <p>Yet, GCC chooses a mostly empty LSDA data structure for the noexcept functions.
An inline noexcept flag would have worked as there is no objects to cleanup or
catch blocks to consider.</p>
   <p>The except functions have enough unwind instructions to warrant their data
being placed in the exception table. Meaning these very simple functions were
not unwindable in a 3 unwind instructions.</p>
<pre class="language-asm highlight">080015<c- nf>a8</c-> &lt;<c- no>except_calls_all_except</c-><c- p>()</c->><c- p>:</c->
80015<c- nl>a8:</c-> <c- nf>b508</c->        <c- no>push</c->  <c- p>{</c-><c- no>r3</c-><c- p>,</c-> <c- no>lr</c-><c- p>}</c->
80015<c- nl>aa:</c-> <c- nf>f7ff</c-> <c- no>fcdd</c->   <c- no>bl</c->  <c- mi>8000</c-><c- no>f68</c-> &lt;<c- no>bar</c-><c- p>()</c->>
80015<c- nl>ae:</c-> <c- nf>f7ff</c-> <c- no>fcfb</c->   <c- no>bl</c->  <c- mi>8000</c-><c- no>fa8</c-> &lt;<c- no>baz</c-><c- p>()</c->>
80015<c- nl>b2:</c-> <c- nf>e8bd</c-> <c- mi>4008</c->   <c- no>ldmia.w</c-> <c- no>sp</c-><c- p>!,</c-> <c- p>{</c-><c- no>r3</c-><c- p>,</c-> <c- no>lr</c-><c- p>}</c->
80015<c- nl>b6:</c-> <c- nf>f7ff</c-> <c- no>bd17</c->   <c- no>b.w</c-> <c- mi>8000</c-><c- no>fe8</c-> &lt;<c- no>qaz</c-><c- p>()</c->>
80015<c- nl>ba:</c-> <c- nf>bf00</c->        <c- no>nop</c->
</pre>
   <p>This function disassembly does two strange things. It pushes <code class="highlight"><c- n>R3</c-></code> onto the
stack which requires 2 bytes of unwind information to be unwound. It also
performs some stack manipulation before calling the last function. If the
compiler had chosen to use <code class="highlight"><c- n>R4</c-></code> rather than <code class="highlight"><c- n>R3</c-></code> and called the <code class="highlight"><c- n>qaz</c-><c- p>()</c-></code> function normally, then only a single byte of instruction memory would be
required to unwind it, specifically <code class="highlight"><c- mb>0b10101000</c-></code> (<code class="highlight"><c- mh>0xA8</c-></code>). This optimization
could bring the exception rank to rank 2.</p>
   <p>All of these functions should have rank 2, inlined noexcept flag and inline
personality.</p>
   <h3 class="heading settled" data-level="5.4" id="except-poisoning"><span class="secno">5.4. </span><span class="content">Except Poisoning</span><a class="self-link" href="#except-poisoning"></a></h3>
   <p>A consistent observation across all exhibits is that calling a single except
function, elevates the function’s rank to at least rank 2, accompanied by the
necessary cleanup landing pads.</p>
   <p>Thus, the advantages of calling <code class="highlight"><c- k>noexcept</c-></code> functions are negated by the
introduction of any except function.</p>
   <h3 class="heading settled" data-level="5.5" id="reducing-cleanup-landing-pads"><span class="secno">5.5. </span><span class="content">Reducing Cleanup Landing Pads</span><a class="self-link" href="#reducing-cleanup-landing-pads"></a></h3>
   <p>Marking a C++ function as <code class="highlight"><c- k>noexcept</c-></code> completely eliminates the cleanup regions.
Such regions become unreachable, making their inclusion unnecessary.</p>
   <p>However, in an except functions, if the only functions called after the
construction of an object are <code class="highlight"><c- k>noexcept</c-></code> functions, then the destructor call
for that object can be omitted from the cleanup landing area. Calling a single
except function afterwards will result in the object’s destructor call being
added to the cleanup landing pad.</p>
   <h3 class="heading settled" data-level="5.6" id="eliminating-try-catch-blocks"><span class="secno">5.6. </span><span class="content">Eliminating Try/Catch Blocks</span><a class="self-link" href="#eliminating-try-catch-blocks"></a></h3>
   <p><a href="#exhibit-5">§ 4.5 Exhibit 5: Calling only noexcept in try/catch block</a> presents an interesting scenario where the compiler assigns a
rank of 2 to the <code class="highlight"><c- k>noexcept</c-></code> function and a rank of 1 to the except function.
The rank of 1 may be influenced by the placement of the functions within the
source code. Nevertheless, the compiler opted for suitably minimal options for
the code. The disassembly for both is minimal and excludes any record of the
catch blocks. The compiler successfully determined that the catch blocks were
unreachable and omitted them.</p>
<pre class="language-asm highlight">080015<c- nf>bc</c-> &lt;<c- no>noexcept_calls_all_noexcept_in_try_catch</c-><c- p>()</c->><c- p>:</c->
80015<c- nl>bc:</c-> <c- nf>b508</c->        <c- no>push</c->  <c- p>{</c-><c- no>r3</c-><c- p>,</c-> <c- no>lr</c-><c- p>}</c->
80015<c- nl>be:</c-> <c- nf>f7ff</c-> <c- no>fc9d</c->   <c- no>bl</c->  <c- mi>8000</c-><c- no>efc</c-> &lt;<c- no>noexcept_bar</c-><c- p>()</c->>
80015<c- nl>c2:</c-> <c- nf>e8bd</c-> <c- mi>4008</c->   <c- no>ldmia.w</c-> <c- no>sp</c-><c- p>!,</c-> <c- p>{</c-><c- no>r3</c-><c- p>,</c-> <c- no>lr</c-><c- p>}</c->
80015<c- nl>c6:</c-> <c- nf>f7ff</c-> <c- no>bcab</c->   <c- no>b.w</c-> <c- mi>8000</c-><c- no>f20</c-> &lt;<c- no>noexcept_baz</c-><c- p>()</c->>
80015<c- nl>ca:</c-> <c- nf>bf00</c->        <c- no>nop</c->
</pre>
<pre class="language-asm highlight">080015<c- nf>cc</c-> &lt;<c- no>except_calls_all_noexcept_in_try_catch</c-><c- p>()</c->><c- p>:</c->
80015<c- nl>cc:</c-> <c- nf>b508</c->        <c- no>push</c->  <c- p>{</c-><c- no>r3</c-><c- p>,</c-> <c- no>lr</c-><c- p>}</c->
80015<c- nl>ce:</c-> <c- nf>f7ff</c-> <c- no>fc95</c->   <c- no>bl</c->  <c- mi>8000</c-><c- no>efc</c-> &lt;<c- no>noexcept_bar</c-><c- p>()</c->>
80015<c- nl>d2:</c-> <c- nf>e8bd</c-> <c- mi>4008</c->   <c- no>ldmia.w</c-> <c- no>sp</c-><c- p>!,</c-> <c- p>{</c-><c- no>r3</c-><c- p>,</c-> <c- no>lr</c-><c- p>}</c->
80015<c- nl>d6:</c-> <c- nf>f7ff</c-> <c- no>bca3</c->   <c- no>b.w</c-> <c- mi>8000</c-><c- no>f20</c-> &lt;<c- no>noexcept_baz</c-><c- p>()</c->>
80015<c- nl>da:</c-> <c- nf>bf00</c->        <c- no>nop</c->
</pre>
   <p>Note that calling all noexcept functions within a try block is a code smell.
It begs the question of, "what exception were you expecting to catch from these
APIs?"</p>
   <p><a href="#exhibit-6">§ 4.6 Exhibit 6: Calling both except &amp; noexcept in try/catch block</a> and <a href="#exhibit-7">§ 4.7 Exhibit 7: Calling only except in try/catch block</a> both show no difference introduced by
labeling the functions as noexcept, due to the except poisoning mentioned
earlier. You can see the disassembly of <code class="highlight"><c- n>noexcept_calls_mixed_in_try_catch</c-></code> with the Itanium catch block APIs <code class="highlight"><c- n>__cxa_begin_catch</c-></code> and <code class="highlight"><c- n>__cxa_end_catch</c-></code>.</p>
<pre class="language-asm highlight">080015<c- nf>dc</c-> &lt;<c- no>noexcept_calls_mixed_in_try_catch</c-><c- p>()</c->><c- p>:</c->
80015<c- nl>dc:</c-> <c- nf>b508</c->        <c- no>push</c->  <c- p>{</c-><c- no>r3</c-><c- p>,</c-> <c- no>lr</c-><c- p>}</c->
80015<c- nl>de:</c-> <c- nf>f7ff</c-> <c- no>fcc3</c->   <c- no>bl</c->  <c- mi>8000</c-><c- no>f68</c-> &lt;<c- no>bar</c-><c- p>()</c->>
80015<c- nl>e2:</c-> <c- nf>e8bd</c-> <c- mi>4008</c->   <c- no>ldmia.w</c-> <c- no>sp</c-><c- p>!,</c-> <c- p>{</c-><c- no>r3</c-><c- p>,</c-> <c- no>lr</c-><c- p>}</c->
80015<c- nl>e6:</c-> <c- nf>f7ff</c-> <c- no>bc9b</c->   <c- no>b.w</c-> <c- mi>8000</c-><c- no>f20</c-> &lt;<c- no>noexcept_baz</c-><c- p>()</c->>
80015<c- nl>ea:</c-> <c- nf>f000</c-> <c- no>f9b9</c->   <c- no>bl</c->  <c- mh>8001960</c-> <c- p>&lt;</c-><c- no>__cxa_begin_catch</c-><c- p>></c->
80015<c- nl>ee:</c-> 4<c- nf>a03</c->        <c- no>ldr</c-> <c- no>r2</c-><c- p>,</c-> <c- p>[</c-><c- no>pc</c-><c- p>,</c-> <c- mi>#12</c-><c- p>]</c->
80015<c- nl>f0:</c-> 6<c- nf>bd3</c->        <c- no>ldr</c-> <c- no>r3</c-><c- p>,</c-> <c- p>[</c-><c- no>r2</c-><c- p>,</c-> <c- mi>#60</c-><c- p>]</c-> @ <c- mi>0x3c</c->
80015<c- nl>f2:</c-> 3301        <c- nf>adds</c->  <c- no>r3</c-><c- p>,</c-> <c- mi>#1</c->
80015<c- nl>f4:</c-> 63<c- nf>d3</c->        <c- no>str</c-> <c- no>r3</c-><c- p>,</c-> <c- p>[</c-><c- no>r2</c-><c- p>,</c-> <c- mi>#60</c-><c- p>]</c-> @ <c- mi>0x3c</c->
80015<c- nl>f6:</c-> <c- nf>f000</c-> <c- no>f9f3</c->   <c- no>bl</c->  <c- mh>80019e0</c-> <c- p>&lt;</c-><c- no>__cxa_end_catch</c-><c- p>></c->
80015<c- nl>fa:</c-> <c- nf>bd08</c->        <c- no>pop</c-> <c- p>{</c-><c- no>r3</c-><c- p>,</c-> <c- no>pc</c-><c- p>}</c->
80015<c- nl>fc:</c-> 20000<c- nf>b60</c->  <c- no>.word</c-> <c- mi>0x20000b60</c->
</pre>
   <h2 class="heading settled" data-level="6" id="conclusion"><span class="secno">6. </span><span class="content">Conclusion</span><a class="self-link" href="#conclusion"></a></h2>
   <p>Noexcept can be useful in cases such as where a strong exception guarantee is
needed. But in terms of code gen, it’s a mixed bag. In general, adding the <code class="highlight"><c- k>noexcept</c-></code> to a function reduces its code gen.</p>
   <p>The cases where GCC was able to optimize the code gen would be:</p>
   <ol>
    <li data-md>
     <p>Removing destructor landing pads</p>
    <li data-md>
     <p>Removing dead catch blocks</p>
   </ol>
   <p>Removing destructor landing pads is useful, but making a function noexcept for
this purpose seems a bit extreme.</p>
   <p>Noexcept also tends to cause GCC to change what would have been 0 bytes of
exception data into requiring a mostly empty LSDA section and exception index
entry.</p>
   <p>The benefits of noexcept only occur as an edge case. An edge case that breaks
once a single function capable of throwing an exception is called within that
function.</p>
   <p>We want to give the compiler as much information and guarantees as possible to
coax it into generating more efficient code for us, but do we really need <code class="highlight"><c- k>noexcept</c-></code> for that?</p>
   <p>Given the data in this study, I believe the right choice is to look for
improvements in toolchains. Changes to code should not be necessary because
there are many of the improvements to code gen that can be performed without
the need to change source code.</p>
   <h3 class="heading settled" data-level="6.1" id="improve-selection"><span class="secno">6.1. </span><span class="content">Improve data structure selection</span><a class="self-link" href="#improve-selection"></a></h3>
   <p>The exception rank for noexcept functions could be optimized to choosen lower
rank options. Here are a few checks that could be performed:</p>
   <ol>
    <li data-md>
     <p>Is it a leaf? No entry</p>
    <li data-md>
     <p>Calls only noexcept? No entry</p>
    <li data-md>
     <p>Is noexcept and does not have a try block? inline noexcept</p>
    <li data-md>
     <p>Is noexcept with non-trivial destructors? inline noexcept</p>
   </ol>
   <h3 class="heading settled" data-level="6.2" id="group-functions"><span class="secno">6.2. </span><span class="content">Group functions with identical exception entries</span><a class="self-link" href="#group-functions"></a></h3>
   <p>GCC merges identical exception entries when the functions are right next to
each other in the source code. The linker could generate a first run of the
exception index, collect all of the identical entries, and then group all
functions with identical entries. Now all of the identical entires can be
merged into a single entry, reducing the size of the table.</p>
   <h3 class="heading settled" data-level="6.3" id="deduce-noexcept"><span class="secno">6.3. </span><span class="content">Deduce <code class="highlight"><c- k>noexcept</c-></code> in Functions</span><a class="self-link" href="#deduce-noexcept"></a></h3>
   <p>Many functions operate as <code class="highlight"><c- k>noexcept</c-></code> without being explicitly marked as such;
they call other functions, and down the entire call graph, no function ever
throws an exception. Instead of manually marking such functions as <code class="highlight"><c- k>noexcept</c-></code>,
it is feasible for the linker to determine whether a function is exception
propagating. GCC, for instance, can already generate a call graph using the <code class="highlight"><c- o>-</c-><c- n>fcallgraph</c-><c- o>-</c-><c- n>info</c-></code> flag. The proposed idea is for the linker to evaluate all
functions it has full assembly information of and determine which ones throw
exceptions. Using this information, the linker could identify functions that
could never throw an exception and automatically mark all them <code class="highlight"><c- k>noexcept</c-></code>. Leaf
functions would receive an implicit <code class="highlight"><c- k>noexcept</c-></code> marking. Similarly, if an except
functions calls a set of functions that have implicitly marked <code class="highlight"><c- k>noexcept</c-></code> then
that function could also be marked as implicitely noexcept. For APIs external
to an application, such as those in a shared library, the linker would have to
assume that any function not explicitly marked as <code class="highlight"><c- k>noexcept</c-></code> does propagate
exceptions.</p>
   <p>Implementing such a mechanism would allow a C++ application to benefit from
marking many of its non-throwing functions as <code class="highlight"><c- k>noexcept</c-></code>, while retaining the
flexibility to adjust this designation as needed in the future.</p>
  </main>
<script>
(function() {
  "use strict";
  var collapseSidebarText = '<span aria-hidden="true">←</span> '
                          + '<span>Collapse Sidebar</span>';
  var expandSidebarText   = '<span aria-hidden="true">→</span> '
                          + '<span>Pop Out Sidebar</span>';
  var tocJumpText         = '<span aria-hidden="true">↑</span> '
                          + '<span>Jump to Table of Contents</span>';

  var sidebarMedia = window.matchMedia('screen and (min-width: 78em)');
  var autoToggle   = function(e){ toggleSidebar(e.matches) };
  if(sidebarMedia.addListener) {
    sidebarMedia.addListener(autoToggle);
  }

  function toggleSidebar(on) {
    if (on == undefined) {
      on = !document.body.classList.contains('toc-sidebar');
    }

    /* Don't scroll to compensate for the ToC if we're above it already. */
    var headY = 0;
    var head = document.querySelector('.head');
    if (head) {
      // terrible approx of "top of ToC"
      headY += head.offsetTop + head.offsetHeight;
    }
    var skipScroll = window.scrollY < headY;

    var toggle = document.getElementById('toc-toggle');
    var tocNav = document.getElementById('toc');
    if (on) {
      var tocHeight = tocNav.offsetHeight;
      document.body.classList.add('toc-sidebar');
      document.body.classList.remove('toc-inline');
      toggle.innerHTML = collapseSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, 0 - tocHeight);
      }
      tocNav.focus();
      sidebarMedia.addListener(autoToggle); // auto-collapse when out of room
    }
    else {
      document.body.classList.add('toc-inline');
      document.body.classList.remove('toc-sidebar');
      toggle.innerHTML = expandSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, tocNav.offsetHeight);
      }
      if (toggle.matches(':hover')) {
        /* Unfocus button when not using keyboard navigation,
           because I don't know where else to send the focus. */
        toggle.blur();
      }
    }
  }

  function createSidebarToggle() {
    /* Create the sidebar toggle in JS; it shouldn't exist when JS is off. */
    var toggle = document.createElement('a');
      /* This should probably be a button, but appearance isn't standards-track.*/
    toggle.id = 'toc-toggle';
    toggle.class = 'toc-toggle';
    toggle.href = '#toc';
    toggle.innerHTML = collapseSidebarText;

    sidebarMedia.addListener(autoToggle);
    var toggler = function(e) {
      e.preventDefault();
      sidebarMedia.removeListener(autoToggle); // persist explicit off states
      toggleSidebar();
      return false;
    }
    toggle.addEventListener('click', toggler, false);


    /* Get <nav id=toc-nav>, or make it if we don't have one. */
    var tocNav = document.getElementById('toc-nav');
    if (!tocNav) {
      tocNav = document.createElement('p');
      tocNav.id = 'toc-nav';
      /* Prepend for better keyboard navigation */
      document.body.insertBefore(tocNav, document.body.firstChild);
    }
    /* While we're at it, make sure we have a Jump to Toc link. */
    var tocJump = document.getElementById('toc-jump');
    if (!tocJump) {
      tocJump = document.createElement('a');
      tocJump.id = 'toc-jump';
      tocJump.href = '#toc';
      tocJump.innerHTML = tocJumpText;
      tocNav.appendChild(tocJump);
    }

    tocNav.appendChild(toggle);
  }

  var toc = document.getElementById('toc');
  if (toc) {
    createSidebarToggle();
    toggleSidebar(sidebarMedia.matches);

    /* If the sidebar has been manually opened and is currently overlaying the text
       (window too small for the MQ to add the margin to body),
       then auto-close the sidebar once you click on something in there. */
    toc.addEventListener('click', function(e) {
      if(e.target.tagName.toLowerCase() == "a" && document.body.classList.contains('toc-sidebar') && !sidebarMedia.matches) {
        toggleSidebar(false);
      }
    }, false);
  }
  else {
    console.warn("Can't find Table of Contents. Please use <nav id='toc'> around the ToC.");
  }

  /* Wrap tables in case they overflow */
  var tables = document.querySelectorAll(':not(.overlarge) > table.data, :not(.overlarge) > table.index');
  var numTables = tables.length;
  for (var i = 0; i < numTables; i++) {
    var table = tables[i];
    var wrapper = document.createElement('div');
    wrapper.className = 'overlarge';
    table.parentNode.insertBefore(wrapper, table);
    wrapper.appendChild(table);
  }

})();
</script>