<!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>P3358R0: SARIF for Structured Diagnostics</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/P3358R0" rel="canonical">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
  <meta content="e731dd4b3cf754f99300145e3373b85fe873a0f9" name="revision">
  <meta content="dark light" name="color-scheme">
<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;
}

@media (prefers-color-scheme: dark) {
    :root {
        --selflink-text: black;
        --selflink-bg: silver;
        --selflink-hover-text: white;
    }
}
</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;
}

@media (prefers-color-scheme: dark) {
    :root {
        --text: #ddd;
        --bg: black;

        --unofficial-watermark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400'%3E%3Cg fill='%23100808' transform='translate(200 200) rotate(-45) translate(-200 -200)' stroke='%23100808' stroke-width='3'%3E%3Ctext x='50%25' y='220' style='font: bold 70px sans-serif; text-anchor: middle; letter-spacing: 6px;'%3EUNOFFICIAL%3C/text%3E%3Ctext x='50%25' y='305' style='font: bold 70px sans-serif; text-anchor: middle; letter-spacing: 6px;'%3EDRAFT%3C/text%3E%3C/g%3E%3C/svg%3E");

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

        --tocnav-normal-text: #999;
        --tocnav-normal-bg: var(--bg);
        --tocnav-hover-text: var(--tocnav-normal-text);
        --tocnav-hover-bg: #080808;
        --tocnav-active-text: #f44;
        --tocnav-active-bg: var(--tocnav-normal-bg);

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

        --toclink-text: var(--text);
        --toclink-underline: #6af;
        --toclink-visited-text: var(--toclink-text);
        --toclink-visited-underline: #054572;

        --heading-text: #8af;

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

        --algo-border: #456;

        --del-text: #f44;
        --del-bg: transparent;
        --ins-text: #4a4;
        --ins-bg: transparent;

        --a-normal-text: #6af;
        --a-normal-underline: #555;
        --a-visited-text: var(--a-normal-text);
        --a-visited-underline: var(--a-normal-underline);
        --a-hover-bg: rgba(25%, 25%, 25%, .2);
        --a-active-text: #f44;
        --a-active-underline: var(--a-active-text);

        --borderedblock-bg: rgba(255, 255, 255, .05);

        --blockquote-border: silver;
        --blockquote-bg: var(--borderedblock-bg);
        --blockquote-text: currentcolor;

        --issue-border: #e05252;
        --issue-bg: var(--borderedblock-bg);
        --issue-text: var(--text);
        --issueheading-text: hsl(0deg, 70%, 70%);

        --example-border: hsl(50deg, 90%, 60%);
        --example-bg: var(--borderedblock-bg);
        --example-text: var(--text);
        --exampleheading-text: hsl(50deg, 70%, 70%);

        --note-border: hsl(120deg, 100%, 35%);
        --note-bg: var(--borderedblock-bg);
        --note-text: var(--text);
        --noteheading-text: hsl(120, 70%, 70%);
        --notesummary-underline: silver;

        --assertion-border: #444;
        --assertion-bg: var(--borderedblock-bg);
        --assertion-text: var(--text);

        --advisement-border: orange;
        --advisement-bg: #222218;
        --advisement-text: var(--text);
        --advisementheading-text: #f84;

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

        --amendment-border: #330099;
        --amendment-bg: #080010;
        --amendment-text: var(--text);
        --amendmentheading-text: #cc00ff;

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

        --datacell-border: silver;

        --indexinfo-text: #aaa;

        --indextable-hover-text: var(--text);
        --indextable-hover-bg: #181818;

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

        --editedrec-bg: darkorange;
    }
    /* In case a transparent-bg image doesn't expect to be on a dark bg,
       which is quite common in practice... */
    img { background: white; }
}
</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 */

@media (prefers-color-scheme: dark) {
    .highlight:not(.idl) { background: rgba(255, 255, 255, .05); }

    c-[a] { color: #d33682 } /* Keyword.Declaration */
    c-[b] { color: #d33682 } /* Keyword.Type */
    c-[c] { color: #2aa198 } /* Comment */
    c-[d] { color: #2aa198 } /* Comment.Multiline */
    c-[e] { color: #268bd2 } /* Name.Attribute */
    c-[f] { color: #b58900 } /* Name.Tag */
    c-[g] { color: #cb4b16 } /* Name.Variable */
    c-[k] { color: #d33682 } /* Keyword */
    c-[l] { color: #657b83 } /* Literal */
    c-[m] { color: #657b83 } /* Literal.Number */
    c-[n] { color: #268bd2 } /* Name */
    c-[o] { color: #657b83 } /* Operator */
    c-[p] { color: #657b83 } /* Punctuation */
    c-[s] { color: #6c71c4 } /* Literal.String */
    c-[t] { color: #6c71c4 } /* Literal.String.Single */
    c-[u] { color: #6c71c4 } /* Literal.String.Double */
    c-[ch] { color: #2aa198 } /* Comment.Hashbang */
    c-[cp] { color: #2aa198 } /* Comment.Preproc */
    c-[cpf] { color: #2aa198 } /* Comment.PreprocFile */
    c-[c1] { color: #2aa198 } /* Comment.Single */
    c-[cs] { color: #2aa198 } /* Comment.Special */
    c-[kc] { color: #d33682 } /* Keyword.Constant */
    c-[kn] { color: #d33682 } /* Keyword.Namespace */
    c-[kp] { color: #d33682 } /* Keyword.Pseudo */
    c-[kr] { color: #d33682 } /* Keyword.Reserved */
    c-[ld] { color: #657b83 } /* Literal.Date */
    c-[nc] { color: #268bd2 } /* Name.Class */
    c-[no] { color: #268bd2 } /* Name.Constant */
    c-[nd] { color: #268bd2 } /* Name.Decorator */
    c-[ni] { color: #268bd2 } /* Name.Entity */
    c-[ne] { color: #268bd2 } /* Name.Exception */
    c-[nf] { color: #268bd2 } /* Name.Function */
    c-[nl] { color: #268bd2 } /* Name.Label */
    c-[nn] { color: #268bd2 } /* Name.Namespace */
    c-[py] { color: #268bd2 } /* Name.Property */
    c-[ow] { color: #657b83 } /* Operator.Word */
    c-[mb] { color: #657b83 } /* Literal.Number.Bin */
    c-[mf] { color: #657b83 } /* Literal.Number.Float */
    c-[mh] { color: #657b83 } /* Literal.Number.Hex */
    c-[mi] { color: #657b83 } /* Literal.Number.Integer */
    c-[mo] { color: #657b83 } /* Literal.Number.Oct */
    c-[sa] { color: #6c71c4 } /* Literal.String.Affix */
    c-[sb] { color: #6c71c4 } /* Literal.String.Backtick */
    c-[sc] { color: #6c71c4 } /* Literal.String.Char */
    c-[dl] { color: #6c71c4 } /* Literal.String.Delimiter */
    c-[sd] { color: #6c71c4 } /* Literal.String.Doc */
    c-[se] { color: #6c71c4 } /* Literal.String.Escape */
    c-[sh] { color: #6c71c4 } /* Literal.String.Heredoc */
    c-[si] { color: #6c71c4 } /* Literal.String.Interpol */
    c-[sx] { color: #6c71c4 } /* Literal.String.Other */
    c-[sr] { color: #6c71c4 } /* Literal.String.Regex */
    c-[ss] { color: #6c71c4 } /* Literal.String.Symbol */
    c-[fm] { color: #268bd2 } /* Name.Function.Magic */
    c-[vc] { color: #cb4b16 } /* Name.Variable.Class */
    c-[vg] { color: #cb4b16 } /* Name.Variable.Global */
    c-[vi] { color: #cb4b16 } /* Name.Variable.Instance */
    c-[vm] { color: #cb4b16 } /* Name.Variable.Magic */
    c-[il] { color: #657b83 } /* 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">P3358R0<br>SARIF for Structured Diagnostics</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="profile-and-date"><span class="content">Published Proposal, <time class="dt-updated" datetime="2024-07-16">2024-07-16</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="https://wg21.link/P3358R0">https://wg21.link/P3358R0</a>
     <dt class="editor">Author:
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:sy.brand@microsoft.com">Sy Brand</a>
     <dt>Audience:
     <dd>SG15
     <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><a href="https://sarifweb.azurewebsites.net/">Static Analysis Results Interchange Format</a> (SARIF) is a standardised, structured format for the output of static analysis tools. Support for this format is common across C++ tooling, including static analyzers and compilers. Adoption is also growing among editors and IDEs. This paper presents what SARIF is, how it benefits the C++ ecosystem, the current state-of-the-art in support, and a future direction that will enrich the C++ diagnostic experience for programmers.</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="#overview-of-sarif"><span class="secno">1</span> <span class="content">Overview of SARIF</span></a>
    <li><a href="#what-sarif-gives-us"><span class="secno">2</span> <span class="content">What SARIF Gives Us</span></a>
    <li>
     <a href="#sarif_adoption"><span class="secno">3</span> <span class="content">SARIF Adoption in C++ Tools</span></a>
     <ol class="toc">
      <li>
       <a href="#compilers"><span class="secno">3.1</span> <span class="content">Compilers</span></a>
       <ol class="toc">
        <li><a href="#msvc"><span class="secno">3.1.1</span> <span class="content">MSVC</span></a>
        <li><a href="#gcc"><span class="secno">3.1.2</span> <span class="content">GCC</span></a>
        <li><a href="#clang"><span class="secno">3.1.3</span> <span class="content">Clang</span></a>
       </ol>
      <li><a href="#static-analyzers"><span class="secno">3.2</span> <span class="content">Static Analyzers</span></a>
      <li>
       <a href="#ides"><span class="secno">3.3</span> <span class="content">IDEs/Editors</span></a>
       <ol class="toc">
        <li><a href="#others"><span class="secno">3.3.1</span> <span class="content">Others</span></a>
       </ol>
     </ol>
    <li><a href="#hierarchical-diagnostics"><span class="secno">4</span> <span class="content">Hierarchical Diagnostics</span></a>
    <li>
     <a href="#suggested-direction"><span class="secno">5</span> <span class="content">Suggested Direction</span></a>
     <ol class="toc">
      <li><a href="#sarif-standard"><span class="secno">5.1</span> <span class="content">SARIF Standard</span></a>
      <li><a href="#build-systems"><span class="secno">5.2</span> <span class="content">Build Systems</span></a>
      <li><a href="#compilers①"><span class="secno">5.3</span> <span class="content">Compilers</span></a>
      <li><a href="#ides①"><span class="secno">5.4</span> <span class="content">IDEs</span></a>
     </ol>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="overview-of-sarif"><span class="secno">1. </span><span class="content">Overview of SARIF</span><a class="self-link" href="#overview-of-sarif"></a></h2>
   <p>SARIF is a <a href="https://www.rfc-editor.org/info/rfc8259">JSON</a>-based format for the output of static analysis tools (and therefore also compilers: what is a compiler if not a static analysis tool that happens to also output code?) It is standardised under the <a href="https://www.oasis-open.org/">OASIS Open</a> project. The most recent standard version is <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.pdf">v2.1.0</a>. The goals of the project are to:</p>
   <ul>
    <li data-md>
     <p>Comprehensively capture the range of data produced by commonly used static analysis tools.</p>
    <li data-md>
     <p>Be a useful format for analysis tools to emit directly, and also an effective interchange format into which the output of any analysis tool can be converted.</p>
    <li data-md>
     <p>Be suitable for use in a variety of scenarios related to analysis result management and be extensible for use in new scenarios.</p>
    <li data-md>
     <p>Reduce the cost and complexity of aggregating the results of various analysis tools into common workflows.</p>
    <li data-md>
     <p>Capture information that is useful for assessing a project’s compliance with corporate policy or certification standards.</p>
    <li data-md>
     <p>Adopt a widely used serialization format that can be parsed by readily available tools.</p>
    <li data-md>
     <p>Represent analysis results for all kinds of artifacts, including source code and object code.</p>
   </ul>
   <p>SARIF diagnostics are captured in <a href="https://www.rfc-editor.org/info/rfc3629">UTF-8</a>-encoded JSON objects with a specific set of JSON properties. Such objects are referred to as <code class="highlight"><c- n>sarifLog</c-></code> objects, and capture the results of one or more analysis runs, potentially from multiple tools. They contain metadata about the analysis runs and nested information about each diagnostic produced by the runs.</p>
   <p>Consider the following C++ code as an example:</p>
<pre class="language-cpp highlight"><c- b>int</c-> <c- nf>main</c-><c- p>()</c-> <c- p>{</c->
    <c- b>int</c-> <c- n>oops</c-> <c- o>=</c-> <c- s>"not an int"</c->
<c- p>}</c->
</pre>
   <p>This code has two errors and one issue that’s commonly diagnosed as a warning:</p>
   <ul>
    <li data-md>
     <p>The type of <code class="highlight"><c- n>oops</c-></code> is wrong</p>
    <li data-md>
     <p>There’s a missing semicolon</p>
    <li data-md>
     <p><code class="highlight"><c- n>oops</c-></code> is unused in the rest of the program</p>
   </ul>
   <p>GCC 14.1 generates the following <code class="highlight"><c- n>sarifLog</c-></code> object when it compiles the above code with <code class="highlight"><c- o>-</c-><c- n>Wall</c-> <c- o>-</c-><c- n>fdiagnostics</c-><c- o>-</c-><c- n>format</c-><c- o>=</c-><c- n>sarif</c-></code>:</p>
<pre class="language-json highlight"><c- p>{</c->
    <c- f>"$schema"</c-><c- p>:</c-> <c- u>"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json"</c-><c- p>,</c->
    <c- f>"version"</c-><c- p>:</c-> <c- u>"2.1.0"</c-><c- p>,</c->
    <c- f>"runs"</c-><c- p>:</c-> <c- p>[</c->
        <c- p>{</c->
            <c- f>"tool"</c-><c- p>:</c-> <c- p>{</c->
                <c- f>"driver"</c-><c- p>:</c-> <c- p>{</c->
                    <c- f>"name"</c-><c- p>:</c-> <c- u>"GNU C++17"</c-><c- p>,</c->
                    <c- f>"fullName"</c-><c- p>:</c-> <c- u>"GNU C++17 (Compiler-Explorer-Build-gcc--binutils-2.42) version 14.1.0 (x86_64-linux-gnu)"</c-><c- p>,</c->
                    <c- f>"version"</c-><c- p>:</c-> <c- u>"14.1.0"</c-><c- p>,</c->
                    <c- f>"informationUri"</c-><c- p>:</c-> <c- u>"https://gcc.gnu.org/gcc-14/"</c-><c- p>,</c->
                    <c- f>"rules"</c-><c- p>:</c-> <c- p>[</c->
                        <c- p>{</c->
                            <c- f>"id"</c-><c- p>:</c-> <c- u>"-fpermissive"</c-><c- p>,</c->
                            <c- f>"helpUri"</c-><c- p>:</c-> <c- u>"https://gcc.gnu.org/onlinedocs/gcc-14.1.0/gcc/Warning-Options.html#index-fpermissive"</c->
                        <c- p>},</c->
                        <c- p>{</c->
                            <c- f>"id"</c-><c- p>:</c-> <c- u>"-Wunused-variable"</c-><c- p>,</c->
                            <c- f>"helpUri"</c-><c- p>:</c-> <c- u>"https://gcc.gnu.org/onlinedocs/gcc-14.1.0/gcc/Warning-Options.html#index-Wno-unused-variable"</c->
                        <c- p>}</c->
                    <c- p>]</c->
                <c- p>}</c->
            <c- p>},</c->
            <c- f>"invocations"</c-><c- p>:</c-> <c- p>[</c->
                <c- p>{</c->
                    <c- f>"executionSuccessful"</c-><c- p>:</c-> <c- kc>true</c-><c- p>,</c->
                    <c- f>"toolExecutionNotifications"</c-><c- p>:</c-> <c- p>[]</c->
                <c- p>}</c->
            <c- p>],</c->
            <c- f>"artifacts"</c-><c- p>:</c-> <c- p>[</c->
                <c- p>{</c->
                    <c- f>"location"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"uri"</c-><c- p>:</c-> <c- u>"&lt;source>"</c->
                    <c- p>},</c->
                    <c- f>"contents"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"text"</c-><c- p>:</c-> <c- u>"int main() {\n    int oops = \"not an int\"\n}"</c->
                    <c- p>},</c->
                    <c- f>"sourceLanguage"</c-><c- p>:</c-> <c- u>"cplusplus"</c->
                <c- p>}</c->
            <c- p>],</c->
            <c- f>"results"</c-><c- p>:</c-> <c- p>[</c->
                <c- p>{</c->
                    <c- f>"ruleId"</c-><c- p>:</c-> <c- u>"-fpermissive"</c-><c- p>,</c->
                    <c- f>"level"</c-><c- p>:</c-> <c- u>"error"</c-><c- p>,</c->
                    <c- f>"message"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"text"</c-><c- p>:</c-> <c- u>"invalid conversion from 'const char*' to 'int'"</c->
                    <c- p>},</c->
                    <c- f>"locations"</c-><c- p>:</c-> <c- p>[</c->
                        <c- p>{</c->
                            <c- f>"physicalLocation"</c-><c- p>:</c-> <c- p>{</c->
                                <c- f>"artifactLocation"</c-><c- p>:</c-> <c- p>{</c->
                                    <c- f>"uri"</c-><c- p>:</c-> <c- u>"&lt;source>"</c->
                                <c- p>},</c->
                                <c- f>"region"</c-><c- p>:</c-> <c- p>{</c->
                                    <c- f>"startLine"</c-><c- p>:</c-> <c- mi>2</c-><c- p>,</c->
                                    <c- f>"startColumn"</c-><c- p>:</c-> <c- mi>16</c-><c- p>,</c->
                                    <c- f>"endColumn"</c-><c- p>:</c-> <c- mi>28</c->
                                <c- p>},</c->
                                <c- f>"contextRegion"</c-><c- p>:</c-> <c- p>{</c->
                                    <c- f>"startLine"</c-><c- p>:</c-> <c- mi>2</c-><c- p>,</c->
                                    <c- f>"snippet"</c-><c- p>:</c-> <c- p>{</c->
                                        <c- f>"text"</c-><c- p>:</c-> <c- u>"    int oops = \"not an int\"\n"</c->
                                    <c- p>}</c->
                                <c- p>}</c->
                            <c- p>},</c->
                            <c- f>"logicalLocations"</c-><c- p>:</c-> <c- p>[</c->
                                <c- p>{</c->
                                    <c- f>"name"</c-><c- p>:</c-> <c- u>"main"</c-><c- p>,</c->
                                    <c- f>"fullyQualifiedName"</c-><c- p>:</c-> <c- u>"main"</c-><c- p>,</c->
                                    <c- f>"decoratedName"</c-><c- p>:</c-> <c- u>"main"</c-><c- p>,</c->
                                    <c- f>"kind"</c-><c- p>:</c-> <c- u>"function"</c->
                                <c- p>}</c->
                            <c- p>]</c->
                        <c- p>}</c->
                    <c- p>]</c->
                <c- p>},</c->
                <c- p>{</c->
                    <c- f>"ruleId"</c-><c- p>:</c-> <c- u>"error"</c-><c- p>,</c->
                    <c- f>"level"</c-><c- p>:</c-> <c- u>"error"</c-><c- p>,</c->
                    <c- f>"message"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"text"</c-><c- p>:</c-> <c- u>"expected ',' or ';' before '}' token"</c->
                    <c- p>},</c->
                    <c- f>"locations"</c-><c- p>:</c-> <c- p>[</c->
                        <c- p>{</c->
                            <c- f>"physicalLocation"</c-><c- p>:</c-> <c- p>{</c->
                                <c- f>"artifactLocation"</c-><c- p>:</c-> <c- p>{</c->
                                    <c- f>"uri"</c-><c- p>:</c-> <c- u>"&lt;source>"</c->
                                <c- p>},</c->
                                <c- f>"region"</c-><c- p>:</c-> <c- p>{</c->
                                    <c- f>"startLine"</c-><c- p>:</c-> <c- mi>3</c-><c- p>,</c->
                                    <c- f>"startColumn"</c-><c- p>:</c-> <c- mi>1</c-><c- p>,</c->
                                    <c- f>"endColumn"</c-><c- p>:</c-> <c- mi>2</c->
                                <c- p>},</c->
                                <c- f>"contextRegion"</c-><c- p>:</c-> <c- p>{</c->
                                    <c- f>"startLine"</c-><c- p>:</c-> <c- mi>3</c-><c- p>,</c->
                                    <c- f>"snippet"</c-><c- p>:</c-> <c- p>{</c->
                                        <c- f>"text"</c-><c- p>:</c-> <c- u>"}\n"</c->
                                    <c- p>}</c->
                                <c- p>}</c->
                            <c- p>},</c->
                            <c- f>"logicalLocations"</c-><c- p>:</c-> <c- p>[</c->
                                <c- p>{</c->
                                    <c- f>"name"</c-><c- p>:</c-> <c- u>"main"</c-><c- p>,</c->
                                    <c- f>"fullyQualifiedName"</c-><c- p>:</c-> <c- u>"main"</c-><c- p>,</c->
                                    <c- f>"decoratedName"</c-><c- p>:</c-> <c- u>"main"</c-><c- p>,</c->
                                    <c- f>"kind"</c-><c- p>:</c-> <c- u>"function"</c->
                                <c- p>}</c->
                            <c- p>]</c->
                        <c- p>}</c->
                    <c- p>]</c->
                <c- p>},</c->
                <c- p>{</c->
                    <c- f>"ruleId"</c-><c- p>:</c-> <c- u>"-Wunused-variable"</c-><c- p>,</c->
                    <c- f>"level"</c-><c- p>:</c-> <c- u>"warning"</c-><c- p>,</c->
                    <c- f>"message"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"text"</c-><c- p>:</c-> <c- u>"unused variable 'oops'"</c->
                    <c- p>},</c->
                    <c- f>"locations"</c-><c- p>:</c-> <c- p>[</c->
                        <c- p>{</c->
                            <c- f>"physicalLocation"</c-><c- p>:</c-> <c- p>{</c->
                                <c- f>"artifactLocation"</c-><c- p>:</c-> <c- p>{</c->
                                    <c- f>"uri"</c-><c- p>:</c-> <c- u>"&lt;source>"</c->
                                <c- p>},</c->
                                <c- f>"region"</c-><c- p>:</c-> <c- p>{</c->
                                    <c- f>"startLine"</c-><c- p>:</c-> <c- mi>2</c-><c- p>,</c->
                                    <c- f>"startColumn"</c-><c- p>:</c-> <c- mi>9</c-><c- p>,</c->
                                    <c- f>"endColumn"</c-><c- p>:</c-> <c- mi>13</c->
                                <c- p>},</c->
                                <c- f>"contextRegion"</c-><c- p>:</c-> <c- p>{</c->
                                    <c- f>"startLine"</c-><c- p>:</c-> <c- mi>2</c-><c- p>,</c->
                                    <c- f>"snippet"</c-><c- p>:</c-> <c- p>{</c->
                                        <c- f>"text"</c-><c- p>:</c-> <c- u>"    int oops = \"not an int\"\n"</c->
                                    <c- p>}</c->
                                <c- p>}</c->
                            <c- p>},</c->
                            <c- f>"logicalLocations"</c-><c- p>:</c-> <c- p>[</c->
                                <c- p>{</c->
                                    <c- f>"name"</c-><c- p>:</c-> <c- u>"main"</c-><c- p>,</c->
                                    <c- f>"fullyQualifiedName"</c-><c- p>:</c-> <c- u>"main"</c-><c- p>,</c->
                                    <c- f>"decoratedName"</c-><c- p>:</c-> <c- u>"main"</c-><c- p>,</c->
                                    <c- f>"kind"</c-><c- p>:</c-> <c- u>"function"</c->
                                <c- p>}</c->
                            <c- p>]</c->
                        <c- p>}</c->
                    <c- p>]</c->
                <c- p>}</c->
            <c- p>]</c->
        <c- p>}</c->
    <c- p>]</c->
<c- p>}</c->
</pre>
   <p>The output has three top-level properties:</p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- n>$schema</c-></code>: Defines the <a href="https://json-schema.org/">JSON Schema</a> for the <code class="highlight"><c- n>sarifLog</c-></code> object, which is provided by the SARIF project</p>
    <li data-md>
     <p><code class="highlight"><c- n>version</c-></code>: Defines the SARIF version</p>
    <li data-md>
     <p><code class="highlight"><c- n>runs</c-></code>: Captures the analysis runs that produced diagnostics (in this case, there is only one)</p>
   </ul>
   <p>The <code class="highlight"><c- n>runs</c-></code> property is an array of <code class="highlight"><c- n>run</c-></code> objects (defined in the SARIF spec), which contains metadata about the tool that produced the diagnostics in the <code class="highlight"><c- n>tool</c-></code> property, metadata about how the tool was executed in the <code class="highlight"><c- n>invocations</c-></code> property, the source code that the tool was run on in the <code class="highlight"><c- n>artifacts</c-></code> property, and the diagnostics produced in the <code class="highlight"><c- n>results</c-></code> property. Some properties are mandatory, some are optional. There are several optional properties that GCC did not include in this output.</p>
   <p>The diagnostics in the <code class="highlight"><c- n>results</c-></code> property are <code class="highlight"><c- n>result</c-></code> objects. Each of the results produced by GCC have the following properties:</p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- n>ruleId</c-></code>: An identifier key that refers to an entry in the <code class="highlight"><c- n>tool</c-><c- p>.</c-><c- n>driver</c-><c- p>.</c-><c- n>rules</c-></code> object for this run, which provides more information about what analysis rule caused this diagnostic to be generated.</p>
    <li data-md>
     <p><code class="highlight"><c- n>level</c-></code>: The severity of the diagnostic (<code class="highlight"><c- n>error</c-></code>, <code class="highlight"><c- n>warning</c-></code>, <code class="highlight"><c- n>note</c-></code>, or <code class="highlight"><c- n>none</c-></code>).</p>
    <li data-md>
     <p><code class="highlight"><c- n>message</c-></code>: The textual diagnostic that should be displayed to the user.</p>
    <li data-md>
     <p><code class="highlight"><c- n>locations</c-></code>: Descriptions of the parts of the source code to which the diagnostic applies.</p>
   </ul>
   <h2 class="heading settled" data-level="2" id="what-sarif-gives-us"><span class="secno">2. </span><span class="content">What SARIF Gives Us</span><a class="self-link" href="#what-sarif-gives-us"></a></h2>
   <p>In <a href="https://wg21.link/p2429r0">P2429</a> I presented the state-of-the-art of compiler diagnostics, both in research and in industry tooling. The paper "<a href="https://dl.acm.org/doi/10.1145/3344429.3372508">Compiler Error Messages Considered Unhelpful: The Landscape of Text-Based
Programming Error Message Research</a>" summarized the following key ways in which compiler errors can be improved:</p>
   <ul>
    <li data-md>
     <p>Increase readability by using plain language, being concise, and writing errors for humans rather than tools.</p>
    <li data-md>
     <p>Reduce cognitive load by placing relevant information near the offending code, reducing redundancy so the user does not process the same information twice, and using multiple modalities to provide feedback.</p>
    <li data-md>
     <p>Provide context that can help the user.</p>
    <li data-md>
     <p>Use a positive tone</p>
    <li data-md>
     <p>Show examples of similar errors that are minimal and aid understanding.</p>
    <li data-md>
     <p>Show solutions or hints.</p>
    <li data-md>
     <p>Allow dynamic interaction by providing the user with autonomy over error message presentation.</p>
    <li data-md>
     <p>Provide scaffolding that helps the user connect concepts in the language with errors in their code.</p>
    <li data-md>
     <p>Use logical argumentation by providing a coherent narrative of the error.</p>
    <li data-md>
     <p>Report errors at the right time by giving the user the right amount of information when they need it.</p>
   </ul>
   <p>SARIF supports several of these points. By providing diagnostics in a machine-readable format, tools can more easily filter and manipulate diagnostics in order to reduce cognitive load. Solutions and hints can be provided in a standardized manner with <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html#_Toc141791131">fix objects</a>. Dynamic interaction and logical argumentation can be more easily facilitated by compilers and IDEs because they can express and understand the hierarchical nature of diagnostics (this is how Visual Studio’s <a href="https://learn.microsoft.com/en-us/visualstudio/ide/reference/problem-details-window?view=vs-2022">Problem Details Window</a> works).</p>
   <p>Furthermore, since SARIF is standardised and there are existing tools that can read, manipulate, and visualize it (see <a href="#sarif_adoption">§ 3 SARIF Adoption in C++ Tools</a> for some examples), users can take the output of C++ compilers and use external tools to process them.</p>
   <h2 class="heading settled" data-level="3" id="sarif_adoption"><span class="secno">3. </span><span class="content">SARIF Adoption in C++ Tools</span><a class="self-link" href="#sarif_adoption"></a></h2>
   <h3 class="heading settled" data-level="3.1" id="compilers"><span class="secno">3.1. </span><span class="content">Compilers</span><a class="self-link" href="#compilers"></a></h3>
   <h4 class="heading settled" data-level="3.1.1" id="msvc"><span class="secno">3.1.1. </span><span class="content">MSVC</span><a class="self-link" href="#msvc"></a></h4>
   <p>SARIF support for MSVC is documented on the <a href="https://learn.microsoft.com/en-us/cpp/build/reference/sarif-output?view=msvc-170">Structured SARIF Diagnostics</a> page and is available as of Visual Studio 2022 version 17.8.</p>
   <p>There are two ways to make the MSVC compiler produce SARIF diagnostics:</p>
   <ul>
    <li data-md>
     <p>Pass the <code class="highlight"><c- o>/</c-><c- n>experimental</c-><c- o>:</c-><c- n>log</c-> <c- n>FILENAME</c-></code> switch on the command line. The <code class="highlight"><c- n>FILENAME</c-></code> argument specifies. Where to output SARIF diagnostics. The <code class="highlight"><c- p>.</c-><c- n>sarif</c-></code> suffix is added to <code class="highlight"><c- n>FILENAME</c-></code> to produce the final filename at which to store the resulting SARIF diagnostics. <code class="highlight"><c- n>FILENAME</c-></code> can be absolute, or relative to the current working directory of the compiler.</p>
    <li data-md>
     <p>Launch <code class="highlight"><c- n>cl</c-><c- p>.</c-><c- n>exe</c-></code> programatically and set the <code class="highlight"><c- n>SARIF_OUTPUT_PIPE</c-></code> environment variable to retrieve SARIF blocks through a pipe.</p>
   </ul>
   <p>To retrieve SARIF through a pipe, tools set the <code class="highlight"><c- n>SARIF_OUTPUT_PIPE</c-></code> environment variable to be the UTF-16-encoded integer representation of the <a href="https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types">HANDLE</a> to the write end of the pipe, then launch <code class="highlight"><c- n>cl</c-><c- p>.</c-><c- n>exe</c-></code>. SARIF is sent along the pipe as follows:</p>
   <ul>
    <li data-md>
     <p>When a new diagnostic is available, it is written to this pipe.</p>
    <li data-md>
     <p>Diagnostics are written to the pipe one-at-a-time rather than as an entire SARIF object.</p>
    <li data-md>
     <p>Each diagnostic is represented by a <a href="https://www.jsonrpc.org/">JSON-RPC 2.0</a> message of type <a href="https://www.jsonrpc.org/specification#notification:%7E:text=as%20binary%20fractions.-,4.1%20Notification,-A%20Notification%20is">Notification</a>.</p>
    <li data-md>
     <p>The JSON-RPC message is prefixed with a <code class="highlight"><c- n>Content</c-><c- o>-</c-><c- n>Length</c-></code> header with the form <code class="highlight"><c- n>Content</c-><c- o>-</c-><c- n>Length</c-><c- o>:</c-> <c- n>N</c-></code> followed by two newlines, where <code class="highlight"><c- n>N</c-></code> is the length of the following JSON-RPC message in bytes.</p>
    <li data-md>
     <p>The JSON-RPC message and header are both encoded in UTF-8.</p>
    <li data-md>
     <p>This JSON-RPC-with-header format is compatible with <a href="https://github.com/microsoft/vs-streamjsonrpc">vs-streamjsonrpc</a>.</p>
    <li data-md>
     <p>The method name for the JSON-RPC call is <code class="highlight"><c- n>OnSarifResult</c-></code>.</p>
    <li data-md>
     <p>The call has a single parameter that is encoded <a href="https://www.jsonrpc.org/specification#parameter_structures">by-name</a> with the parameter name <code class="highlight"><c- n>result</c-></code>.</p>
    <li data-md>
     <p>The value of the argument is a single <code class="highlight"><c- n>result</c-></code> object as specified by the SARIF Version 2.1 standard.</p>
   </ul>
<pre class="language-json highlight">Co<c- kc>ntent</c-><c- mi>-</c->Le<c- kc>n</c->g<c- kc>t</c->h<c- p>:</c-> <c- mi>334</c->

<c- p>{</c-><c- f>"jsonrpc"</c-><c- p>:</c-><c- u>"2.0"</c-><c- p>,</c-><c- f>"method"</c-><c- p>:</c-><c- u>"OnSarifResult"</c-><c- p>,</c-><c- f>"params"</c-><c- p>:{</c-><c- f>"result"</c-><c- p>:{</c-><c- f>"ruleId"</c-><c- p>:</c-><c- u>"C1034"</c-><c- p>,</c-><c- f>"level"</c-><c- p>:</c-><c- u>"fatal"</c-><c- p>,</c-><c- f>"message"</c-><c- p>:{</c-><c- f>"text"</c-><c- p>:</c-><c- u>"iostream: no include path set"</c-><c- p>},</c-><c- f>"locations"</c-><c- p>:[{</c-><c- f>"physicalLocation"</c-><c- p>:{</c-><c- f>"artifactLocation"</c-><c- p>:{</c-><c- f>"uri"</c-><c- p>:</c-><c- u>"file:///C:/Users/sybrand/source/repos/cppcon-diag/cppcon-diag/cppcon-diag.cpp"</c-><c- p>},</c-><c- f>"region"</c-><c- p>:{</c-><c- f>"startLine"</c-><c- p>:</c-><c- mi>1</c-><c- p>,</c-><c- f>"startColumn"</c-><c- p>:</c-><c- mi>10</c-><c- p>}}}]}}}{</c-><c- f>"jsonrpc"</c-><c- p>:</c-><c- u>"2.0"</c-><c- p>,</c-><c- f>"method"</c-><c- p>:</c-><c- u>"OnSarifResult"</c-><c- p>,</c-><c- f>"params"</c-><c- p>:{</c-><c- f>"result"</c-><c- p>:{</c-><c- f>"ruleId"</c-><c- p>:</c-><c- u>"C1034"</c-><c- p>,</c-><c- f>"level"</c-><c- p>:</c-><c- u>"fatal"</c-><c- p>,</c-><c- f>"message"</c-><c- p>:{</c-><c- f>"text"</c-><c- p>:</c-><c- u>"iostream: no include path set"</c-><c- p>},</c-><c- f>"locations"</c-><c- p>:[{</c-><c- f>"physicalLocation"</c-><c- p>:{</c-><c- f>"artifactLocation"</c-><c- p>:{</c-><c- f>"uri"</c-><c- p>:</c-><c- u>"file:///C:/Users/sybrand/source/repos/cppcon-diag/cppcon-diag/cppcon-diag.cpp"</c-><c- p>},</c-><c- f>"region"</c-><c- p>:{</c-><c- f>"startLine"</c-><c- p>:</c-><c- mi>1</c-><c- p>,</c-><c- f>"startColumn"</c-><c- p>:</c-><c- mi>10</c-><c- p>}}}]}}}</c->
</pre>
   <p>The SARIF <code class="highlight"><c- n>result</c-></code> object additionally encodes information about hierarchical diagnostics. See <a href="#hierarchical-diagnostics">§ 4 Hierarchical Diagnostics</a> for details.</p>
   <h4 class="heading settled" data-level="3.1.2" id="gcc"><span class="secno">3.1.2. </span><span class="content">GCC</span><a class="self-link" href="#gcc"></a></h4>
   <p>GCC supports outputting diagnostics in SARIF 2.1 as of GCC 13. It is controlled with the <code class="highlight"><c- o>-</c-><c- n>fdiagnostics</c-><c- o>-</c-><c- n>format</c-><c- o>=</c-><c- n>FORMAT</c-></code> option, where the valid values for <code class="highlight"><c- n>FORMAT</c-></code> are <code class="highlight"><c- n>sarif</c-><c- o>-</c-><c- n>file</c-></code>, <code class="highlight"><c- n>sarif</c-><c- o>-</c-><c- n>stderr</c-></code>, <code class="highlight"><c- n>json</c-><c- o>-</c-><c- n>file</c-></code>, and <code class="highlight"><c- n>json</c-><c- o>-</c-><c- n>stderr</c-></code>. When <code class="highlight"><c- n>sarif</c-><c- o>-</c-><c- n>file</c-></code> or <code class="highlight"><c- n>json</c-><c- o>-</c-><c- n>file</c-></code> are passed, the resulting SARIF or JSON data is stored in <code class="highlight"><c- n>FILENAME</c-><c- p>.</c-><c- n>sarif</c-></code> in the current working directory of the compiler where <code class="highlight"><c- n>FILENAME</c-></code> is the filename of the source file whose translation unit.</p>
   <p>The file format used for <code class="highlight"><c- n>json</c-><c- o>-</c-><c- n>file</c-></code> and <code class="highlight"><c- n>json</c-><c- o>-</c-><c- n>stderr</c-></code> carries essentially the same information as the SARIF, but in a custom JSON format.</p>
   <h4 class="heading settled" data-level="3.1.3" id="clang"><span class="secno">3.1.3. </span><span class="content">Clang</span><a class="self-link" href="#clang"></a></h4>
   <p>As of version 15, Clang has "unstable" support for SARIF 2.1 output. It is controlled with the <code class="highlight"><c- o>-</c-><c- n>fdiagnostics</c-><c- o>-</c-><c- n>format</c-><c- o>=</c-><c- n>FORMAT</c-></code> option, where the <code class="highlight"><c- n>FORMAT</c-></code> argument can be <code class="highlight"><c- n>clang</c-></code>, <code class="highlight"><c- n>msvc</c-></code>, <code class="highlight"><c- n>vi</c-></code>, <code class="highlight"><c- n>sarif</c-></code>, or <code class="highlight"><c- n>SARIF</c-></code>. The final two options are undocumented. When invoked with <code class="highlight"><c- o>-</c-><c- n>fdiagnostics</c-><c- o>-</c-><c- n>format</c-><c- o>=</c-><c- n>sarif</c-></code> or <code class="highlight"><c- o>-</c-><c- n>fdiagnostics</c-><c- o>-</c-><c- n>format</c-><c- o>=</c-><c- n>SARIF</c-></code>, Clang outputs SARIF to <code class="highlight"><c- n>stderr</c-></code>, along with the following message:</p>
<pre class="highlight"><c- n>clang</c-><c- o>++:</c-> <c- n>warning</c-><c- o>:</c-> <c- n>diagnostic</c-> <c- n>formatting</c-> <c- n>in</c-> <c- n>SARIF</c-> <c- n>mode</c-> <c- n>is</c-> <c- n>currently</c-> <c- n>unstable</c-> <c- p>[</c-><c- o>-</c-><c- n>Wsarif</c-><c- o>-</c-><c- n>format</c-><c- o>-</c-><c- n>unstable</c-><c- p>]</c->
</pre>
   <p>There is an <a href="https://reviews.llvm.org/D145284">open pull request</a> that changes this support to mirror GCC’s <code class="highlight"><c- n>sarif</c-><c- o>-</c-><c- n>file</c-></code> and <code class="highlight"><c- n>sarif</c-><c- o>-</c-><c- n>stderr</c-></code> options.</p>
   <h3 class="heading settled" data-level="3.2" id="static-analyzers"><span class="secno">3.2. </span><span class="content">Static Analyzers</span><a class="self-link" href="#static-analyzers"></a></h3>
   <ul>
    <li data-md>
     <p><a href="https://learn.microsoft.com/en-us/cpp/code-quality/code-analysis-for-c-cpp-overview?view=msvc-170">MSVC Code Analysis</a> - Provides results to Visual Studio in SARIF 2.1.</p>
    <li data-md>
     <p><a href="https://www.jetbrains.com/qodana/">Qodana</a> - <a href="https://www.jetbrains.com/help/qodana/qodana-sarif-output.html">Supports SARIF 2.1</a>.</p>
    <li data-md>
     <p><a href="https://clang.llvm.org/extra/clang-tidy/">Clang-Tidy</a> - There is an <a href="https://github.com/llvm/llvm-project/issues/55647">open issue</a> for SARIF support.</p>
    <li data-md>
     <p><a href="https://codeql.github.com/">GitHub CodeQL</a> - <a href="https://docs.github.com/en/code-security/codeql-cli/using-the-advanced-functionality-of-the-codeql-cli/sarif-output">Supports SARIF 2.1</a>.</p>
    <li data-md>
     <p><a href="https://www.sonarsource.com/products/sonarqube/">SonarQube</a> - Can <a href="https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/importing-external-issues/importing-issues-from-sarif-reports/">import SARIF 2.1</a>.</p>
    <li data-md>
     <p><a href="https://codechecker.readthedocs.io/en/latest/">CodeChecker</a> - <a href="https://github.com/Ericsson/codechecker/pull/4011">Supports SARIF 2.1</a>.</p>
    <li data-md>
     <p><a href="https://fbinfer.com/">Infer</a> - <a href="https://github.com/facebook/infer/pull/1487">Supports SARIF 2.1</a></p>
   </ul>
   <h3 class="heading settled" data-level="3.3" id="ides"><span class="secno">3.3. </span><span class="content">IDEs/Editors</span><a class="self-link" href="#ides"></a></h3>
   <ul>
    <li data-md>
     <p><a href="https://code.visualstudio.com/">Visual Studio Code</a> - There is a <a href="https://marketplace.visualstudio.com/items?itemName=MS-SarifVSCode.sarif-viewer">SARIF viewer extension</a>.</p>
    <li data-md>
     <p><a href="https://visualstudio.microsoft.com/">Visual Studio</a> - The <a href="https://learn.microsoft.com/en-us/visualstudio/ide/reference/problem-details-window?view=vs-2022">Problem Details Window</a> is driven by SARIF. When building a <a href="https://learn.microsoft.com/en-us/cpp/build/creating-and-managing-visual-cpp-projects?view=msvc-170">Visual Studio project</a> (MSBuild) and the <strong>Project > Properties > Advanced > Enable MSVC Structured Output</strong> option is enabled, Visual Studio will spawn <code class="highlight"><c- n>cl</c-><c- p>.</c-><c- n>exe</c-></code> with the <code class="highlight"><c- n>SARIF_OUTPUT_PIPE</c-></code> environment variable set and will stream SARIF results out of the compiler and into the <a href="https://learn.microsoft.com/en-us/visualstudio/ide/reference/output-window?view=vs-2022">Output Window</a> and Problem Details Window. As such, Visual Studio supports SARIF natively when building with MSVC and MSBuild. There is also a <a href="https://marketplace.visualstudio.com/items?itemName=WDGIS.MicrosoftSarifViewer">SARIF viewer extension</a>.</p>
    <li data-md>
     <p><a href="https://developer.android.com/studio">Android Studio</a>, <a href="https://www.jetbrains.com/rider/">Rider</a>, and <a href="https://www.jetbrains.com/clion/">CLion</a> - There is a <a href="https://plugins.jetbrains.com/plugin/23159-sarif-viewer">SARIF viewer extension</a>.</p>
    <li data-md>
     <p><a href="https://godbolt.org/">Compiler Explorer</a>: There is an <a href="https://github.com/compiler-explorer/compiler-explorer/issues/4832">open issue</a> for SARIF support.</p>
   </ul>
   <h4 class="heading settled" data-level="3.3.1" id="others"><span class="secno">3.3.1. </span><span class="content">Others</span><a class="self-link" href="#others"></a></h4>
   <ul>
    <li data-md>
     <p><a href="https://cmake.org/cmake/help/latest/manual/ctest.1.html">CTest</a> - There is an <a href="https://gitlab.kitware.com/cmake/cmake/-/issues/25953">open issue</a> for SARIF support.</p>
    <li data-md>
     <p><a href="https://www.convisoappsec.com/">Convisio Platform</a> - <a href="https://blog.convisoappsec.com/en/what-is-sarif-and-how-it-could-revolutionize-software-security/">Supports SARIF</a></p>
   </ul>
   <h2 class="heading settled" data-level="4" id="hierarchical-diagnostics"><span class="secno">4. </span><span class="content">Hierarchical Diagnostics</span><a class="self-link" href="#hierarchical-diagnostics"></a></h2>
   <p>One key benefit of using a structured diagnostic format is the ability to output diagnostics that have a logical hierarchy. This is especially useful for code that uses Concepts heavily (which includes any piece of code that uses Ranges) Consider, for example, the following C++ code:</p>
<pre class="language-cpp highlight"><c- k>struct</c-> <c- nc>dog</c-> <c- p>{};</c->
<c- k>struct</c-> <c- nc>cat</c-> <c- p>{};</c->

<c- b>void</c-> <c- nf>pet</c-><c- p>(</c-><c- n>dog</c-><c- p>);</c->
<c- b>void</c-> <c- nf>pet</c-><c- p>(</c-><c- n>cat</c-><c- p>);</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
<c- k>concept</c-> <c- nc>has_member_pet</c-> <c- o>=</c-> <c- k>requires</c-><c- p>(</c-><c- n>T</c-> <c- n>t</c-><c- p>)</c-> <c- p>{</c-> <c- n>t</c-><c- p>.</c-><c- n>pet</c-><c- p>();</c-> <c- p>};</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
<c- k>concept</c-> <c- nc>has_default_pet</c-> <c- o>=</c-> <c- n>T</c-><c- o>::</c-><c- n>is_pettable</c-><c- p>;</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
<c- k>concept</c-> <c- nc>pettable</c-> <c- o>=</c-> <c- n>has_member_pet</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- k>or</c-> <c- n>has_default_pet</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>;</c->

<c- b>void</c-> <c- nf>pet</c-><c- p>(</c-><c- n>pettable</c-> <c- k>auto</c-> <c- n>t</c-><c- p>);</c->

<c- k>struct</c-> <c- nc>lizard</c-> <c- p>{};</c->

<c- b>int</c-> <c- nf>main</c-><c- p>()</c-> <c- p>{</c->
    <c- n>pet</c-><c- p>(</c-><c- n>lizard</c-><c- p>{});</c->
<c- p>}</c->
</pre>
   <p>Passing a <code class="highlight"><c- n>lizard</c-></code> to <code class="highlight"><c- n>pet</c-></code> is not valid, because neither of the <code class="highlight"><c- n>pet</c-><c- p>(</c-><c- n>dog</c-><c- p>)</c-></code> or <code class="highlight"><c- n>pet</c-><c- p>(</c-><c- n>cat</c-><c- p>)</c-></code> functions match, and the template overload requires the type model <code class="highlight"><c- n>pettable</c-></code>, which <code class="highlight"><c- n>lizard</c-></code> does not, since it neither has a member <code class="highlight"><c- n>pet</c-></code> function nor specifies <code class="highlight"><c- n>lizard</c-><c- o>::</c-><c- n>is_pettable</c-></code>. MSVC generates a hierarchical error like this:</p>
<pre class="highlight"><c- n>source</c-><c- p>.</c-><c- n>cpp</c-><c- p>(</c-><c- mi>21</c-><c- p>,</c-><c- mi>5</c-><c- p>)</c-><c- o>:</c-> <c- n>error</c-> <c- n>C2665</c-><c- o>:</c-> '<c- n>pet</c->'<c- o>:</c-> <c- n>no</c-> <c- n>overloaded</c-> <c- n>function</c-> <c- n>could</c-> <c- n>convert</c-> <c- n>all</c-> <c- n>the</c-> <c- n>argument</c-> <c- n>types</c->
    <c- n>source</c-><c- p>.</c-><c- n>cpp</c-><c- p>(</c-><c- mi>5</c-><c- p>,</c-><c- mi>6</c-><c- p>)</c-><c- o>:</c->
    <c- n>could</c-> <c- n>be</c-> '<c- b>void</c-> <c- n>pet</c-><c- p>(</c-><c- n>cat</c-><c- p>)</c->'
        <c- n>source</c-><c- p>.</c-><c- n>cpp</c-><c- p>(</c-><c- mi>21</c-><c- p>,</c-><c- mi>5</c-><c- p>)</c-><c- o>:</c->
        '<c- b>void</c-> <c- n>pet</c-><c- p>(</c-><c- n>cat</c-><c- p>)</c->'<c- o>:</c-> <c- n>cannot</c-> <c- n>convert</c-> <c- n>argument</c-> <c- mi>1</c-> <c- n>from</c-> '<c- n>lizard</c->' <c- n>to</c-> '<c- n>cat</c->'
            <c- n>source</c-><c- p>.</c-><c- n>cpp</c-><c- p>(</c-><c- mi>21</c-><c- p>,</c-><c- mi>15</c-><c- p>)</c-><c- o>:</c->
            <c- n>No</c-> <c- n>user</c-><c- o>-</c-><c- n>defined</c-><c- o>-</c-><c- n>conversion</c-> <c- k>operator</c-> <c- n>available</c-> <c- n>that</c-> <c- n>can</c-> <c- n>perform</c-> <c- k>this</c-> <c- n>conversion</c-><c- p>,</c-> <c- k>or</c-> <c- n>the</c-> <c- k>operator</c-> <c- n>cannot</c-> <c- n>be</c-> <c- n>called</c->
    <c- n>source</c-><c- p>.</c-><c- n>cpp</c-><c- p>(</c-><c- mi>4</c-><c- p>,</c-><c- mi>6</c-><c- p>)</c-><c- o>:</c->
    <c- k>or</c->       '<c- b>void</c-> <c- n>pet</c-><c- p>(</c-><c- n>dog</c-><c- p>)</c->'
        <c- n>source</c-><c- p>.</c-><c- n>cpp</c-><c- p>(</c-><c- mi>21</c-><c- p>,</c-><c- mi>5</c-><c- p>)</c-><c- o>:</c->
        '<c- b>void</c-> <c- n>pet</c-><c- p>(</c-><c- n>dog</c-><c- p>)</c->'<c- o>:</c-> <c- n>cannot</c-> <c- n>convert</c-> <c- n>argument</c-> <c- mi>1</c-> <c- n>from</c-> '<c- n>lizard</c->' <c- n>to</c-> '<c- n>dog</c->'
            <c- n>source</c-><c- p>.</c-><c- n>cpp</c-><c- p>(</c-><c- mi>21</c-><c- p>,</c-><c- mi>15</c-><c- p>)</c-><c- o>:</c->
            <c- n>No</c-> <c- n>user</c-><c- o>-</c-><c- n>defined</c-><c- o>-</c-><c- n>conversion</c-> <c- k>operator</c-> <c- n>available</c-> <c- n>that</c-> <c- n>can</c-> <c- n>perform</c-> <c- k>this</c-> <c- n>conversion</c-><c- p>,</c-> <c- k>or</c-> <c- n>the</c-> <c- k>operator</c-> <c- n>cannot</c-> <c- n>be</c-> <c- n>called</c->
    <c- n>source</c-><c- p>.</c-><c- n>cpp</c-><c- p>(</c-><c- mi>16</c-><c- p>,</c-><c- mi>6</c-><c- p>)</c-><c- o>:</c->
    <c- k>or</c->       '<c- b>void</c-> <c- n>pet</c-><c- p>(</c-><c- n>_T0</c-><c- p>)</c->'
        <c- n>source</c-><c- p>.</c-><c- n>cpp</c-><c- p>(</c-><c- mi>21</c-><c- p>,</c-><c- mi>5</c-><c- p>)</c-><c- o>:</c->
        <c- n>the</c-> <c- n>associated</c-> <c- n>constraints</c-> <c- n>are</c-> <c- k>not</c-> <c- n>satisfied</c->
            <c- n>source</c-><c- p>.</c-><c- n>cpp</c-><c- p>(</c-><c- mi>16</c-><c- p>,</c-><c- mi>10</c-><c- p>)</c-><c- o>:</c->
            <c- n>the</c-> <c- k>concept</c-> '<c- n>pettable</c-><lizard>' <c- n>evaluated</c-> <c- n>to</c-> false
                <c- n>source</c-><c- p>.</c-><c- n>cpp</c-><c- p>(</c-><c- mi>14</c-><c- p>,</c-><c- mi>20</c-><c- p>)</c-><c- o>:</c->
                <c- n>the</c-> <c- k>concept</c-> '<c- n>has_member_pet</c-><lizard>' <c- n>evaluated</c-> <c- n>to</c-> false
                    <c- n>source</c-><c- p>.</c-><c- n>cpp</c-><c- p>(</c-><c- mi>8</c-><c- p>,</c-><c- mi>44</c-><c- p>)</c-><c- o>:</c->
                    '<c- n>pet</c->'<c- o>:</c-> <c- n>is</c-> <c- k>not</c-> <c- n>a</c-> <c- n>member</c-> <c- n>of</c-> '<c- n>lizard</c->'
                    <c- n>source</c-><c- p>.</c-><c- n>cpp</c-><c- p>(</c-><c- mi>18</c-><c- p>,</c-><c- mi>8</c-><c- p>)</c-><c- o>:</c->
                    <c- n>see</c-> <c- n>declaration</c-> <c- n>of</c-> '<c- n>lizard</c->'
                <c- n>source</c-><c- p>.</c-><c- n>cpp</c-><c- p>(</c-><c- mi>14</c-><c- p>,</c-><c- mi>41</c-><c- p>)</c-><c- o>:</c->
                <c- n>the</c-> <c- k>concept</c-> '<c- n>has_default_pet</c-><lizard>' <c- n>evaluated</c-> <c- n>to</c-> false
                    <c- n>source</c-><c- p>.</c-><c- n>cpp</c-><c- p>(</c-><c- mi>11</c-><c- p>,</c-><c- mi>30</c-><c- p>)</c-><c- o>:</c->
                    '<c- n>is_pettable</c->'<c- o>:</c-> <c- n>is</c-> <c- k>not</c-> <c- n>a</c-> <c- n>member</c-> <c- n>of</c-> '<c- n>lizard</c->'
                    <c- n>source</c-><c- p>.</c-><c- n>cpp</c-><c- p>(</c-><c- mi>18</c-><c- p>,</c-><c- mi>8</c-><c- p>)</c-><c- o>:</c->
                    <c- n>see</c-> <c- n>declaration</c-> <c- n>of</c-> '<c- n>lizard</c->'
    <c- n>source</c-><c- p>.</c-><c- n>cpp</c-><c- p>(</c-><c- mi>21</c-><c- p>,</c-><c- mi>5</c-><c- p>)</c-><c- o>:</c->
    <c- k>while</c-> <c- n>trying</c-> <c- n>to</c-> <c- n>match</c-> <c- n>the</c-> <c- n>argument</c-> <c- n>list</c-> '<c- p>(</c-><c- n>lizard</c-><c- p>)</c->'
</lizard></lizard></lizard></pre>
   <p>Note that each potential overload of <code class="highlight"><c- n>pet</c-></code> is considered and reasons for why the candidate is not valid are given for each as nested diagnostics. Furthermore, the constraint failures for <code class="highlight"><c- n>pettable</c-></code> are further nested, giving the reasons that the constituent constraints failed as well.</p>
   <p>This hierarchy is encoded in SARIF like so (heavily excerpted to only have relevant information):</p>
<pre class="language-json highlight"><c- p>{</c->
    <c- f>"jsonrpc"</c-><c- p>:</c-> <c- u>"2.0"</c-><c- p>,</c->
    <c- f>"method"</c-><c- p>:</c-> <c- u>"OnSarifResult"</c-><c- p>,</c->
    <c- f>"params"</c-><c- p>:</c-> <c- p>{</c->
        <c- f>"result"</c-><c- p>:</c-> <c- p>{</c->
            <c- f>"message"</c-><c- p>:</c-> <c- p>{</c->
                <c- f>"text"</c-><c- p>:</c-> <c- u>"'pet': no overloaded function could convert all the argument types"</c->
            <c- p>},</c->
            <c- f>"locations"</c-><c- p>:</c-> <c- p>[</c->
                <c- c1>//snip</c->
            <c- p>],</c->
            <c- f>"relatedLocations"</c-><c- p>:</c-> <c- p>[</c->
                <c- c1>//snip</c->
                <c- p>{</c->
                    <c- f>"message"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"text"</c-><c- p>:</c-> <c- u>"or       'void pet(_T0)'"</c->
                    <c- p>}</c->
                <c- p>},</c->
                <c- p>{</c->
                    <c- f>"message"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"text"</c-><c- p>:</c-> <c- u>"the associated constraints are not satisfied"</c->
                    <c- p>},</c->
                    <c- f>"properties"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"nestingLevel"</c-><c- p>:</c-> <c- mi>1</c->
                    <c- p>}</c->
                <c- p>},</c->
                <c- p>{</c->
                    <c- f>"message"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"text"</c-><c- p>:</c-> <c- u>"the concept 'pettable&lt;lizard>' evaluated to false"</c->
                    <c- p>},</c->
                    <c- f>"properties"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"nestingLevel"</c-><c- p>:</c-> <c- mi>2</c->
                    <c- p>}</c->
                <c- p>},</c->
                <c- p>{</c->
                    <c- f>"message"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"text"</c-><c- p>:</c-> <c- u>"the concept 'has_member_pet&lt;lizard>' evaluated to false"</c->
                    <c- p>},</c->
                    <c- f>"properties"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"nestingLevel"</c-><c- p>:</c-> <c- mi>3</c->
                    <c- p>}</c->
                <c- p>},</c->
                <c- p>{</c->
                    <c- f>"message"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"text"</c-><c- p>:</c-> <c- u>"'pet': is not a member of 'lizard'"</c->
                    <c- p>},</c->
                    <c- f>"properties"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"nestingLevel"</c-><c- p>:</c-> <c- mi>4</c->
                    <c- p>}</c->
                <c- p>},</c->
                <c- p>{</c->
                    <c- f>"message"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"text"</c-><c- p>:</c-> <c- u>"see declaration of 'lizard'"</c->
                    <c- p>},</c->
                    <c- f>"properties"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"nestingLevel"</c-><c- p>:</c-> <c- mi>4</c->
                    <c- p>}</c->
                <c- p>},</c->
                <c- p>{</c->
                    <c- f>"message"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"text"</c-><c- p>:</c-> <c- u>"the concept 'has_default_pet&lt;lizard>' evaluated to false"</c->
                    <c- p>},</c->
                    <c- f>"properties"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"nestingLevel"</c-><c- p>:</c-> <c- mi>3</c->
                    <c- p>}</c->
                <c- p>},</c->
                <c- p>{</c->
                    <c- f>"message"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"text"</c-><c- p>:</c-> <c- u>"'is_pettable': is not a member of 'lizard'"</c->
                    <c- p>},</c->
                    <c- f>"properties"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"nestingLevel"</c-><c- p>:</c-> <c- mi>4</c->
                    <c- p>}</c->
                <c- p>},</c->
                <c- p>{</c->
                    <c- f>"message"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"text"</c-><c- p>:</c-> <c- u>"see declaration of 'lizard'"</c->
                    <c- p>},</c->
                    <c- f>"properties"</c-><c- p>:</c-> <c- p>{</c->
                        <c- f>"nestingLevel"</c-><c- p>:</c-> <c- mi>4</c->
                    <c- p>}</c->
                <c- p>},</c->
                <c- c1>//snip</c->
            <c- p>]</c->
        <c- p>}</c->
    <c- p>}</c->
<c- p>}</c->
</pre>
   <p>The compiler outputs SARIF that may include additional information to represent the nested structure of some diagnostics. A diagnostic may contain a "diagnostic tree" of additional information in its relatedLocations field. This tree is encoded using a SARIF <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141790698">property bag</a> as follows:</p>
   <p>A location object’s <code class="highlight"><c- n>properties</c-></code> field may contain a <code class="highlight"><c- n>nestingLevel</c-></code> property whose value is the depth of this location in the diagnostic tree. If a location doesn’t have a <code class="highlight"><c- n>nestingLevel</c-></code> specified, the <code class="highlight"><c- n>depth</c-></code> is considered to be <code class="highlight"><c- mi>0</c-></code> and this location is a child of the root diagnostic represented by the <code class="highlight"><c- n>result</c-></code> object containing it. Otherwise, if the value is greater than the depth of the location immediately preceding this location in the <code class="highlight"><c- n>relatedLocations</c-></code> field, this location is a child of that location. Otherwise, this location is a sibling of the closest preceding location in the <code class="highlight"><c- n>relatedLocations</c-></code> field with the same depth.</p>
   <p>Property bags in SARIF allow tools to generate SARIF with extended information that some SARIF consumers can use to display additional information. As such, the <code class="highlight"><c- n>properties</c-><c- p>.</c-><c- n>nestingLevel</c-></code> property of a <code class="highlight"><c- n>result</c-></code> object, while supported by the standard, is not understood by other tools.</p>
   <p>Clang is considering adopting hierarchical diagnostics in addition to MSVC, and there’s an <a href="https://discourse.llvm.org/t/rfc-restructure-clangs-diagnostic-objects-to-allow-for-nested-diagnostics/70249">RFC for it</a>.</p>
   <h2 class="heading settled" data-level="5" id="suggested-direction"><span class="secno">5. </span><span class="content">Suggested Direction</span><a class="self-link" href="#suggested-direction"></a></h2>
   <p>This section captures a direction that I propose tooling and the SARIF standard take in order to make the best experience for C++ users.</p>
   <h3 class="heading settled" data-level="5.1" id="sarif-standard"><span class="secno">5.1. </span><span class="content">SARIF Standard</span><a class="self-link" href="#sarif-standard"></a></h3>
   <p>The SARIF standard should adopt a standard way for expressing hierarchical diagnostics. There is an <a href="https://github.com/oasis-tcs/sarif-spec/issues/572">existing issue</a> on the SARIF standard GitHub page that is tracking this.</p>
   <h3 class="heading settled" data-level="5.2" id="build-systems"><span class="secno">5.2. </span><span class="content">Build Systems</span><a class="self-link" href="#build-systems"></a></h3>
   <p>IDEs and other tools that interact with build systems need a way to retrieve SARIF from running builds. It would likely be possible for tools to find SARIF files on disk (so long as the relevant command line flags are passed to the compiler) and read them, but this requires the entire compilation to complete before diagnostics can be shown to users. This could be a problem for compilations that take a long time (for example, ones with huge template instantiation trees, or unity builds).</p>
   <p>A more user-friendly approach is to enable streaming SARIF from the compiler to the IDE, facilitated by the build system. For example, the build system could use a similar approach to that currently used by MSVC and MS Build by opening a named pipe in a set location that tools can read from in order to retrieve SARIF <code class="highlight"><c- n>result</c-></code> objects on the fly.</p>
   <p>In addition, compiler-agnostic build tools such as CMake should ideally have a way to enable streaming SARIF output on any compiler that supports it. This would require marshalling the data all the way from the compiler, through the native build system, through CMake, and potentially to an IDE. For example, a user could add something like this to their <code class="highlight"><c- n>CMakeLists</c-><c- p>.</c-><c- n>txt</c-></code> file:</p>
<pre class="language-cmake highlight">target_compile_features<c- p>(</c-><c- s>my_target</c-> <c- s>PRIVATE</c-> <c- s>sarif_streaming</c-><c- p>)</c->
</pre>
   <p>This would set up the build in such a way that IDEs can retrieve the streamed data using the specified method.</p>
   <h3 class="heading settled" data-level="5.3" id="compilers①"><span class="secno">5.3. </span><span class="content">Compilers</span><a class="self-link" href="#compilers①"></a></h3>
   <p>MSVC, Clang, and GCC all support SARIF in some form. However, all three support producing it in slightly different ways:</p>
   <ul>
    <li data-md>
     <p>MSVC: anonymous pipe or filesystem</p>
    <li data-md>
     <p>GCC: <code class="highlight"><c- n>stderr</c-></code> or filesystem</p>
    <li data-md>
     <p>Clang: <code class="highlight"><c- n>stderr</c-></code> only</p>
   </ul>
   <p>Furthermore, the command line options for the filesystem outut for MSVC and GCC are different: GCC computes a filename based on the input source file, producing one SARIF file per source file, whereas MSVC puts everything into a single SARIF file with a given name.</p>
   <p>MSVC is the only compiler that supports the streaming of individual SARIF <code class="highlight"><c- n>result</c-></code> objects during the compilation in an easily-consumable way. Ideally, all three compilers would support both writing out to a file, and streaming <code class="highlight"><c- n>result</c-></code> objects. For example, GCC’s command line syntax could be extended to support <code class="highlight"><c- o>-</c-><c- n>fdiagnostics</c-><c- o>-</c-><c- n>format</c-><c- o>=</c-><c- n>sarif</c-><c- o>-</c-><c- n>rpc</c-><c- o>-</c-><c- n>stderr</c-></code>, in which case <code class="highlight"><c- n>result</c-></code> objects would be streamed out to <code class="highlight"><c- n>stderr</c-></code> during compilation using the JSON-RPC format that MSVC currently uses.</p>
   <p>MSVC is the only compiler that supports hierarchical diagnostics deeper than two levels, using the extension specified in <a href="#hierarchical-diagnostics">§ 4 Hierarchical Diagnostics</a>. GCC and Clang produce two levels of hierarchy with the <code class="highlight"><c- n>location</c-></code> and <code class="highlight"><c- n>related</c-><c- o>-</c-><c- n>locations</c-></code> properties of <code class="highlight"><c- n>result</c-></code> objects. Ideally, all compilers would support this, especially for concepts errors. For example, GCC currently has the <code class="highlight"><c- o>-</c-><c- n>fconcepts</c-><c- o>-</c-><c- n>diagnostic</c-><c- o>-</c-><c- n>depth</c-></code> flag that controls how deep to issue diagnostics for for Concepts. One could imagine this depth making it into the SARIF object and expressed explicitly in the diagnostic hierarchy.</p>
   <h3 class="heading settled" data-level="5.4" id="ides①"><span class="secno">5.4. </span><span class="content">IDEs</span><a class="self-link" href="#ides①"></a></h3>
   <p>As noted in <a href="#ides">§ 3.3 IDEs/Editors</a>, some IDEs and editors have native support for SARIF and some have extensions that can visualize SARIF information. Ideally, major C++ IDEs will be able to show hierarchical SARIF information produced by compilers while the compilation is executing, in a way similar to Visual Studio’s Problem Details Window.</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>