<!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>P1152R0: Deprecating &lt;code>volatile&lt;/code></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
 *
 * 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)
 *   - .assertion  for assertions                    (div, p, span)
 *   - .advisement for loud normative statements     (div, p, strong)
 *   - .annoying-warning for spec obsoletion notices (div, aside, details)
 *
 * 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
 *
 * 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)
 *
 ******************************************************************************/

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

	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;

		/* Colors */
		color: black;
		background: white 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-width: .65rem .7rem .6rem;
		border-radius: .4rem;
		background: #1a5e9a;
		color: white;
		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;
		border-color: #c00;
	}

	/* 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: 2;
			bottom: 0; left: 0;
			margin: 0;
			min-width: 1.33em;
			border-top-right-radius: 2rem;
			box-shadow: 0 0 2px;
			font-size: 1.5em;
			color: black;
		}
		#toc-nav > a {
			display: block;
			white-space: nowrap;

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

			background: white;
			box-shadow: 0 0 2px;
			border: none;
			border-top-right-radius: 1.33em;
			background: white;
		}
		#toc-nav > #toc-jump {
			padding-bottom: 2em;
			margin-bottom: -1.9em;
		}

		#toc-nav > a:hover,
		#toc-nav > a:focus {
			background: #f8f8f8;
		}
		#toc-nav > a:not(:hover):not(:focus) {
			color: #707070;
		}

		/* 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-toggle-inline {
			vertical-align: 0.05em;
			font-size: 80%;
			color: gray;
			color: hsla(203,20%,40%,.7);
			border-style: none;
			background: transparent;
			position: relative;
		}
		#toc-toggle-inline:hover:not(:active),
		#toc-toggle-inline:focus:not(:active) {
			text-shadow: 1px 1px silver;
			top: -1px;
			left: -1px;
		}

		#toc-nav :active {
			color: #C00;
		}
	}

/** 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);
			background: inherit;
			background-color: #f7f8f9;
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) 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);
		}
		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);
			background: inherit;
			background-color: #f7f8f9;
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) 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);
		}

		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;
		background: transparent;
	}

	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,
	#subtitle {
		/* #subtitle 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) > hr {
		font-size: 1.5em;
		text-align: center;
		margin: 1em auto;
		height: auto;
		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;
	}

	/* Put nice boxes around each algorithm. */
	[data-algorithm]:not(.heading) {
	  padding: .5em;
	  border: thin solid #ddd; 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: medium;
	}
	dfn var {
		font-style: normal;
	}

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

	del { color: red;  text-decoration: line-through; }
	ins { color: #080; text-decoration: underline;    }

/** 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;
		page-break-inside: avoid;
		hyphens: none;
		text-transform: none;
	}
	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;
		text-decoration: none;
		border-bottom: 1px solid #707070;
		/* Need a bit of extending for it to look okay */
		padding: 0 1px 0;
		margin: 0 -1px 0;
	}
	a:visited {
		border-bottom-color: #BBB;
	}

	/* Use distinguishing colors when user is interacting with the link */
	a[href]:focus,
	a[href]:hover {
		background: #f8f8f8;
		background: rgba(75%, 75%, 75%, .25);
		border-bottom-width: 3px;
		margin-bottom: -2px;
	}
	a[href]:active {
		color: #C00;
		border-color: #C00;
	}

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

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

	img {
		border-style: none;
	}

	/* 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;
	}
	.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 {
		padding: .5em;
		border: .5em;
		border-left-style: solid;
		page-break-inside: avoid;
	}
	span.issue, span.note {
		padding: .1em .5em .15em;
		border-right-style: solid;
	}

	.issue,
	.note,
	.example,
	.advisement,
	.assertion,
	blockquote {
		margin: 1em auto;
	}
	.note  > p:first-child,
	.issue > p:first-child,
	blockquote > :first-child {
		margin-top: 0;
	}
	blockquote > :last-child {
		margin-bottom: 0;
	}

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

	blockquote {
		border-color: silver;
	}

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

	.issue {
		border-color: #E05252;
		background: #FBE9E9;
		counter-increment: issue;
		overflow: auto;
	}
	.issue::before, .issue > .marker {
		text-transform: uppercase;
		color: #AE1E1E;
		padding-right: 1em;
		text-transform: uppercase;
	}
	/* 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;
		background: #FCFAEE;
		counter-increment: example;
		overflow: auto;
		clear: both;
	}
	.example::before, .example > .marker {
		text-transform: uppercase;
		color: #827017;
		min-width: 7.5em;
		display: block;
	}
	/* 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;
		background: #E9FBE9;
		overflow: auto;
	}

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

	details.note > summary {
		display: block;
		color: hsl(120, 70%, 30%);
	}
	details.note[open] > summary {
		border-bottom: 1px silver solid;
	}

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

	.assertion {
		border-color: #AAA;
		background: #EEE;
	}

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

	.advisement {
		border-color: orange;
		border-style: none solid;
		background: #FFEECC;
	}
	strong.advisement {
		display: block;
		text-align: center;
	}
	.advisement > .marker {
		color: #B35F00;
	}

/** 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: #fdd;
		color: red;
		font-weight: bold;
		padding: .75em 1em;
		border: thick red;
		border-style: solid;
		border-radius: 1em;
	}
	.annoying-warning :last-child {
		margin-bottom: 0;
	}

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

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

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

	.def {
		padding: .5em 1em;
		background: #DEF;
		margin: 1.2em 0;
		border-left: 0.5em solid #8CCBF2;
	}

/******************************************************************************/
/*                                    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;
	}

	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-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;
		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;
		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-top: 0.1rem;
		/* Larger, more consistently-sized click target */
		display: block;
		/* Reverse color scheme */
		color: black;
		border-color: #3980B5;
		border-bottom-width: 3px !important;
		margin-bottom: 0px !important;
	}
	.toc a:visited {
		border-color: #054572;
	}
	.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;
		line-height: 1.1rem; /* consistent spacing */
	}

	/* 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 .secno { font-size: 85%; }
	.toc > li li li li li { font-size:   85%;    }
	.toc > li li li li li .secno { font-size: 100%; }

	/* @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 {
			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; }
		}
	/* } */

	@supports (display:grid) {
		/* 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;
		}
		#toc .content:hover {
			background: rgba(75%, 75%, 75%, .25);
			border-bottom: 3px solid #054572;
			margin-bottom: -3px;
		}
		#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 span {
			white-space: nowrap;
			color: transparent; }
		ul.index li a:hover + span,
		ul.index li a:focus + span {
			color: #707070;
		}
	}

/** 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]) {
		background: #f7f8f9;
	}

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

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

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

/******************************************************************************/
/*                                    Legacy                                  */
/******************************************************************************/

	/* This rule is inherited from past style sheets. No idea what it's for. */
	.hide { display: none }



/******************************************************************************/
/*                             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 > table {
		/* limit preferred width of table */
		max-width: 50em;
		margin-left: auto;
		margin-right: auto;
	}

	@media (min-width: 55em) {
		.overlarge {
			margin-left: calc(13px + 26.5rem - 50vw);
			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-left: calc(40em - 50vw) !important;
			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-left: 0 !important;
			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 type="text/css">
    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;
    }
  </style>
  <meta content="Bikeshed version b39e6e3f91be18b7c7027813f7128b3087ae9333" name="generator">
  <link href="http://wg21.link/P1152R0" rel="canonical">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
  <meta content="7a53e67a1ddc6ef85c70559a18e40bfcfa07dd6c" name="document-revision">
<style>
blockquote.book {
  display: block;
  border-width: 2px 0;
  border-style: solid;
  border-color: #eee;
  padding: 1.5em 5em 0.5em 5em;
  margin: 1.5em 0;
  position: relative;
  text-align: justify;
}
blockquote.book:before {
  content: '\201C';
  position: absolute;
  top: 0em;
  left: 50%;
  transform: translate(-50%, -50%);
  background: #fff;
  width: 3rem;
  height: 2rem;
  font: 6em/1.08em 'PT Sans', sans-serif;
  color: #666;
  text-align: center;
}
blockquote.book:after {
  content: '\201D';
  position: absolute;
  bottom: -0.25em;
  left: 50%;
  transform: translate(-50%, -50%);
  background: #fff;
  width: 3rem;
  height: 2rem;
  font: 6em/1.08em 'PT Sans', sans-serif;
  color: #666;
  text-align: center;
}
cite {
  display: block;
  text-align: right;
  color: #e74c3c;
  margin: 0 -5em 1em 0;
}
</style>
<style>
.counts {
  margin: 0 auto;
}
.counts tr td:nth-child(2) {
  text-align: center;
}
</style>
<style>/* 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>/* 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>/* style-syntax-highlighting */

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

.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%;
}
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: gray;
    color: white;
    font-style: normal;
    transition: opacity .2s, background-color .2s, color .2s;
}
dfn:hover > a.self-link {
    opacity: 1;
}
dfn > a.self-link:hover {
    color: black;
}

a.self-link::before            { content: "¶"; }
.heading > a.self-link::before { content: "§"; }
dfn > a.self-link::before      { content: "#"; }</style>
<style>/* style-autolinks */

.css.css, .property.property, .descriptor.descriptor {
    color: #005a9c;
    font-size: inherit;
    font-family: inherit;
}
.css::before, .property::before, .descriptor::before {
    content: "‘";
}
.css::after, .property::after, .descriptor::after {
    content: "’";
}
.property, .descriptor {
    /* Don't wrap property and descriptor names */
    white-space: nowrap;
}
.type { /* CSS value <type> */
    font-style: italic;
}
pre .property::before, pre .property::after {
    content: "";
}
[data-link-type="property"]::before,
[data-link-type="propdesc"]::before,
[data-link-type="descriptor"]::before,
[data-link-type="value"]::before,
[data-link-type="function"]::before,
[data-link-type="at-rule"]::before,
[data-link-type="selector"]::before,
[data-link-type="maybe"]::before {
    content: "‘";
}
[data-link-type="property"]::after,
[data-link-type="propdesc"]::after,
[data-link-type="descriptor"]::after,
[data-link-type="value"]::after,
[data-link-type="function"]::after,
[data-link-type="at-rule"]::after,
[data-link-type="selector"]::after,
[data-link-type="maybe"]::after {
    content: "’";
}

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

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

[data-link-type=biblio] {
    white-space: pre;
}</style>
 <body class="h-entry">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">P1152R0<br>Deprecating <code class="highlight"><c- k>volatile</c-></code></h1>
   <h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Published Proposal, <time class="dt-updated" datetime="2018-10-01">2018-10-01</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="http://wg21.link/P1152R0">http://wg21.link/P1152R0</a>
     <dt>Issue Tracking:
     <dd><a href="#issues-index">Inline In Spec</a>
     <dt>Author:
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:jfbastien@apple.com">JF Bastien</a> (<span class="p-org org">Apple</span>)
     <dt>Audience:
     <dd>SG1, LEWG, EWG
     <dt>Project:
     <dd>ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
     <dt>Source:
     <dd><a href="https://github.com/jfbastien/papers/blob/master/source/D1152R0.bs">github.com/jfbastien/papers/blob/master/source/D1152R0.bs</a>
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </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="#abstract"><span class="secno">1</span> <span class="content">Abstract</span></a>
    <li><a href="#notw"><span class="secno">2</span> <span class="content">A Syntax of Three Parts</span></a>
    <li>
     <a href="#wmf"><span class="secno">3</span> <span class="content">The Wise Programmer’s Fear</span></a>
     <ol class="toc">
      <li><a href="#over"><span class="secno">3.1</span> <span class="content">Overview</span></a>
      <li><a href="#prop"><span class="secno">3.2</span> <span class="content">Proposed changes</span></a>
      <li><a href="#uses"><span class="secno">3.3</span> <span class="content">When is <code class="highlight"><c- k>volatile</c-></code> useful?</span></a>
      <li>
       <a href="#here"><span class="secno">3.4</span> <span class="content">How we got here</span></a>
       <ol class="toc">
        <li><a href="#inC"><span class="secno">3.4.1</span> <span class="content">Original intent for <code class="highlight"><c- k>volatile</c-></code> in C</span></a>
        <li><a href="#C89"><span class="secno">3.4.2</span> <span class="content">C89 intent</span></a>
        <li><a href="#CppIntent"><span class="secno">3.4.3</span> <span class="content">Intent in C++</span></a>
       </ol>
      <li><a href="#nowword"><span class="secno">3.5</span> <span class="content">Current Wording</span></a>
      <li>
       <a href="#why"><span class="secno">3.6</span> <span class="content">Why the proposed changes?</span></a>
       <ol class="toc">
        <li><a href="#extern"><span class="secno">3.6.1</span> <span class="content">External modification</span></a>
        <li><a href="#compound"><span class="secno">3.6.2</span> <span class="content">Compound assignment</span></a>
        <li><a href="#qual"><span class="secno">3.6.3</span> <span class="content"><code class="highlight"><c- k>volatile</c-></code> qualified member functions</span></a>
        <li><a href="#overloads"><span class="secno">3.6.4</span> <span class="content"><code class="highlight"><c- k>volatile</c-></code> overloads in the Library</span></a>
        <li><a href="#atomic"><span class="secno">3.6.5</span> <span class="content"><code class="highlight"><c- k>volatile</c-></code> atomic</span></a>
        <li><a href="#parret"><span class="secno">3.6.6</span> <span class="content"><code class="highlight"><c- k>volatile</c-></code> parameters and returns</span></a>
       </ol>
     </ol>
    <li><a href="#srst"><span class="secno">4</span> <span class="content">The Slow Regard of Syntactic Things</span></a>
    <li><a href="#dos"><span class="secno">5</span> <span class="content">The Doors of Stone</span></a>
    <li><a href="#ack"><span class="secno">6</span> <span class="content">Acknowledgements</span></a>
    <li><a href="#examples"><span class="secno">7</span> <span class="content">Examples</span></a>
    <li>
     <a href="#references"><span class="secno"></span> <span class="content">References</span></a>
     <ol class="toc">
      <li><a href="#informative"><span class="secno"></span> <span class="content">Informative References</span></a>
     </ol>
    <li><a href="#issues-index"><span class="secno"></span> <span class="content">Issues Index</span></a>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="abstract"><span class="secno">1. </span><span class="content">Abstract</span><a class="self-link" href="#abstract"></a></h2>
   <p>We propose deprecating most of <code class="highlight"><c- k>volatile</c-></code>. This paper explores <a href="#here">§3.4 How we got here</a>. See <a href="#prop">§3.2 Proposed changes</a> for a short overview, <a href="#why">§3.6 Why the proposed changes?</a> for details, and <a href="#examples">§7 Examples</a>. There
is currently no proposed wording: this paper tries to capture all of the
required context and lets WG21 choose whether to tackle everything at once or
incrementally.</p>
   <p>The proposed deprecation preserves the useful parts of <code class="highlight"><c- k>volatile</c-></code>, and removes
the dubious / already broken ones. This paper aims at breaking at compile-time
code which is today subtly broken at runtime or through a compiler update. The
paper might also break another type of code: that which doesn’t exist. This
removes a significant foot-gun and removes unintuitive corner cases from the
languages.</p>
   <h2 class="heading settled" data-level="2" id="notw"><span class="secno">2. </span><span class="content">A Syntax of Three Parts</span><a class="self-link" href="#notw"></a></h2>
   <blockquote class="book">
    <p>C and C++ have syntax for <code class="highlight"><c- k>volatile</c-></code>, and it is a syntax in three parts.</p>
    <p>The most obvious part is the abstract machine syntax, made by loads and stores
  present in the original program. If there is an expression that would have
  touched <code class="highlight"><c- k>volatile</c-></code> memory in the original source, it will generate
  instructions by which each byte will be touched exactly once. If there had
  been shared memory, a signal, even <code class="highlight"><c- n>setjmp</c-></code> / <code class="highlight"><c- n>longjmp</c-></code>, the <code class="highlight"><c- k>volatile</c-></code> would
  have filled the compiler with doubt, the slowness and preciseness one expects
  from a compiler during external modifications. If it had been part of the
  memory model… but no, of course, it isn’t part of the memory model. In fact
  there are none of these things, and so the syntax remains.</p>
    <p>Inside C, pairs of operations can huddle with <code class="highlight"><c- o>++</c-></code>, <code class="highlight"><c- o>--</c-></code>, or <code class="highlight"><c- n>op</c-><c- o>=</c-></code>. They’re
  used with quiet determination, avoiding serious code. In doing this with <code class="highlight"><c- k>volatile</c-></code> C adds a small, sullen syntax to the larger, hollow one. It makes
  an alloy of sorts, a counterpoint.</p>
    <p>The third syntax is not an easy thing to notice. If you read the Standard for
  hours, you might begin to notice it in the Standard Library under its
  specializations and in the rough, splintered applications of design
  guidelines. It adds weight to Generic Programs which hold the instantiations
  of templates long specialized. It is in the slow back and forth of code
  reviews rubbing out esoteric corner cases. And it is all in C++, adding to
  classes that already are qualified through <code class="highlight"><c- k>const</c-></code>.</p>
    <p>The C++ Committee can move with the subtle certainty that comes from knowing
  many things.</p>
    <p><code class="highlight"><c- k>volatile</c-></code> is ours, just as the third syntax is ours. This is appropriate, as
  it is the most onerous syntax of the three, wrapping the others inside itself.
  It is as deep and wide as <code class="highlight"><c- k>const</c-></code>-qualification. It is heavy as a great
  river-smooth stone. It is the patient, cut-flower syntax of a feature which is
  waiting to be deprecated.</p>
    <p><cite>— The Name of <code class="highlight"><c- k>volatile</c-></code> <sup>in the style of <a data-link-type="biblio" href="#biblio-notw">[NotW]</a></sup></cite></p>
   </blockquote>
   <h2 class="heading settled" data-level="3" id="wmf"><span class="secno">3. </span><span class="content">The Wise Programmer’s Fear</span><a class="self-link" href="#wmf"></a></h2>
   <blockquote class="book">
    <p>There are three things all wise programmers fear: C’s corner cases, a hardware
  platform with no documentation, and the anger of an optimizing compiler.</p>
    <p><cite>— The Name of <code class="highlight"><c- k>volatile</c-></code> <sup>in the style of <a data-link-type="biblio" href="#biblio-notw">[NotW]</a></sup></cite></p>
   </blockquote>
   <h3 class="heading settled" data-level="3.1" id="over"><span class="secno">3.1. </span><span class="content">Overview</span><a class="self-link" href="#over"></a></h3>
   <p><code class="highlight"><c- k>volatile</c-></code> is often revered as a sacred decree from C, yet very little is known
about what it actually means. Further, that knowledge is often disjoint from how <code class="highlight"><c- k>volatile</c-></code> is actually used. In this section we’ll lay out what we want to
change, explain what is useful, explain how the language got to where it is,
present what the C and C++ standards say and how they got there, and finally
we’ll justify what should be revised.</p>
   <h3 class="heading settled" data-level="3.2" id="prop"><span class="secno">3.2. </span><span class="content">Proposed changes</span><a class="self-link" href="#prop"></a></h3>
   <p>This proposal has the following goals:</p>
   <ol>
    <li data-md>
     <p>Continue supporting the time-honored usage of <code class="highlight"><c- k>volatile</c-></code> to load and store
 variables that are used for shared memory, signal handling, <code class="highlight"><c- n>setjmp</c-></code> / <code class="highlight"><c- n>longjmp</c-></code>, or other external modifications such as special hardware
 support.</p>
    <li data-md>
     <p>Deprecate (and eventually remove) <code class="highlight"><c- k>volatile</c-></code> compound assignment <code class="highlight"><c- n>op</c-><c- o>=</c-></code>, and
 pre / post increment / decrement <code class="highlight"><c- o>--</c-></code> <code class="highlight"><c- o>++</c-></code>.</p>
    <li data-md>
     <p>Deprecate (and eventually remove) <code class="highlight"><c- k>volatile</c-></code>-qualification of member
 functions. Don’t change <code class="highlight"><c- k>volatile</c-></code>-qualification of data members.</p>
    <li data-md>
     <p>Deprecate (and eventually remove) partial template specializations
 involving <code class="highlight"><c- k>volatile</c-></code>, overloads on <code class="highlight"><c- k>volatile</c-></code>, and qualified member
 functions for all but the <code class="highlight"><c- n>atomic</c-></code> and <code class="highlight"><c- n>numeric_limits</c-></code> parts of the
 Library.</p>
    <li data-md>
     <p>Deprecate (and eventually remove) <code class="highlight"><c- k>volatile</c-></code> member functions of <code class="highlight"><c- n>atomic</c-></code> in favor of new template partial specializations which will only declare <code class="highlight"><c- n>load</c-></code>, <code class="highlight"><c- n>store</c-></code>, and only exist when <code class="highlight"><c- n>is_always_lock_free</c-></code> is <code class="highlight">true</code>.
 Preserve most <code class="highlight"><c- k>volatile</c-></code> free function overloads for atomic.</p>
    <li data-md>
     <p>Deprecate (and eventually remove) non-reference and non-pointer <code class="highlight"><c- k>volatile</c-></code> parameters. Deprecate (and eventually remove) <code class="highlight"><c- k>const</c-></code> as well as <code class="highlight"><c- k>volatile</c-></code> return values. References and pointers <em>to</em> <code class="highlight"><c- k>volatile</c-></code> data remain valid.</p>
   </ol>
   <p>A rationale for each of these is provided in <a href="#why">§3.6 Why the proposed changes?</a>.</p>
   <h3 class="heading settled" data-level="3.3" id="uses"><span class="secno">3.3. </span><span class="content">When is <code class="highlight"><c- k>volatile</c-></code> useful?</span><a class="self-link" href="#uses"></a></h3>
   <blockquote class="book">
    <p>Knowing your own ignorance is the first step to enlightenment.</p>
    <p><cite>― The Wise Man’s Fear <sup><a data-link-type="biblio" href="#biblio-wmf">[WMF]</a></sup></cite></p>
   </blockquote>
   <p>Colloquially, <code class="highlight"><c- k>volatile</c-></code> tells the compiler to back off and not optimize code
too much. If the source code contains a load or store of a <code class="highlight"><c- k>volatile</c-></code> operation
then these should occur as many times in the final execution. A <code class="highlight"><c- k>volatile</c-></code> operation cannot be eliminated or fused with a subsequent one, even if the
compiler thinks that it can prove that it’s useless. A <code class="highlight"><c- k>volatile</c-></code> operation
cannot be speculated, even if the compiler can undo or otherwise make that
speculation benign.</p>
   <p>Importantly, <code class="highlight"><c- k>volatile</c-></code> does not guarantee that memory operations won’t tear,
meaning that a <code class="highlight"><c- k>volatile</c-></code> load may observe partial writes and <code class="highlight"><c- k>volatile</c-></code> stores
may be observed in parts. Realistically, compilers will only tear when the
hardware doesn’t have an instruction which can perform the entire memory
operation atomically. That being said, the Standard technically allows an
implementation which touched each target byte exactly once, one after the other,
in an unspecified order that could change on each execution.</p>
   <p>The order of <code class="highlight"><c- k>volatile</c-></code> operations cannot change relative to other <code class="highlight"><c- k>volatile</c-></code> operations, but may change relative to non-<code class="highlight"><c- k>volatile</c-></code> operations.</p>
   <p>That being said, <code class="highlight"><c- k>volatile</c-></code> doesn’t imply any observable ordering in terms of
the C++ memory model. Atomic instructions guarantee sequential consistency for
data-race free programs (data races are otherwise undefined behavior) <a data-link-type="biblio" href="#biblio-batty">[BATTY]</a>. <code class="highlight"><c- k>volatile</c-></code> has no such guarantee and doesn’t imply a memory ordering or any
fencing, though some implementations provide stronger guarantees (such as <a data-link-type="biblio" href="#biblio-xtensa">[XTENSA]</a> and <a data-link-type="biblio" href="#biblio-msvc">[MSVC]</a>). This is not in contradiction with the previous
paragraph: the <em>instructions</em> are emitted in a defined order, but processors can
issue and execute them out of order, and other cores may observe them in a
completely different order if no extra synchronization is used. Such
synchronization can come from implementation guarantees or hardware mapping
specifics.</p>
   <p><code class="highlight"><c- k>volatile</c-></code> is nonetheless a useful concept to have at the level of the language.
It is more practical than inline assembly because it lives within the language
and offers fairly portable semantics for load and store. It is more capable than
externally linked assembly functions (such as defined in <code class="highlight"><c- p>.</c-><c- n>S</c-></code> files) because
compilers don’t typically inline these functions.</p>
   <h3 class="heading settled" data-level="3.4" id="here"><span class="secno">3.4. </span><span class="content">How we got here</span><a class="self-link" href="#here"></a></h3>
   <p>When discussing <code class="highlight"><c- k>volatile</c-></code> in C++ it is important to understand that <code class="highlight"><c- k>volatile</c-></code> came from C, before either language acquired a memory model and acknowledged the
existence of threads.</p>
   <h4 class="heading settled" data-level="3.4.1" id="inC"><span class="secno">3.4.1. </span><span class="content">Original intent for <code class="highlight"><c- k>volatile</c-></code> in C</span><a class="self-link" href="#inC"></a></h4>
   <p><a data-link-type="biblio" href="#biblio-sebor">[SEBOR]</a> lays out the original intent for <code class="highlight"><c- k>volatile</c-></code> in C:</p>
   <blockquote>
    <p>The use case that motivated the introduction of the <code class="highlight"><c- k>volatile</c-></code> keyword into C
  was a variant of the following snippet copied from early UNIX sources <a data-link-type="biblio" href="#biblio-sysiii">[SysIII]</a>:</p>
<pre class="highlight"><c- cp>#define KL 0177560</c->

<c- k>struct</c-> <c- p>{</c-> <c- b>char</c-> <c- n>lobyte</c-><c- p>,</c-> <c- n>hibyte</c-><c- p>;</c-> <c- p>};</c->
<c- k>struct</c-> <c- p>{</c-> <c- b>int</c-> <c- n>ks</c-><c- p>,</c-> <c- n>kb</c-><c- p>,</c-> <c- n>ps</c-><c- p>,</c-> <c- n>pb</c-><c- p>;</c-> <c- p>};</c->

<c- n>getchar</c-><c- p>()</c-> <c- p>{</c->
    <c- k>register</c-> <c- n>rc</c-><c- p>;</c->
    <c- p>...</c->
    <c- k>while</c-> <c- p>(</c-><c- n>KL</c-><c- o>-></c-><c- n>ks</c-><c- p>.</c-><c- n>lobyte</c-> <c- o>>=</c-> <c- mi>0</c-><c- p>);</c->
    <c- n>rc</c-> <c- o>=</c-> <c- n>KL</c-><c- o>-></c-><c- n>kb</c-> <c- o>&amp;</c-> <c- mo>0177</c-><c- p>;</c->
    <c- p>...</c->
    <c- k>return</c-> <c- n>rc</c-><c- p>;</c->
<c- p>}</c->
</pre>
    <p>The desired effect of the while loop in the <code class="highlight"><c- n>getchar</c-><c- p>()</c-></code> function is to iterate
  until the most significant (sign) bit of the keyboard status register mapped
  to an address in memory represented by the <code class="highlight"><c- n>KL</c-></code> macro (the address of the
  memory-mapped <code class="highlight"><c- n>KBD_STAT</c-></code> I/O register on the PDP-11) has become non-zero,
  indicating that a key has been pressed, and then return the character value
  extracted from the low 7 bits corresponding to the pressed key. In order for
  the function to behave as expected, the compiler must emit an instruction to
  read a value from the I/O register on each iteration of the loop. In
  particular, the compiler must avoid caching the read value in a CPU register
  and substituting it in subsequent accesses.</p>
    <p>On the other hand, in situations where the memory location doesn’t correspond
  to a special memory-mapped register, it’s more efficient to avoid reading the
  value from memory if it happens to already have been read into a CPU register,
  and instead use the value cached in the CPU register.</p>
    <p>The problem is that without some sort of notation (in K&amp;R C there was none)
  there would be no way for a compiler to distinguish between these two cases.
  The following paragraph quoted from <em>The C Programming Language, Second
  Edition</em> <a data-link-type="biblio" href="#biblio-kr">[KR]</a>, by Kernighan and Ritchie, explains the solution that was
  introduced into standard C to deal with this problem: the <code class="highlight"><c- k>volatile</c-></code> keyword.</p>
    <blockquote>
     <p>The purpose of <code class="highlight"><c- k>volatile</c-></code> is to force an implementation to suppress optimization
    that could otherwise occur. For example, for a machine with memory-mapped
    input/output, a pointer to a device register might be declared as a pointer to <code class="highlight"><c- k>volatile</c-></code>, in order to prevent the compiler from removing apparently redundant
    references through the pointer.</p>
    </blockquote>
    <p>Using the <code class="highlight"><c- k>volatile</c-></code> keyword, it should then be possible to rewrite the loop
  in the snippet above as follows:</p>
<pre class="highlight"><c- k>while</c-> <c- p>(</c-><c- o>*</c-><c- p>(</c-><c- k>volatile</c-> <c- b>int</c-><c- o>*</c-><c- p>)</c-><c- o>&amp;</c-><c- n>KL</c-><c- o>-></c-><c- n>ks</c-><c- p>.</c-><c- n>lobyte</c-> <c- o>>=</c-> <c- mi>0</c-><c- p>);</c->
</pre>
    <p>or equivalently:</p>
<pre class="highlight"><c- k>volatile</c-> <c- b>int</c-> <c- o>*</c-><c- n>lobyte</c-> <c- o>=</c-> <c- o>&amp;</c-><c- n>KL</c-><c- o>-></c-><c- n>ks</c-><c- p>.</c-><c- n>lobyte</c-><c- p>;</c->
<c- k>while</c-> <c- p>(</c-><c- o>*</c-><c- n>lobyte</c-> <c- o>>=</c-> <c- mi>0</c-><c- p>);</c->
</pre>
    <p>and prevent the compiler from caching the value of the keyboard status
  register, thus guaranteeing that the register will be read once in each
  iteration.</p>
    <p>The difference between the two forms of the rewritten loop is of historical
  interest: Early C compilers are said to have recognized the first pattern
  (without the <code class="highlight"><c- k>volatile</c-></code> keyword) where the address used to access the register
  was a constant, and avoided the undesirable optimization for such accesses <a data-link-type="biblio" href="#biblio-gwyn">[GWYN]</a>. However, they did not have the same ability when the access was
  through pointer variable in which the address had been stored, especially not
  when the use of such a variable was far removed from the last assignment to
  it. The <code class="highlight"><c- k>volatile</c-></code> keyword was intended to allow both forms of the loop to
  work as expected.</p>
    <p>The use case exemplified by the loop above has since become idiomatic and is
  being extensively relied on in today’s software even beyond reading I/O
  registers.</p>
    <p>As a representative example, consider the Linux kernel which relies on <code class="highlight"><c- k>volatile</c-></code> in its implementation of synchronization primitives such as spin
  locks, or for performance counters. The variables that are operated on by
  these primitives are typically declared to be of unqualified (i.e., non <code class="highlight"><c- k>volatile</c-></code>) scalar types and allocated in ordinary memory. In serial code, for
  maximum efficiency, each such variable is read and written just like any other
  variable, with its value cached in a CPU register as compiler optimizations
  permit. At well-defined points in the code where such a variable may be
  accessed by more than one CPU at a time, the caching must be prevented and the
  variable must be accessed using the special <code class="highlight"><c- k>volatile</c-></code> semantics. To achieve
  that, the kernel defines two macros: <code class="highlight"><c- n>READ_ONCE</c-></code>, and <code class="highlight"><c- n>WRITE_ONCE</c-></code>, in whose
  terms the primitives are implemented. Each of the macros prevents the compiler
  optimization by casting the address of its argument to a <code class="highlight"><c- k>volatile</c-> <c- n>T</c-><c- o>*</c-></code> and
  accessing the variable via an lvalue of the <code class="highlight"><c- k>volatile</c-></code>-qualified type <code class="highlight"><c- n>T</c-></code> (where <code class="highlight"><c- n>T</c-></code> is one of the standard scalar types). Other primitives gurantee
  memory synchronization and visibility but those are orthogonal to the subject
  of this paper. See <a data-link-type="biblio" href="#biblio-p0124r5">[P0124R5]</a>.</p>
    <p>Similar examples can be found in other system or embedded programs as well as
  in many other pre-C11 and pre-C++11 code bases that don’t rely on the Atomic
  types and operations newly introduced in those standards. . They are often
  cited in programming books <a data-link-type="biblio" href="#biblio-cbook">[CBOOK]</a> and in online articles <a data-link-type="biblio" href="#biblio-intro">[INTRO]</a> <a data-link-type="biblio" href="#biblio-why">[WHY]</a> <a data-link-type="biblio" href="#biblio-whyc">[WHYC]</a>.</p>
   </blockquote>
   <h4 class="heading settled" data-level="3.4.2" id="C89"><span class="secno">3.4.2. </span><span class="content">C89 intent</span><a class="self-link" href="#C89"></a></h4>
   <p><a data-link-type="biblio" href="#biblio-rationale">[RATIONALE]</a> lays out the intent for <code class="highlight"><c- k>volatile</c-></code> in C89:</p>
   <blockquote>
    <p>The C89 Committee concluded that about the only thing a strictly conforming
  program can do in a signal handler is to assign a value to a volatile static
  variable which can be written uninterruptedly and promptly return.</p>
    <p>[…]</p>
    <p><code class="highlight"><c- k>volatile</c-></code>: No cacheing through this lvalue: each operation in the abstract
  semantics must be performed (that is, no cacheing assumptions may be made,
  since the location is not guaranteed to contain any previous value). In the
  absence of this qualifier, the contents of the designated location may be
  assumed to be unchanged except for possible aliasing.</p>
    <p>[…]</p>
    <p>A <code class="highlight"><c- k>static</c-> <c- k>volatile</c-></code> object is an appropriate model for a memory-mapped I/O
  register. Implementors of C translators should take into account relevant
  hardware details on the target systems when implementing accesses to <code class="highlight"><c- k>volatile</c-></code> objects. For instance, the hardware logic of a system may require
  that a two-byte memory-mapped register not be accessed with byte operations;
  and a compiler for such a system would have to assure that no such
  instructions were generated, even if the source code only accesses one byte of
  the register. Whether read-modify-write instructions can be used on such
  device registers must also be considered. Whatever decisions are adopted on
  such issues must be documented, as <code class="highlight"><c- k>volatile</c-></code> access is
  implementation-defined. A <code class="highlight"><c- k>volatile</c-></code> object is also an appropriate model for a
  variable shared among multiple processes.</p>
    <p>A <code class="highlight"><c- k>static</c-> <c- k>const</c-> <c- k>volatile</c-></code> object appropriately models a memory-mapped input
  port, such as a real-time clock. Similarly, a <code class="highlight"><c- k>const</c-> <c- k>volatile</c-></code> object models a
  variable which can be altered by another process but not by this one.</p>
    <p>[…]</p>
    <p>A cast of a value to a qualified type has no effect; the qualification
  (<code class="highlight"><c- k>volatile</c-></code>, say) can have no effect on the access since it has occurred prior
  to the cast. If it is necessary to access a non-<code class="highlight"><c- k>volatile</c-></code> object using <code class="highlight"><c- k>volatile</c-></code> semantics, the technique is to cast the address of the object to
  the appropriate pointer-to-qualified type, then dereference that pointer.</p>
    <p>[…]</p>
    <p>The C89 Committee also considered requiring that a call to <code class="highlight"><c- n>longjmp</c-></code> restore
  the calling environment fully, that is, that upon execution of <code class="highlight"><c- n>longjmp</c-></code>, all
  local variables in the environment of <code class="highlight"><c- n>setjmp</c-></code> have the values they did at the
  time of the <code class="highlight"><c- n>longjmp</c-></code> call. Register variables create problems with this idea.
  Unfortunately, the best that many implementations attempt with register
  variables is to save them in <code class="highlight"><c- b>jmp_buf</c-></code> at the time of the initial <code class="highlight"><c- n>setjmp</c-></code> call, then restore them to that state on each return initiated by a <code class="highlight"><c- n>longjmp</c-></code> call. Since compilers are certainly at liberty to change register variables to
  automatic, it is not obvious that a register declaration will indeed be rolled
  back. And since compilers are at liberty to change automatic variables to
  register if their addresses are never taken, it is not obvious that an
  automatic declaration will not be rolled back, hence the vague wording. In
  fact, the only reliable way to ensure that a local variable retain the value
  it had at the time of the call to <code class="highlight"><c- n>longjmp</c-></code> is to define it with the <code class="highlight"><c- k>volatile</c-></code> attribute.</p>
   </blockquote>
   <h4 class="heading settled" data-level="3.4.3" id="CppIntent"><span class="secno">3.4.3. </span><span class="content">Intent in C++</span><a class="self-link" href="#CppIntent"></a></h4>
   <p><code class="highlight"><c- k>volatile</c-></code> was extended to "fit" into C++ by allowing <code class="highlight"><c- k>volatile</c-></code>-qualification
to member functions. <a data-link-type="biblio" href="#biblio-de">[DE]</a> states:</p>
   <blockquote>
    <p>To match ANSI C, the <code class="highlight"><c- k>volatile</c-></code> modifier was introduced to help optimizer
  implementers. I am not at all sure that the syntactic parallel with <code class="highlight"><c- k>const</c-></code> is
  warranted by semantic similarities. However, I never had strong feelings
  about <code class="highlight"><c- k>volatile</c-></code> and see no reason to try to improve on the ANSI C committee’s
  decisions in this area.</p>
   </blockquote>
   <p>As threads and a formal model were added to C++ it was unclear what role <code class="highlight"><c- k>volatile</c-></code> should play. It was often advocated for multi-threaded applications <a data-link-type="biblio" href="#biblio-intro">[INTRO]</a>. This advice is incorrect as <a data-link-type="biblio" href="#biblio-robison">[ROBISON]</a> explains. Others, such as <a data-link-type="biblio" href="#biblio-alexandrescu">[ALEXANDRESCU]</a>, suggested using <code class="highlight"><c- k>volatile</c-></code> member functions to have the type
system enforce user annotations about thread safety. Various approaches were
suggested to improve visibility of writes in a memory model—such as <a data-link-type="biblio" href="#biblio-regehr">[REGEHR]</a>—but weren’t adopted for C++. <a data-link-type="biblio" href="#biblio-n2016">[N2016]</a> explains why <code class="highlight"><c- k>volatile</c-></code> shouldn’t acquire atomicity and thread visibility semantics. Further, <a data-link-type="biblio" href="#biblio-boehm">[BOEHM]</a> makes the a case that threads cannot be implemented as a library. A variety of
FAQs existed to help programmers make sense of the state of concurrency before
C++0x became C++11, for example <a data-link-type="biblio" href="#biblio-faq">[FAQ]</a>. The behavior of <code class="highlight"><c- k>volatile</c-></code> has slightly
changed over time <a data-link-type="biblio" href="#biblio-cwg1054">[CWG1054]</a> <a data-link-type="biblio" href="#biblio-change">[CHANGE]</a> <a data-link-type="biblio" href="#biblio-when">[WHEN]</a>. Importantly, C++11’s memory
model forbids the compiler from introducing races in otherwise correct code,
modulo compiler bugs <a data-link-type="biblio" href="#biblio-invalid">[INVALID]</a>.</p>
   <h3 class="heading settled" data-level="3.5" id="nowword"><span class="secno">3.5. </span><span class="content">Current Wording</span><a class="self-link" href="#nowword"></a></h3>
   <blockquote class="book">
    <p>C++ has flaws, but what does that matter when it comes to matters of the
  heart? We love what we love. Reason does not enter into it. In many ways,
  unwise love is the truest love. Anyone can love a thing <em>because</em>. That’s as
  easy as putting a penny in your pocket. But to love something <em>despite</em>. To
  know the flaws and love them too. That is rare and pure and perfect.</p>
    <p><cite>― The Wise Programmer’s Fear <sup>in the style of <a data-link-type="biblio" href="#biblio-wmf">[WMF]</a></sup></cite></p>
   </blockquote>
   <p>The above description doesn’t tell us <em>how</em> <code class="highlight"><c- k>volatile</c-></code> is used: it merely sets
out, informally, what it guarantees and what the intent was. What follows are
the formal guarantees provided by <code class="highlight"><c- k>volatile</c-></code>. As of this writing, the word <code class="highlight"><c- k>volatile</c-></code> appears 322 times in the current draft of the C++ Standard <a data-link-type="biblio" href="#biblio-draft">[DRAFT]</a>.
Here are the salient appearances from C++17 <a data-link-type="biblio" href="#biblio-n4659">[N4659]</a>:</p>
   <p>Program execution [<strong>intro.execution</strong>]</p>
   <blockquote>
    <p>Accesses through <code class="highlight"><c- k>volatile</c-></code> glvalues are evaluated strictly according to the
  rules of the abstract machine.</p>
    <p>Reading an object designated by a <code class="highlight"><c- k>volatile</c-></code> glvalue, modifying an object,
  calling a library I/O function, or calling a function that does any of those
  operations are all <em>side effects</em>, which are changes in the state of the
  execution environment. <em>Evaluation</em> of an expression (or a subexpression) in
  general includes both value computations (including determining the identity
  of an object for glvalue evaluation and fetching a value previously assigned
  to an object for prvalue evaluation) and initiation of side effects. When a
  call to a library I/O function returns or an access through a <code class="highlight"><c- k>volatile</c-></code> glvalue is evaluated the side effect is considered complete, even though some
  external actions implied by the call (such as the I/O itself) or by the <code class="highlight"><c- k>volatile</c-></code> access may not have completed yet.</p>
   </blockquote>
   <p>Data races [<strong>intro.races</strong>]</p>
   <blockquote>
    <p>Two accesses to the same object of type <code class="highlight"><c- k>volatile</c-></code> <code class="highlight"><c- n>std</c-><c- o>::</c-><c- b>sig_atomic_t</c-></code> do not
  result in a data race if both occur in the same thread, even if one or more
  occurs in a signal handler. For each signal handler invocation, evaluations
  performed by the thread invoking a signal handler can be divided into two
  groups A and B, such that no evaluations in B happen before evaluations in A,
  and the evaluations of such <code class="highlight"><c- k>volatile</c-></code> <code class="highlight"><c- n>std</c-><c- o>::</c-><c- b>sig_atomic_t</c-></code> objects take values
  as though all evaluations in A happened before the execution of the signal
  handler and the execution of the signal handler happened before all
  evaluations in B.</p>
   </blockquote>
   <p>Forward progress [<strong>intro.progress</strong>]</p>
   <blockquote>
    <p>The implementation may assume that any thread will eventually do one of the
  following:</p>
    <ul>
     <li data-md>
      <p>terminate,</p>
     <li data-md>
      <p>make a call to a library I/O function,</p>
     <li data-md>
      <p>perform an access through a <code class="highlight"><c- k>volatile</c-></code> glvalue, or</p>
     <li data-md>
      <p>perform a synchronization operation or an atomic operation</p>
    </ul>
    <p>During the execution of a thread of execution, each of the following is termed
  an execution step:</p>
    <ul>
     <li data-md>
      <p>termination of the thread of execution,</p>
     <li data-md>
      <p>performing an access through a <code class="highlight"><c- k>volatile</c-></code> glvalue, or</p>
     <li data-md>
      <p>completion of a call to a library I/O function, a synchronization
operation, or an atomic operation.</p>
    </ul>
   </blockquote>
   <p>Class member access [<strong>expr.ref</strong>]</p>
   <blockquote>
    <p>Abbreviating <em>postfix-expression.id-expression</em> as <code class="highlight"><c- n>E1</c-><c- p>.</c-><c- n>E2</c-></code>, <code class="highlight"><c- n>E1</c-></code> is called the <em>object expression</em>. If <code class="highlight"><c- n>E2</c-></code> is a bit-field, <code class="highlight"><c- n>E1</c-><c- p>.</c-><c- n>E2</c-></code> is a bit-field. The type
  and value category of <code class="highlight"><c- n>E1</c-><c- p>.</c-><c- n>E2</c-></code> are determined as follows. In the remainder of
  [<strong>expr.ref</strong>], <em>cq</em> represents either <code class="highlight"><c- k>const</c-></code> or the absence of <code class="highlight"><c- k>const</c-></code> and <em>vq</em> represents either <code class="highlight"><c- k>volatile</c-></code> or the absence of <code class="highlight"><c- k>volatile</c-></code>. <em>cv</em> represents an arbitrary set of cv-qualifiers.</p>
    <ul>
     <li data-md>
      <p>If <code class="highlight"><c- n>E2</c-></code> is a non-static data member and the type of <code class="highlight"><c- n>E1</c-></code> is “<em>cq1 vq1 X</em>”,
and the type of <code class="highlight"><c- n>E2</c-></code> is “<em>cq2 vq2 T</em>”, the expression designates the named
member of the object designated by the first expression. If <code class="highlight"><c- n>E1</c-></code> is an
lvalue, then <code class="highlight"><c- n>E1</c-><c- p>.</c-><c- n>E2</c-></code> is an lvalue; otherwise <code class="highlight"><c- n>E1</c-><c- p>.</c-><c- n>E2</c-></code> is an xvalue. Let the
notation <em>vq12</em> stand for the “union” of <em>vq1</em> and <em>vq2</em>; that is, if <em>vq1</em> or <em>vq2</em> is <code class="highlight"><c- k>volatile</c-></code>, then <em>vq12</em> is <code class="highlight"><c- k>volatile</c-></code>. Similarly, let the
notation <em>cq12</em> stand for the “union” of <em>cq1</em> and <em>cq2</em>; that is, if <em>cq1</em> or <em>cq2</em> is <code class="highlight"><c- k>const</c-></code>, then <em>cq12</em> is <code class="highlight"><c- k>const</c-></code>. If <code class="highlight"><c- n>E2</c-></code> is declared to be a <code class="highlight"><c- k>mutable</c-></code> member, then the type of <code class="highlight"><c- n>E1</c-><c- p>.</c-><c- n>E2</c-></code> is “<em>vq12 T</em>”. If <code class="highlight"><c- n>E2</c-></code> is not
declared to be a <code class="highlight"><c- k>mutable</c-></code> member, then the type of <code class="highlight"><c- n>E1</c-><c- p>.</c-><c- n>E2</c-></code> is
“<em>cq12 vq12 T</em>”.</p>
    </ul>
   </blockquote>
   <p>The cv-qualifiers [<strong>dcl.type.cv</strong>]</p>
   <blockquote>
    <p>The semantics of an access through a <code class="highlight"><c- k>volatile</c-></code> glvalue are
  implementation-defined. If an attempt is made to access an object defined with
  a <code class="highlight"><c- k>volatile</c-></code>-qualified type through the use of a non-<code class="highlight"><c- k>volatile</c-></code> glvalue, the
  behavior is undefined.</p>
    <p>[ <em>Note:</em> <code class="highlight"><c- k>volatile</c-></code> is a hint to the implementation to avoid aggressive
  optimization involving the object because the value of the object might be
  changed by means undetectable by an implementation. Furthermore, for some
  implementations, <code class="highlight"><c- k>volatile</c-></code> might indicate that special hardware instructions
  are required to access the object. See [<strong>intro.execution</strong>] for detailed
  semantics. In general, the semantics of <code class="highlight"><c- k>volatile</c-></code> are intended to be the same
  in C++ as they are in C. —<em>end note</em>]</p>
   </blockquote>
   <p>Non-static member functions [<strong>class.mfct.non-static</strong>]</p>
   <blockquote>
    <p>A non-static member function may be declared <code class="highlight"><c- k>const</c-></code>, <code class="highlight"><c- k>volatile</c-></code>, or <code class="highlight"><c- k>const</c-> <c- k>volatile</c-></code>. These cv-qualifiers affect the type of the <code class="highlight"><c- k>this</c-></code> pointer.
  They also affect the function type of the member function; a member
  function declared <code class="highlight"><c- k>const</c-></code> is a <code class="highlight"><c- k>const</c-></code> member function, a member function declared <code class="highlight"><c- k>volatile</c-></code> is a <code class="highlight"><c- k>volatile</c-></code> member function and a member function declared <code class="highlight"><c- k>const</c-> <c- k>volatile</c-></code> is a <code class="highlight"><c- k>const</c-> <c- k>volatile</c-></code> member function.</p>
   </blockquote>
   <p>The this pointer [<strong>class.this</strong>]</p>
   <blockquote>
    <p>In the body of a non-static member function, the keyword <code class="highlight"><c- k>this</c-></code> is a prvalue
   expression whose value is the address of the object for which the function is
   called. The type of <code class="highlight"><c- k>this</c-></code> in a member function of a class <code class="highlight"><c- n>X</c-></code> is <code class="highlight"><c- n>X</c-><c- o>*</c-></code>. If
   the member function is declared <code class="highlight"><c- k>const</c-></code>, the type of <code class="highlight"><c- k>this</c-></code> is <code class="highlight"><c- k>const</c-> <c- n>X</c-><c- o>*</c-></code>, if
   the member function is declared <code class="highlight"><c- k>volatile</c-></code>, the type of <code class="highlight"><c- k>this</c-></code> is <code class="highlight"><c- k>volatile</c-> <c- n>X</c-><c- o>*</c-></code>, and if the member function is declared <code class="highlight"><c- k>const</c-> <c- k>volatile</c-></code>, the type of <code class="highlight"><c- k>this</c-></code> is <code class="highlight"><c- k>const</c-> <c- k>volatile</c-> <c- n>X</c-><c- o>*</c-></code>.</p>
    <p><code class="highlight"><c- k>volatile</c-></code> semantics apply in <code class="highlight"><c- k>volatile</c-></code> member functions when accessing the
   object and its non-static data members.</p>
   </blockquote>
   <p>Constructors [<strong>class.ctor</strong>]</p>
   <blockquote>
    <p>A constructor can be invoked for a <code class="highlight"><c- k>const</c-></code>, <code class="highlight"><c- k>volatile</c-></code> or <code class="highlight"><c- k>const</c-> <c- k>volatile</c-></code> object. <code class="highlight"><c- k>const</c-></code> and <code class="highlight"><c- k>volatile</c-></code> semantics are not applied on an object under
  construction. They come into effect when the constructor for the most derived
  object ends.</p>
   </blockquote>
   <p>Destructors [<strong>class.dtor</strong>]</p>
   <blockquote>
    <p>A destructor is used to destroy objects of its class type. The address of a
  destructor shall not be taken. A destructor can be invoked for a <code class="highlight"><c- k>const</c-></code>, <code class="highlight"><c- k>volatile</c-></code> or <code class="highlight"><c- k>const</c-> <c- k>volatile</c-></code> object. <code class="highlight"><c- k>const</c-></code> and <code class="highlight"><c- k>volatile</c-></code> semantics are
  not applied on an object under destruction. They stop being in effect when the
  destructor for the most derived object starts.</p>
   </blockquote>
   <p>Overloadable declarations [<strong>over.load</strong>]</p>
   <blockquote>
    <p>Parameter declarations that differ only in the presence or absence of <code class="highlight"><c- k>const</c-></code> and/or <code class="highlight"><c- k>volatile</c-></code> are equivalent. That is, the <code class="highlight"><c- k>const</c-></code> and <code class="highlight"><c- k>volatile</c-></code> type-specifiers for each parameter type are ignored when determining which
  function is being declared, defined, or called.</p>
   </blockquote>
   <p>Built-in operators [<strong>over.built</strong>]</p>
   <blockquote>
    <p>In the remainder of this section, <em>vq</em> represents either <code class="highlight"><c- k>volatile</c-></code> or no
  cv-qualifier.</p>
    <p>For every pair (<em>T</em>, <em>vq</em>), where <em>T</em> is an arithmetic type other than <code class="highlight"><c- b>bool</c-></code>,
  there exist candidate operator functions of the form</p>
<pre class="highlight"><c- n>vq</c-> <c- n>T</c-> <c- o>&amp;</c-> <c- k>operator</c-><c- o>++</c-><c- p>(</c-><c- n>vq</c-> <c- n>T</c-> <c- o>&amp;</c-><c- p>);</c->
<c- n>T</c-> <c- k>operator</c-><c- o>++</c-><c- p>(</c-><c- n>vq</c-> <c- n>T</c-> <c- o>&amp;</c-><c- p>,</c-> <c- b>int</c-><c- p>);</c->
</pre>
    <p>For every pair (<em>T</em>, <em>vq</em>), where <em>T</em> is an arithmetic type other than <code class="highlight"><c- b>bool</c-></code>,
  there exist candidate operator functions of the form</p>
<pre class="highlight"><c- n>vq</c-> <c- n>T</c-> <c- o>&amp;</c-> <c- k>operator</c-><c- o>--</c-><c- p>(</c-><c- n>vq</c-> <c- n>T</c-> <c- o>&amp;</c-><c- p>);</c->
<c- n>T</c-> <c- k>operator</c-><c- o>--</c-><c- p>(</c-><c- n>vq</c-> <c- n>T</c-> <c- o>&amp;</c-><c- p>,</c-> <c- b>int</c-><c- p>);</c->
</pre>
    <p>For every pair (<em>T</em>, <em>vq</em>), where <em>T</em> is a cv-qualified or cv-unqualified
  object type, there exist candidate operator functions of the form</p>
<pre class="highlight"><c- n>T</c-><c- o>*</c-><c- n>vq</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>++</c-><c- p>(</c-><c- n>T</c-><c- o>*</c-><c- n>vq</c-><c- o>&amp;</c-><c- p>);</c->
<c- n>T</c-><c- o>*</c-><c- n>vq</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>--</c-><c- p>(</c-><c- n>T</c-><c- o>*</c-><c- n>vq</c-><c- o>&amp;</c-><c- p>);</c->
<c- n>T</c-><c- o>*</c-> <c- k>operator</c-><c- o>++</c-><c- p>(</c-><c- n>T</c-><c- o>*</c-><c- n>vq</c-><c- o>&amp;</c-><c- p>,</c-> <c- b>int</c-><c- p>);</c->
<c- n>T</c-><c- o>*</c-> <c- k>operator</c-><c- o>--</c-><c- p>(</c-><c- n>T</c-><c- o>*</c-><c- n>vq</c-><c- o>&amp;</c-><c- p>,</c-> <c- b>int</c-><c- p>);</c->
</pre>
    <p>For every quintuple (<em>C1</em>, <em>C2</em>, <em>T</em>, <em>cv1</em>, <em>cv2</em>), where <em>C2</em> is a class
  type, <em>C1</em> is the same type as <em>C2</em> or is a derived class of <em>C2</em>, and <em>T</em> is an
  object type or a function type, there exist candidate operator functions of
  the form</p>
<pre class="highlight"><c- n>cv12</c-> <c- n>T</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>->*</c-><c- p>(</c-><c- n>cv1</c-> <c- n>C1</c-><c- o>*</c-><c- p>,</c-> <c- n>cv2</c-> <c- n>T</c-> <c- n>C2</c-><c- o>::*</c-><c- p>);</c->
</pre>
    <p>For every triple (<em>L</em>, <em>vq</em>, <em>R</em>), where <em>L</em> is an arithmetic type, and <em>R</em> is
  a promoted arithmetic type, there exist candidate operator functions of the
  form</p>
<pre class="highlight"><c- n>vq</c-> <c- n>L</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>=</c-><c- p>(</c-><c- n>vq</c-> <c- n>L</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>R</c-><c- p>);</c->
<c- n>vq</c-> <c- n>L</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>*=</c-><c- p>(</c-><c- n>vq</c-> <c- n>L</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>R</c-><c- p>);</c->
<c- n>vq</c-> <c- n>L</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>/=</c-><c- p>(</c-><c- n>vq</c-> <c- n>L</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>R</c-><c- p>);</c->
<c- n>vq</c-> <c- n>L</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>+=</c-><c- p>(</c-><c- n>vq</c-> <c- n>L</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>R</c-><c- p>);</c->
<c- n>vq</c-> <c- n>L</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>-=</c-><c- p>(</c-><c- n>vq</c-> <c- n>L</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>R</c-><c- p>);</c->
</pre>
    <p>For every pair (<em>T</em>, <em>vq</em>), where <em>T</em> is any type, there exist candidate
  operator functions of the form</p>
<pre class="highlight"><c- n>T</c-><c- o>*</c-><c- n>vq</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>=</c-><c- p>(</c-><c- n>T</c-><c- o>*</c-><c- n>vq</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>T</c-><c- o>*</c-><c- p>);</c->
</pre>
    <p>For every pair (<em>T</em>, <em>vq</em>), where <em>T</em> is an enumeration or pointer to member
  type, there exist candidate operator functions of the form</p>
<pre class="highlight"><c- n>vq</c-> <c- n>T</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>=</c-><c- p>(</c-><c- n>vq</c-> <c- n>T</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>T</c-> <c- p>);</c->
</pre>
    <p>For every pair (<em>T</em>, <em>vq</em>), where <em>T</em> is a cv-qualified or cv-unqualified
  object type, there exist candidate operator functions of the form</p>
<pre class="highlight"><c- n>T</c-><c- o>*</c-><c- n>vq</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>+=</c-><c- p>(</c-><c- n>T</c-><c- o>*</c-><c- n>vq</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- b>ptrdiff_t</c-><c- p>);</c->
<c- n>T</c-><c- o>*</c-><c- n>vq</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>-=</c-><c- p>(</c-><c- n>T</c-><c- o>*</c-><c- n>vq</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- b>ptrdiff_t</c-><c- p>);</c->
</pre>
    <p>For every triple (<em>L</em>, <em>vq</em>, <em>R</em>), where <em>L</em> is an integral type, and <em>R</em> is a
  promoted integral type, there exist candidate operator functions of the form</p>
<pre class="highlight"><c- n>vq</c-> <c- n>L</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>%=</c-><c- p>(</c-><c- n>vq</c-><c- p>,</c-> <c- n>L</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>R</c-><c- p>);</c->
<c- n>vq</c-> <c- n>L</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>&lt;&lt;=</c-><c- p>(</c-><c- n>vq</c-><c- p>,</c-> <c- n>L</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>R</c-><c- p>);</c->
<c- n>vq</c-> <c- n>L</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>>>=</c-><c- p>(</c-><c- n>vq</c-><c- p>,</c-> <c- n>L</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>R</c-><c- p>);</c->
<c- n>vq</c-> <c- n>L</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>&amp;=</c-><c- p>(</c-><c- n>vq</c-><c- p>,</c-> <c- n>L</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>R</c-><c- p>);</c->
<c- n>vq</c-> <c- n>L</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>^=</c-><c- p>(</c-><c- n>vq</c-><c- p>,</c-> <c- n>L</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>R</c-><c- p>);</c->
<c- n>vq</c-> <c- n>L</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>|=</c-><c- p>(</c-><c- n>vq</c-><c- p>,</c-> <c- n>L</c-><c- o>&amp;</c-><c- p>,</c-> <c- n>R</c-><c- p>);</c->
</pre>
   </blockquote>
   <p>Here are salient appearances of <code class="highlight"><c- k>volatile</c-></code> in the C17 Standard:</p>
   <p>Type qualifiers</p>
   <blockquote>
    <p>An object that has <code class="highlight"><c- k>volatile</c-></code>-qualified type may be modified in ways unknown
   to the implementation or have other unknown side effects. Therefore any
   expression referring to such an object shall be evaluated strictly according
   to the rules of the abstract machine. Furthermore, at every sequence point
   the value last stored in the object shall agree with that prescribed by the
   abstract machine, except as modified by the unknown factors mentioned
   previously.<sup>†</sup> What constitutes an access to an object that has <code class="highlight"><c- k>volatile</c-></code>-qualified type is implementation-defined.</p>
    <p><sup>†</sup> A <code class="highlight"><c- k>volatile</c-></code> declaration may be used to describe an object
   corresponding to a memory-mapped input/output port or an object accessed by
   an asynchronously interrupting function. Actions on objects so declared shall
   not be "optimized out" by an implementation or reordered except as permitted
   by the rules for evaluating expressions.</p>
   </blockquote>
   <h3 class="heading settled" data-level="3.6" id="why"><span class="secno">3.6. </span><span class="content">Why the proposed changes?</span><a class="self-link" href="#why"></a></h3>
   <blockquote class="book">
    <p>Only priests and fools are fearless and I’ve never been on the best of terms
  with God.</p>
    <p><cite>— The Name of The Wind <sup><a data-link-type="biblio" href="#biblio-notw">[NotW]</a></sup></cite></p>
   </blockquote>
   <h4 class="heading settled" data-level="3.6.1" id="extern"><span class="secno">3.6.1. </span><span class="content">External modification</span><a class="self-link" href="#extern"></a></h4>
   <p>We’ve shown that <code class="highlight"><c- k>volatile</c-></code> is purposely defined to denote external
modifications. This happens for:</p>
   <ul>
    <li data-md>
     <p>Shared memory with untrusted code, where <code class="highlight"><c- k>volatile</c-></code> is the right way to
avoid time-of-check time-of-use (ToCToU) races which lead to security bugs
such as <a data-link-type="biblio" href="#biblio-pwn2own">[PWN2OWN]</a> and <a data-link-type="biblio" href="#biblio-xenxsa155">[XENXSA155]</a>.</p>
    <li data-md>
     <p>Signal handling, where at any time in a program’s execution a signal can
occur, and the optimizer must therefore make sure that <code class="highlight"><c- k>volatile</c-></code> operations
occur (even though they are allowed to tear).</p>
    <li data-md>
     <p><code class="highlight"><c- n>setjmp</c-></code> / <code class="highlight"><c- n>longjmp</c-></code>, where <code class="highlight"><c- n>setjmp</c-></code> can effectively return twice and <code class="highlight"><c- k>volatile</c-></code> is used to prevent motion of memory operations around this
operation. <code class="highlight"><c- n>atomic_signal_fence</c-></code> is a more coarse-grained solution to this
problem.</p>
    <li data-md>
     <p>Various other external modifications such as special hardware support—e.g.
memory-mapped registers—where the compiler cannot assume that memory doesn’t
change or that writes aren’t synchronizing externally.</p>
    <li data-md>
     <p>Marking that an infinite loop has side-effects and is therefore not
undefined behavior (this can also be done with atomic or I/O operations).</p>
    <li data-md>
     <p>Casting pointers to <code class="highlight"><c- k>volatile</c-></code> to denote code expecting <code class="highlight"><c- k>volatile</c-></code> semantics
(as opposed having this as a property of data). This type of code is
commonplace and we intend this paper to leave it alone, e.g. <a data-link-type="biblio" href="#biblio-torvalds">[TORVALDS]</a>.</p>
    <li data-md>
     <p>Enforcing control dependencies and preventing compiler value speculation
(such as through feedback-directed optimization) as discussed in <a data-link-type="biblio" href="#biblio-control">[CONTROL]</a>.</p>
    <li data-md>
     <p>Avoiding value speculation around some hand-rolled implementations of <code class="highlight"><c- n>memory_order_consume</c-></code> (until <a data-link-type="biblio" href="#biblio-p0750r1">[P0750R1]</a> is resolved).</p>
   </ul>
   <p>As <a data-link-type="biblio" href="#biblio-sebor">[SEBOR]</a> lays out there have been wording issues around this usage. <a data-link-type="biblio" href="#biblio-trouble">[TROUBLE]</a> and <a data-link-type="biblio" href="#biblio-access_once">[ACCESS_ONCE]</a> make a similar case. This paper doesn’t try to
address those issues. We don’t see a reason to change existing syntax denoting
external modification in this paper: this paper rather focuses on deprecation of <em>invalid</em> or <em>misleading</em> uses of <code class="highlight"><c- k>volatile</c-></code>. The above uses are valid and have
no alternative other than inline assembly.</p>
   <p><code class="highlight"><c- k>volatile</c-></code> deprecation / repurposing in any form wasn’t on the table when C++11
was standardized because existing code had no alternative but (sometimes
erroneous) <code class="highlight"><c- k>volatile</c-></code> coupled with inline assembly. Now that codebases use
atomic and have moved away from <em>erroneous</em> <code class="highlight"><c- k>volatile</c-></code>, we believe deprecation
is warranted. In other words, what would have been a disastrous breaking change
for C++11 is merely good house-cleaning for C++20.</p>
   <p>A new language would likely do things differently, but this paper isn’t about
creating a new language. Notably, <a data-link-type="biblio" href="#biblio-d">[D]</a> and <a data-link-type="biblio" href="#biblio-rust">[Rust]</a> took different approaches
(<code class="highlight"><c- n>peek</c-></code>/<code class="highlight"><c- n>poke</c-></code> and <code class="highlight"><c- n>unsafe</c-> <c- n>read_volatile</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> / <code class="highlight"><c- n>unsafe</c-> <c- n>write_volatile</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> respectively).</p>
   <p>Note that an important aspect of external modification for <code class="highlight"><c- k>volatile</c-></code> is <code class="highlight"><c- k>constexpr</c-></code>. As discussed in <a data-link-type="biblio" href="#biblio-cwg1688">[CWG1688]</a> a <code class="highlight"><c- k>constexpr</c-> <c- k>volatile</c-></code> is intentionally
permitted and could be used in some circumstances to force constant
initialization.</p>
   <h4 class="heading settled" data-level="3.6.2" id="compound"><span class="secno">3.6.2. </span><span class="content">Compound assignment</span><a class="self-link" href="#compound"></a></h4>
   <p><code class="highlight"><c- k>volatile</c-></code> external modifications are only truly meaningful for loads and
stores. Other read-modify-write operations imply touching the <code class="highlight"><c- k>volatile</c-></code> object
more than once per byte because that’s fundamentally how hardware works. Even
atomic instructions (remember: <code class="highlight"><c- k>volatile</c-></code> isn’t atomic) need to read <em>and</em> write
a memory location (e.g. x86’s <code class="highlight"><c- n>lock</c-> <c- n>addl</c-> $<c- mi>42</c-><c- p>,</c-> <c- p>(</c-><c- o>%</c-><c- n>rdi</c-><c- p>)</c-></code> won’t allow a race
between the read and write, but needs to both read and write, whereas ARM will
require a load-linked store-conditional loop to perform the same operation).
These RMW operations are therefore misleading and should be spelled out as
separate <code class="highlight"><c- n>read</c-> <c- p>;</c-> <c- n>modify</c-> <c- p>;</c-> <c- n>write</c-></code>, or use <code class="highlight"><c- k>volatile</c-></code> atomic operations which we
discuss below.</p>
   <p>We propose to deprecate, and eventually remove, <code class="highlight"><c- k>volatile</c-></code> compound assignment <code class="highlight"><c- n>op</c-><c- o>=</c-></code>, and pre / post increment / decrement <code class="highlight"><c- o>--</c-></code> <code class="highlight"><c- o>++</c-></code> of <code class="highlight"><c- k>volatile</c-></code> variables.
This is a departure from C which breaks source compatibility (once removed), but
maintains ABI compatibility.</p>
   <p class="issue" id="issue-c1a9b9d1"><a class="self-link" href="#issue-c1a9b9d1"></a> We would like guidance on <code class="highlight"><c- k>volatile</c-></code> when combined with <code class="highlight"><c- k>operator</c-><c- o>->*</c-></code>.
That guidance will depend on choices made with respect to <code class="highlight"><c- k>volatile</c-></code> aggregates.</p>
   <p class="issue" id="issue-16eb408f"><a class="self-link" href="#issue-16eb408f"></a> There’s a related problem in <a data-link-type="biblio" href="#biblio-trouble">[TROUBLE]</a> with chained assignments of <code class="highlight"><c- k>volatile</c-></code> values, such as <code class="highlight"><c- n>a</c-> <c- o>=</c-> <c- n>b</c-> <c- o>=</c-> <c- n>c</c-></code>. This is equally misleading, and it’s not
intuitive whether the value stored to <code class="highlight"><c- n>b</c-></code> is re-read before storing to <code class="highlight"><c- n>a</c-></code>. We
would like guidance on whether this is worth addressing.</p>
   <h4 class="heading settled" data-level="3.6.3" id="qual"><span class="secno">3.6.3. </span><span class="content"><code class="highlight"><c- k>volatile</c-></code> qualified member functions</span><a class="self-link" href="#qual"></a></h4>
   <p><code class="highlight"><c- k>volatile</c-></code>-qualification of member functions was added to C++ to parallel <code class="highlight"><c- k>const</c-></code>-qualification. Unlike <code class="highlight"><c- k>const</c-></code>-qualification this never truly got used
except for odd cases such as <a data-link-type="biblio" href="#biblio-alexandrescu">[ALEXANDRESCU]</a>. <a data-link-type="biblio" href="#biblio-de">[DE]</a> is clearly uncertain about
whether <code class="highlight"><c- k>volatile</c-></code>-qualification of member functions is warranted. This
mis-feature is either a heavy burden on Generic Programming, or something
Generic Programming purposely avoids supporting because it often doubles the
(already chatty) amount of Generic code.</p>
   <p>Let’s consider what <code class="highlight"><c- k>const</c-></code>-qualification truly means: a <code class="highlight"><c- k>class</c-></code> could be used
in a context where it can be mutated, as well as in a context where it cannot be
mutated. A member function can be declared <code class="highlight"><c- k>const</c-></code> to behave differently, and
this qualifier can be used to forbid usage of non-<code class="highlight"><c- k>const</c-></code> member functions when
a variable is <code class="highlight"><c- k>const</c-></code>. This doesn’t translate to <code class="highlight"><c- k>volatile</c-></code>: why would a <code class="highlight"><c- k>class</c-></code> <em>sometimes</em> map to hardware and sometimes not? And more importantly, <em>how</em> would
a member function meaningfully differ in those circumstances?</p>
   <p>It’s worth noting that <code class="highlight"><c- k>const</c-></code> constructors aren’t a thing: <code class="highlight"><c- k>const</c-></code> semantics
come into effect when the constructor for the most derived object ends. The same
applies to <code class="highlight"><c- k>volatile</c-></code>, but if the object was truly hardware-mapped or
potentially externally modified then it seems unwise to construct its members
without <code class="highlight"><c- k>volatile</c-></code> semantics. Ditto for destructors.</p>
   <p>We propose to deprecate, and eventually remove, <code class="highlight"><c- k>volatile</c-></code>-qualified member
functions.</p>
   <p>Our goal is to avoid the ambiguity where an aggregate is sometimes <code class="highlight"><c- k>volatile</c-></code> and sometimes not. The above proposal forces developers to recursively <code class="highlight"><c- k>volatile</c-></code>-qualify all non-aggregate data members. Alternatively, we could:</p>
   <ol>
    <li data-md>
     <p>Mandate that member functions <code class="highlight"><c- k>volatile</c-></code>-qualification be all-or-nothing; or</p>
    <li data-md>
     <p>Allow the aggregate declaration itself to be <code class="highlight"><c- k>volatile</c-></code> (e.g. <code class="highlight"><c- k>struct</c-> <c- k>volatile</c-> <c- n>my_hardware</c-> <c- p>{</c-> <c- d>/* ... */</c-> <c- p>};</c-></code>).</p>
    <li data-md>
     <p>Disallow <code class="highlight"><c- k>volatile</c-></code>-qualified aggregates entirely.</p>
   </ol>
   <p>Either of the first two approaches approaches clearly tell the compiler that
every data member access should be done in a <code class="highlight"><c- k>volatile</c-></code> manner, and disallows
accessing that particular aggregate in a non-<code class="highlight"><c- k>volatile</c-></code> manner. In all cases,
data members can still be <code class="highlight"><c- k>volatile</c-></code>-qualified.</p>
   <p class="issue" id="issue-c3997c0a"><a class="self-link" href="#issue-c3997c0a"></a> Which of the above approaches (deprecate <code class="highlight"><c- k>volatile</c-></code>-qualified member
functions, all-or-nothing, <code class="highlight"><c- k>struct</c-> <c- k>volatile</c-></code>, or deprecate <code class="highlight"><c- k>volatile</c-></code> aggregates, should we pursue?</p>
   <p class="issue" id="issue-5b42e15e"><a class="self-link" href="#issue-5b42e15e"></a> If we keep <code class="highlight"><c- k>volatile</c-></code> aggregates, it seems like <code class="highlight"><c- k>volatile</c-></code> aggregates
should have constructors which initialize all members with <code class="highlight"><c- k>volatile</c-></code> semantics,
and destroy them with <code class="highlight"><c- k>volatile</c-></code> semantics. Otherwise, we encourage the use of
initialization / cleanup member functions. Alternatively, triviality could be
mandated for constructors and destructors of <code class="highlight"><c- k>volatile</c-></code> aggregates. The author
is told by some embedded developers that it’s very common to have an aggregate
that describes some hardware, and to access hardware registers (member variables
of the aggregate) by indirection through a pointer to <code class="highlight"><c- k>volatile</c-></code> struct.</p>
   <p class="issue" id="issue-0ae133a2"><a class="self-link" href="#issue-0ae133a2"></a> If we keep <code class="highlight"><c- k>volatile</c-></code> aggregates, what does it mean to have a <code class="highlight"><c- k>volatile</c-></code> virtual function table pointer?</p>
   <p class="issue" id="issue-8a3b6c52"><a class="self-link" href="#issue-8a3b6c52"></a> It is unclear how <code class="highlight"><c- k>volatile</c-> <c- k>union</c-></code> should be accessed when all types in
the <code class="highlight"><c- k>union</c-></code> aren’t stored using the same bits (i.e. should <code class="highlight"><c- k>union</c-> <c- p>{</c-> <c- b>char</c-> <c- n>c</c-><c- p>;</c-> <c- b>int</c-> <c- n>i</c-><c- p>;</c-> <c- p>}</c-></code> always access the full union, even when only accessing <code class="highlight"><c- n>c</c-></code>?). Some
hardware defines different semantics to MMIO register accesses of different
sizes to the same address. A union would be a natural way to represent such
hardware. This could be outside the scope of the current paper.</p>
   <p class="issue" id="issue-601cb919"><a class="self-link" href="#issue-601cb919"></a> We would like guidance on whether <code class="highlight"><c- k>volatile</c-></code> bit-fields should be
constrained. At the moment no guarantee is made about read-modify-write
operations required when mixing <code class="highlight"><c- k>volatile</c-></code> and non-<code class="highlight"><c- k>volatile</c-></code> bit-field data
members. It seems like, at a minimum, bit fields should always cause alignment
when subsequent data members change their cv-qualification. This could be
outside the scope of the current paper.</p>
   <h4 class="heading settled" data-level="3.6.4" id="overloads"><span class="secno">3.6.4. </span><span class="content"><code class="highlight"><c- k>volatile</c-></code> overloads in the Library</span><a class="self-link" href="#overloads"></a></h4>
   <p>Partial template specializations involving <code class="highlight"><c- k>volatile</c-></code>, overloads on <code class="highlight"><c- k>volatile</c-></code>,
and qualified member functions are provided for the following classes:</p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- n>numeric_limits</c-></code></p>
    <li data-md>
     <p><code class="highlight"><c- n>tuple_size</c-></code></p>
    <li data-md>
     <p><code class="highlight"><c- n>tuple_element</c-></code></p>
    <li data-md>
     <p><code class="highlight"><c- n>variant_size</c-></code></p>
    <li data-md>
     <p><code class="highlight"><c- n>variant_alternative</c-></code></p>
    <li data-md>
     <p>atomic free function overloads</p>
    <li data-md>
     <p><code class="highlight"><c- n>atomic</c-></code> member functions</p>
   </ul>
   <p><code class="highlight"><c- n>numeric_limits</c-></code> is obviously useful and should stay. Atomic is discussed below.
Tuple and variant are odd in how they’re made to support <code class="highlight"><c- k>volatile</c-></code>, and we
wonder why other parts of the Library aren’t consistent. It’s unclear what
hardware mapping is expected from a tuple, and how a <code class="highlight"><c- k>volatile</c-></code> discriminated <code class="highlight"><c- k>union</c-></code> (such as variant) should be accessed.</p>
   <p>We propose to deprecate, and eventually remove, <code class="highlight"><c- k>volatile</c-></code> partial template
specializations, overloads, or qualified member functions for all but the <code class="highlight"><c- n>atomic</c-></code> and <code class="highlight"><c- n>numeric_limits</c-></code> parts of the Library.</p>
   <p>As of this writing, <code class="highlight"><c- k>volatile</c-></code> appears in libc++ as follows:</p>
   <table class="counts">
    <tbody>
     <tr>
      <th>Directory
      <th><code class="highlight"><c- k>volatile</c-></code> count
     <tr>
      <td><code class="highlight"><c- n>include</c-><c- o>/</c-><c- n>__functional_base</c-></code>
      <td>12
     <tr>
      <td><code class="highlight"><c- n>include</c-><c- o>/</c-><c- n>__tuple</c-></code>
      <td>12
     <tr>
      <td><code class="highlight"><c- n>include</c-><c- o>/</c-><c- n>atomic</c-></code>
      <td>175
     <tr>
      <td><code class="highlight"><c- n>include</c-><c- o>/</c-><c- n>chrono</c-></code>
      <td>2
     <tr>
      <td><code class="highlight"><c- n>include</c-><c- o>/</c-><c- n>limits</c-></code>
      <td>48
     <tr>
      <td><code class="highlight"><c- n>include</c-><c- o>/</c-><c- n>memory</c-></code>
      <td>2
     <tr>
      <td><code class="highlight"><c- n>include</c-><c- o>/</c-><c- n>mutex</c-></code>
      <td>1
     <tr>
      <td><code class="highlight"><c- n>include</c-><c- o>/</c-><c- n>scoped_allocator</c-></code>
      <td>1
     <tr>
      <td><code class="highlight"><c- n>include</c-><c- o>/</c-><c- n>type_traits</c-></code>
      <td>71
     <tr>
      <td><code class="highlight"><c- n>include</c-><c- o>/</c-><c- n>variant</c-></code>
      <td>8
     <tr>
      <td><code class="highlight"><c- n>src</c-><c- o>/</c-><c- n>mutex</c-><c- p>.</c-><c- n>cpp</c-></code>
      <td>1
   </table>
   <p class="issue" id="issue-3b9bc2e5"><a class="self-link" href="#issue-3b9bc2e5"></a> Should we go further and forbid <code class="highlight"><c- k>volatile</c-></code> in containers? Some containers
seem useful for signal handlers and such, however how loads and stores are
performed to these containers isn’t mandated by the Standard which means that to
use containers in signal handlers one needs to synchronize separately with <code class="highlight"><c- n>atomic_signal_fence</c-></code> and some form of token. Containers of <code class="highlight"><c- k>volatile</c-></code> data are
therefore misleading at best.</p>
   <h4 class="heading settled" data-level="3.6.5" id="atomic"><span class="secno">3.6.5. </span><span class="content"><code class="highlight"><c- k>volatile</c-></code> atomic</span><a class="self-link" href="#atomic"></a></h4>
   <p><code class="highlight"><c- k>volatile</c-></code> can tear, provides no ordering guarantees (with respect to
non-<code class="highlight"><c- k>volatile</c-></code> memory operations, and when it comes to CPU reordering), can
touch bytes exactly once, and inhibits optimizations. This is useful. <code class="highlight"><c- n>atomic</c-></code> cannot tear, has a full memory model, can require a loop to succeed, and can be
optimized <a data-link-type="biblio" href="#biblio-n4455">[N4455]</a>. This is also useful. <code class="highlight"><c- k>volatile</c-></code> atomic should offer the
union of these properties, but currently fails to do so:</p>
   <ul>
    <li data-md>
     <p>A non-lock-free atomic can be <code class="highlight"><c- k>volatile</c-></code>, in which case it can tear when the
issued instructions are considered.</p>
    <li data-md>
     <p>Read-modify-write operations are implemented as either loops which retry,
locked instructions (which still perform a load and a store), as
transactional memory operations, or as memory controller operations. Only
the last of these can truly be said to touch each byte exactly once, and
these hardware implementations are far from the norm.</p>
   </ul>
   <p>We propose to deprecate, and eventually remove, <code class="highlight"><c- k>volatile</c-></code> member functions of <code class="highlight"><c- n>atomic</c-></code> in favor of new template partial specializations which will only
declare <code class="highlight"><c- n>load</c-></code>, <code class="highlight"><c- n>store</c-></code>, and only exist when <code class="highlight"><c- n>is_always_lock_free</c-></code> is <code class="highlight">true</code>.</p>
   <p class="issue" id="issue-f23f6518"><a class="self-link" href="#issue-f23f6518"></a> We would like guidance on whether other read-modify-write operations
should be maintained with implementation-defined semantics. Specifically, <code class="highlight"><c- n>exchange</c-></code>, <code class="highlight"><c- n>compare_exchange_strong</c-></code>, <code class="highlight"><c- n>compare_exchange_weak</c-></code>, <code class="highlight"><c- n>fetch_add</c-></code> / <code class="highlight"><c- n>fetch_sub</c-></code> (for integral, pointer, and floating-point), and <code class="highlight"><c- n>fetch_and</c-></code> / <code class="highlight"><c- n>fetch_or</c-></code> / <code class="highlight"><c- n>fetch_xor</c-></code> (for integral), can be given useful semantics by an
implementation which wishes to guarantee that particular instructions will be
emitted. This would maintain the status-quo whereby <code class="highlight"><c- k>volatile</c-></code> is a
semi-portable abstraction for hardware, and still allows us to consider
deprecation in the future. Keeping these for now is the conservative option.</p>
   <p>The same guidance would apply to atomic free function overloads.</p>
   <h4 class="heading settled" data-level="3.6.6" id="parret"><span class="secno">3.6.6. </span><span class="content"><code class="highlight"><c- k>volatile</c-></code> parameters and returns</span><a class="self-link" href="#parret"></a></h4>
   <p>Marking parameters as <code class="highlight"><c- k>volatile</c-></code> makes sense to denote external modification
through signals or <code class="highlight"><c- n>setjmp</c-></code> / <code class="highlight"><c- n>longjmp</c-></code>. In that sense it’s similar to <code class="highlight"><c- k>const</c-></code>-qualified parameters: it has clear semantics <em>whithin</em> the function’s
implementation. However, it leaks function implementation information to the
caller. It also has no semantics when it comes to calling convention because it
is explicitly ignored (and must therefore have the same semantics as a
non-<code class="highlight"><c- k>volatile</c-></code> declaration). It’s much simpler to have the desirable behavior
above by copying a non-<code class="highlight"><c- k>volatile</c-></code> parameter to an automatic stack variable
marked <code class="highlight"><c- k>volatile</c-></code>. A compiler could, if stack passing is required by the ABI,
make no copy at all in this case.</p>
   <p><code class="highlight"><c- k>volatile</c-></code> return values are pure nonsense. Is register return disallowed? What
does it mean for return value optimization? A caller is better off declaring a <code class="highlight"><c- k>volatile</c-></code> automatic stack variable and assigning the function return to it, and
the caller will be none the wiser.</p>
   <p>Similarly, <code class="highlight"><c- k>const</c-></code> return values are actively harmful. Both cv-qualifiers
already have no effect when returning non-class types, and <code class="highlight"><c- k>const</c-></code>-qualified
class return types are harmful because they inhibit move semantics.</p>
   <p>We propose to deprecate, and eventually remove, non-reference and non-pointer <code class="highlight"><c- k>volatile</c-></code> parameters and return values. That is, <code class="highlight"><c- k>volatile</c-></code> at the outermost
level of the parameter type specification. We also propose to deprecate, and
eventually remove, <code class="highlight"><c- k>const</c-></code>-qualified return types.</p>
   <h2 class="heading settled" data-level="4" id="srst"><span class="secno">4. </span><span class="content">The Slow Regard of Syntactic Things</span><a class="self-link" href="#srst"></a></h2>
   <blockquote class="book">
    <p>This paper is for all the slightly broken features out there. <code class="highlight"><c- k>volatile</c-></code> is
  one of you. You are not alone. You are all beautiful to me.</p>
    <p><cite>— The Slow Regard of Syntactic Things <sup>in the style of <a data-link-type="biblio" href="#biblio-srst">[SRST]</a></sup></cite></p>
   </blockquote>
   <p>This proposal tries to balance real-world usage, real-world breakage, frequent
gotchas, and overly chatty features which aren’t actually used. The author
thinks it strikes the right balance, but may be wrong. <code class="highlight"><c- k>volatile</c-></code> may be better
suited with slower deprecation. <code class="highlight"><c- k>volatile</c-></code> might be one for direct removal
instead of deprecation. <code class="highlight"><c- k>volatile</c-></code> might prefer causing diagnostics. <code class="highlight"><c- k>volatile</c-></code> could even consider full deprecation and replacement with <code class="highlight"><c- n>volatile_load</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> / <code class="highlight"><c- n>volatile_store</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> free functions. <code class="highlight"><c- k>volatile</c-></code> might not suit aggregate types,
maybe it should only be allowed on scalars.</p>
   <p>It is important that <code class="highlight"><c- k>volatile</c-></code> dare be entirely itself, be wild enough to
change itself while somehow staying altogether <em>true</em>, lest we end up with The
Silent Regard of Slow Things. Annex C should be updated, WG14 should be
consulted.</p>
   <h2 class="heading settled" data-level="5" id="dos"><span class="secno">5. </span><span class="content">The Doors of Stone</span><a class="self-link" href="#dos"></a></h2>
   <p>This section will hold future work, wording, etc. It will be published based on
Committee feedback, when it is ready. The author wants to give the Committee a
perfectly worded paper. They deserve it.</p>
   <p>Here are items which could be discussed in the future:</p>
   <ol>
    <li data-md>
     <p><code class="highlight"><c- k>asm</c-></code> statements are implementation-defined. Many compilers also support <code class="highlight"><c- k>asm</c-> <c- k>volatile</c-></code> statements, which are also implementation-defined and not in
 scope for this paper.</p>
    <li data-md>
     <p>Standardize a library-like replacement for <code class="highlight"><c- k>volatile</c-></code> load / store, such as <code class="highlight"><c- n>peek</c-></code> / <code class="highlight"><c- n>poke</c-></code>.</p>
   </ol>
   <h2 class="heading settled" data-level="6" id="ack"><span class="secno">6. </span><span class="content">Acknowledgements</span><a class="self-link" href="#ack"></a></h2>
   <p>Early drafts were reviewed by the C++ Committee’s Direction Group, Thomas
Rodgers, Arthur O’Dwyer, John McCall, Mike Smith, John Regehr, Herb Sutter,
Shafik Yaghmour, Hans Boehm, Richard Smith, Will Deacon, Paul McKenney. Thank
you for in-depth feedback, and apologies if I mistakenly transcribed your
feedback.</p>
   <p>Patrick Rothfuss, for writing amazing books. May he take as much time as needed
to ensure forward progress of book 3.</p>
   <h2 class="heading settled" data-level="7" id="examples"><span class="secno">7. </span><span class="content">Examples</span><a class="self-link" href="#examples"></a></h2>
   <p>Here are dubious uses of <code class="highlight"><c- k>volatile</c-></code>.</p>
<pre class="highlight"><c- k>struct</c-> <c- n>foo</c-> <c- p>{</c->
  <c- b>int</c-> <c- nl>a</c-> <c- p>:</c-> <c- mi>4</c-><c- p>;</c->
  <c- b>int</c-> <c- nl>b</c-> <c- p>:</c-> <c- mi>2</c-><c- p>;</c->
<c- p>};</c->
<c- k>volatile</c-> <c- n>foo</c-> <c- n>f</c-><c- p>;</c->
<c- c1>// Which instructions get generated? Does this touch the bytes more than once?</c->
<c- n>f</c-><c- p>.</c-><c- n>a</c-> <c- o>=</c-> <c- mi>3</c-><c- p>;</c->
</pre>
<pre class="highlight"><c- k>struct</c-> <c- n>foo</c-> <c- p>{</c->
  <c- k>volatile</c-> <c- b>int</c-> <c- nl>a</c-> <c- p>:</c-> <c- mi>4</c-><c- p>;</c->
  <c- b>int</c-> <c- nl>b</c-> <c- p>:</c-> <c- mi>2</c-><c- p>;</c->
<c- p>};</c->
<c- n>foo</c-> <c- n>f</c-><c- p>;</c->
<c- n>f</c-><c- p>.</c-><c- n>b</c-> <c- o>=</c-> <c- mi>1</c-><c- p>;</c-> <c- c1>// Can this touch a?</c->
</pre>
<pre class="highlight"><c- k>union</c-> <c- n>foo</c-> <c- p>{</c->
  <c- b>char</c-> <c- n>c</c-><c- p>;</c->
  <c- b>int</c-> <c- n>i</c-><c- p>;</c->
<c- p>};</c->
<c- k>volatile</c-> <c- n>foo</c-> <c- n>f</c-><c- p>;</c->
<c- c1>// Must this touch sizeof(int) bytes? Or just sizeof(char) bytes?</c->
<c- n>f</c-><c- p>.</c-><c- n>c</c-> <c- o>=</c-> <c- mi>42</c-><c- p>;</c->
</pre>
<pre class="highlight"><c- k>volatile</c-> <c- b>int</c-> <c- n>i</c-><c- p>;</c->
<c- c1>// Can each of these touch the bytes only once?</c->
<c- n>i</c-> <c- o>+=</c-> <c- mi>42</c-><c- p>;</c->
<c- o>++</c-><c- n>i</c-><c- p>;</c->
</pre>
<pre class="highlight"><c- k>volatile</c-> <c- b>int</c-> <c- n>i</c-><c- p>,</c-> <c- n>j</c-><c- p>,</c-> <c- n>k</c-><c- p>;</c->
<c- c1>// Does this reload j before storing to i?</c->
<c- n>i</c-> <c- o>=</c-> <c- n>j</c-> <c- o>=</c-> <c- n>k</c-><c- p>;</c->
</pre>
<pre class="highlight"><c- k>struct</c-> <c- n>big</c-> <c- p>{</c-> <c- b>int</c-> <c- n>arr</c-><c- p>[</c-><c- mi>32</c-><c- p>];</c-> <c- p>};</c->
<c- k>volatile</c-> <c- n>_Atomic</c-> <c- k>struct</c-> <c- n>big</c-> <c- n>ba</c-><c- p>;</c->
<c- k>struct</c-> <c- n>big</c-> <c- n>b2</c-><c- p>;</c->
<c- c1>// Can this tear?</c->
<c- n>ba</c-> <c- o>=</c-> <c- n>b2</c-><c- p>;</c->
</pre>
<pre class="highlight"><c- b>int</c-> <c- nf>what</c-><c- p>(</c-><c- k>volatile</c-> <c- n>std</c-><c- o>::</c-><c- n>atomic</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- o>*</c-><c- n>atom</c-><c- p>)</c-> <c- p>{</c->
    <c- b>int</c-> <c- n>expected</c-> <c- o>=</c-> <c- mi>42</c-><c- p>;</c->
    <c- c1>// Can this touch the bytes more than once?</c->
    <c- n>atom</c-><c- o>-></c-><c- n>compare_exchange_strong</c-><c- p>(</c-><c- n>expected</c-><c- p>,</c-> <c- mh>0xdead</c-><c- p>);</c->
    <c- k>return</c-> <c- n>expected</c-><c- p>;</c->
<c- p>}</c->
</pre>
<pre class="highlight"><c- b>void</c-> <c- nf>what_does_the_caller_care</c-><c- p>(</c-><c- k>volatile</c-> <c- b>int</c-><c- p>);</c->
</pre>
<pre class="highlight"><c- k>volatile</c-> <c- b>int</c-> <c- nf>nonsense</c-><c- p>(</c-><c- b>void</c-><c- p>);</c->
</pre>
<pre class="highlight"><c- k>struct</c-> <c- n>retme</c-> <c- p>{</c-> <c- b>int</c-> <c- n>i</c-><c- p>,</c-> <c- n>j</c-><c- p>;</c-> <c- p>};</c->
<c- k>volatile</c-> <c- k>struct</c-> <c- n>retme</c-> <c- nf>silly</c-><c- p>(</c-><c- b>void</c-><c- p>);</c->
</pre>
<pre class="highlight"><c- k>struct</c-> <c- n>device</c-> <c- p>{</c->
  <c- b>unsigned</c-> <c- n>reg</c-><c- p>;</c->
  <c- n>device</c-><c- p>()</c-> <c- o>:</c-> <c- n>reg</c-><c- p>(</c-><c- mh>0xc0ffee</c-><c- p>)</c-> <c- p>{}</c->
  <c- o>~</c-><c- n>device</c-><c- p>()</c-> <c- p>{</c-> <c- n>reg</c-> <c- o>=</c-> <c- mh>0xdeadbeef</c-><c- p>;</c-> <c- p>}</c->
<c- p>};</c->
<c- k>volatile</c-> <c- n>device</c-> <c- n>dev</c-><c- p>;</c-> <c- c1>// Initialization and destruction aren’t volatile.</c->
</pre>
  </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>
  <h2 class="no-num no-ref heading settled" id="references"><span class="content">References</span><a class="self-link" href="#references"></a></h2>
  <h3 class="no-num no-ref heading settled" id="informative"><span class="content">Informative References</span><a class="self-link" href="#informative"></a></h3>
  <dl>
   <dt id="biblio-access_once">[ACCESS_ONCE]
   <dd>corbet. <a href="https://lwn.net/Articles/508991/">ACCESS_ONCE()</a>. 2012-08-01. URL: <a href="https://lwn.net/Articles/508991/">https://lwn.net/Articles/508991/</a>
   <dt id="biblio-alexandrescu">[ALEXANDRESCU]
   <dd>Andrei Alexandrescu. <a href="http://www.drdobbs.com/cpp/volatile-the-multithreaded-programmers-b/184403766">volatile: The Multithreaded Programmer's Best Friend</a>. 2001-02-01. URL: <a href="http://www.drdobbs.com/cpp/volatile-the-multithreaded-programmers-b/184403766">http://www.drdobbs.com/cpp/volatile-the-multithreaded-programmers-b/184403766</a>
   <dt id="biblio-batty">[BATTY]
   <dd>Mark Batty; et al. <a href="https://www.cl.cam.ac.uk/~pes20/cppppc/popl079-batty.pdf">Clarifying and Compiling C/C++ Concurrency: from C++11 to POWER</a>. 2012-01-25. URL: <a href="https://www.cl.cam.ac.uk/~pes20/cppppc/popl079-batty.pdf">https://www.cl.cam.ac.uk/~pes20/cppppc/popl079-batty.pdf</a>
   <dt id="biblio-boehm">[BOEHM]
   <dd>Hans Boehm. <a href="http://www.hpl.hp.com/techreports/2004/HPL-2004-209.pdf">Threads Cannot be Implemented as a Library</a>. 2004-11-12. URL: <a href="http://www.hpl.hp.com/techreports/2004/HPL-2004-209.pdf">http://www.hpl.hp.com/techreports/2004/HPL-2004-209.pdf</a>
   <dt id="biblio-cbook">[CBOOK]
   <dd>Mike Banahan; Declan Brady. <a href="http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html">The C Book</a>. URL: <a href="http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html">http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html</a>
   <dt id="biblio-change">[CHANGE]
   <dd><a href="https://stackoverflow.com/questions/20242868/correct-behaviour-of-trivial-statements-involving-expressions-with-volatile-vari">Correct behaviour of trivial statements involving expressions with volatile variables?</a>. 2013-11-27. URL: <a href="https://stackoverflow.com/questions/20242868/correct-behaviour-of-trivial-statements-involving-expressions-with-volatile-vari">https://stackoverflow.com/questions/20242868/correct-behaviour-of-trivial-statements-involving-expressions-with-volatile-vari</a>
   <dt id="biblio-control">[CONTROL]
   <dd>David Howells; et al. <a href="https://github.com/torvalds/linux/blob/7876320f88802b22d4e2daf7eb027dd14175a0f8/Documentation/memory-barriers.txt#L666">Linux kernel memory barriers: control dependencies</a>. 2018-07-17. URL: <a href="https://github.com/torvalds/linux/blob/7876320f88802b22d4e2daf7eb027dd14175a0f8/Documentation/memory-barriers.txt#L666">https://github.com/torvalds/linux/blob/7876320f88802b22d4e2daf7eb027dd14175a0f8/Documentation/memory-barriers.txt#L666</a>
   <dt id="biblio-cwg1054">[CWG1054]
   <dd>Hans Boehm. <a href="https://wg21.link/cwg1054">Lvalue-to-rvalue conversions in expression statements</a>. 16 March 2010. C++11. URL: <a href="https://wg21.link/cwg1054">https://wg21.link/cwg1054</a>
   <dt id="biblio-cwg1688">[CWG1688]
   <dd>Daniel Krügler. <a href="https://wg21.link/cwg1688">Volatile constexpr variables</a>. 18 May 2013. NAD. URL: <a href="https://wg21.link/cwg1688">https://wg21.link/cwg1688</a>
   <dt id="biblio-d">[D]
   <dd>Walter Bright. <a href="https://issues.dlang.org/show_bug.cgi?id=13138">DLang issue #13138: add peek/poke as compiler intrinsics</a>. 2014-07-16. URL: <a href="https://issues.dlang.org/show_bug.cgi?id=13138">https://issues.dlang.org/show_bug.cgi?id=13138</a>
   <dt id="biblio-de">[DE]
   <dd>Bjarne Stroustrup. The Design and Evolution of C++. 1994. 
   <dt id="biblio-draft">[DRAFT]
   <dd><a href="https://github.com/cplusplus/draft/search?l=TeX&amp;q=volatile">C++ Standards draft: volatile</a>. URL: <a href="https://github.com/cplusplus/draft/search?l=TeX&amp;q=volatile">https://github.com/cplusplus/draft/search?l=TeX&amp;q=volatile</a>
   <dt id="biblio-faq">[FAQ]
   <dd>Hans Boehm; Paul McKenney. <a href="http://www.hboehm.info/c++mm/user-faq.html">Programming with Threads: Questions Frequently Asked by C and C++ Programmers</a>. URL: <a href="http://www.hboehm.info/c++mm/user-faq.html">http://www.hboehm.info/c++mm/user-faq.html</a>
   <dt id="biblio-gwyn">[GWYN]
   <dd><a href="https://groups.google.com/forum/#!msg/comp.std.c/tHvQhiKFtD4/zfIgJhbkCXcJ">A question on volatile accesses</a>. URL: <a href="https://groups.google.com/forum/#!msg/comp.std.c/tHvQhiKFtD4/zfIgJhbkCXcJ">https://groups.google.com/forum/#!msg/comp.std.c/tHvQhiKFtD4/zfIgJhbkCXcJ</a>
   <dt id="biblio-intro">[INTRO]
   <dd>Nigel Jones. <a href="https://www.embedded.com/electronics-blogs/beginner-s-corner/4023801/Introduction-to-the-Volatile-Keyword">Introduction to the volatile keyword</a>. 2001-07-02. URL: <a href="https://www.embedded.com/electronics-blogs/beginner-s-corner/4023801/Introduction-to-the-Volatile-Keyword">https://www.embedded.com/electronics-blogs/beginner-s-corner/4023801/Introduction-to-the-Volatile-Keyword</a>
   <dt id="biblio-invalid">[INVALID]
   <dd>Viktor Vafeiadis; et al. <a href="https://people.mpi-sws.org/~viktor/papers/popl2015-c11comp.pdf">Common compiler optimisations are invalid in the C11 memory model and what we can do about it</a>. 2015/05-11. URL: <a href="https://people.mpi-sws.org/~viktor/papers/popl2015-c11comp.pdf">https://people.mpi-sws.org/~viktor/papers/popl2015-c11comp.pdf</a>
   <dt id="biblio-kr">[KR]
   <dd>Dennis Ritchie; Brian Kernighan. The C Programming Language. 1978. 
   <dt id="biblio-msvc">[MSVC]
   <dd><a href="https://msdn.microsoft.com/en-us/library/12a04hfd.aspx">Visual Studio: C++ Language Reference > Basic Concepts > Declarations and Definitions > volatile (C++)</a>. URL: <a href="https://msdn.microsoft.com/en-us/library/12a04hfd.aspx">https://msdn.microsoft.com/en-us/library/12a04hfd.aspx</a>
   <dt id="biblio-n2016">[N2016]
   <dd>H. Boehm, N. Maclaren. <a href="https://wg21.link/n2016">Should volatile Acquire Atomicity and Thread Visibility Semantics?</a>. 21 April 2006. URL: <a href="https://wg21.link/n2016">https://wg21.link/n2016</a>
   <dt id="biblio-n4455">[N4455]
   <dd>JF Bastien. <a href="https://wg21.link/n4455">No Sane Compiler Would Optimize Atomics</a>. 10 April 2015. URL: <a href="https://wg21.link/n4455">https://wg21.link/n4455</a>
   <dt id="biblio-n4659">[N4659]
   <dd>Richard Smith. <a href="https://wg21.link/n4659">Working Draft, Standard for Programming Language C++ Note:</a>. 21 March 2017. URL: <a href="https://wg21.link/n4659">https://wg21.link/n4659</a>
   <dt id="biblio-notw">[NotW]
   <dd>Patrick Rothfuss. <a href="http://www.penguin.com/ajax/books/excerpt/9780756405892">The Name of the Wind</a>. 2007-03-27. URL: <a href="http://www.penguin.com/ajax/books/excerpt/9780756405892">http://www.penguin.com/ajax/books/excerpt/9780756405892</a>
   <dt id="biblio-p0124r5">[P0124R5]
   <dd>Paul E. McKenney, Ulrich Weigand, Andrea Parri, Boqun Feng. <a href="https://wg21.link/p0124r5">Linux-Kernel Memory Model</a>. 6 April 2018. URL: <a href="https://wg21.link/p0124r5">https://wg21.link/p0124r5</a>
   <dt id="biblio-p0750r1">[P0750R1]
   <dd>JF Bastien, Paul E. McKenney. <a href="https://wg21.link/p0750r1">Consume</a>. 11 February 2018. URL: <a href="https://wg21.link/p0750r1">https://wg21.link/p0750r1</a>
   <dt id="biblio-pwn2own">[PWN2OWN]
   <dd>lokihardt. <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=468936">Chromium pwn2own GPU bug</a>. 2015-03-19. URL: <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=468936">https://bugs.chromium.org/p/chromium/issues/detail?id=468936</a>
   <dt id="biblio-rationale">[RATIONALE]
   <dd><a href="http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf">Rationale for International Standard—Programming Languages—C</a>. 2003-04. URL: <a href="http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf">http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf</a>
   <dt id="biblio-regehr">[REGEHR]
   <dd>John Regehr; Nathan Cooprider; David Gay. <a href="https://www.cs.utah.edu/%7Eregehr/papers/plos06b.pdf">Atomicity and Visibility in Tiny Embedded Systems</a>. 2006-10-22. URL: <a href="https://www.cs.utah.edu/%7Eregehr/papers/plos06b.pdf">https://www.cs.utah.edu/%7Eregehr/papers/plos06b.pdf</a>
   <dt id="biblio-robison">[ROBISON]
   <dd>Arch Robison. <a href="https://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming">Volatile: Almost Useless for Multi-Threaded Programming</a>. 2007-11-30. URL: <a href="https://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming">https://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming</a>
   <dt id="biblio-rust">[Rust]
   <dd><a href="https://doc.rust-lang.org/std/ptr/fn.read_volatile.html">Function std::ptr::read_volatile</a>. URL: <a href="https://doc.rust-lang.org/std/ptr/fn.read_volatile.html">https://doc.rust-lang.org/std/ptr/fn.read_volatile.html</a>
   <dt id="biblio-sebor">[SEBOR]
   <dd>Martin Sebor. <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm#dr_476">C Defect Report #476: volatile semantics for lvalues</a>. 2015-08-26. URL: <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm#dr_476">http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm#dr_476</a>
   <dt id="biblio-srst">[SRST]
   <dd>Patrick Rothfuss. The Slow Regard of Silent Things. 2014-10-28. 
   <dt id="biblio-sysiii">[SysIII]
   <dd><a href="https://minnie.tuhs.org//cgi-bin/utree.pl?file=SysIII/usr/src/stand/pdp11/iload/console.c">SysIII/usr/src/stand/pdp11/iload/console.c</a>. URL: <a href="https://minnie.tuhs.org//cgi-bin/utree.pl?file=SysIII/usr/src/stand/pdp11/iload/console.c">https://minnie.tuhs.org//cgi-bin/utree.pl?file=SysIII/usr/src/stand/pdp11/iload/console.c</a>
   <dt id="biblio-torvalds">[TORVALDS]
   <dd>Linus Torvalds. <a href="https://gcc.gnu.org/ml/gcc/2012-02/msg00027.html">GCC mailing list: Memory corruption due to word sharing</a>. 2012-02-01. URL: <a href="https://gcc.gnu.org/ml/gcc/2012-02/msg00027.html">https://gcc.gnu.org/ml/gcc/2012-02/msg00027.html</a>
   <dt id="biblio-trouble">[TROUBLE]
   <dd>corbet. <a href="https://lwn.net/Articles/233479/">The trouble with volatile</a>. 2017-05-09. URL: <a href="https://lwn.net/Articles/233479/">https://lwn.net/Articles/233479/</a>
   <dt id="biblio-when">[WHEN]
   <dd><a href="https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Volatiles.html">When is a Volatile C++ Object Accessed?</a>. URL: <a href="https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Volatiles.html">https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Volatiles.html</a>
   <dt id="biblio-why">[WHY]
   <dd><a href="https://stackoverflow.com/questions/72552/why-does-volatile-exist">Why does volatile exist?</a>. 2008-07-16. URL: <a href="https://stackoverflow.com/questions/72552/why-does-volatile-exist">https://stackoverflow.com/questions/72552/why-does-volatile-exist</a>
   <dt id="biblio-whyc">[WHYC]
   <dd><a href="https://stackoverflow.com/questions/246127/why-is-volatile-needed-in-c">Why is volatile needed in C?</a>. URL: <a href="https://stackoverflow.com/questions/246127/why-is-volatile-needed-in-c">https://stackoverflow.com/questions/246127/why-is-volatile-needed-in-c</a>
   <dt id="biblio-wmf">[WMF]
   <dd>Patrick Rothfuss. The Wise Man's Fear. 2011-03-01. 
   <dt id="biblio-xenxsa155">[XENXSA155]
   <dd>Felix Wilhelm. <a href="https://insinuator.net/2015/12/xen-xsa-155-double-fetches-in-paravirtualized-devices/">Xen XSA 155: Double fetches in paravirtualized devices</a>. 2015-12-17. URL: <a href="https://insinuator.net/2015/12/xen-xsa-155-double-fetches-in-paravirtualized-devices/">https://insinuator.net/2015/12/xen-xsa-155-double-fetches-in-paravirtualized-devices/</a>
   <dt id="biblio-xtensa">[XTENSA]
   <dd><a href="https://gcc.gnu.org/onlinedocs/gcc-4.8.1/gcc/Xtensa-Options.html">GCC Xtensa Options</a>. URL: <a href="https://gcc.gnu.org/onlinedocs/gcc-4.8.1/gcc/Xtensa-Options.html">https://gcc.gnu.org/onlinedocs/gcc-4.8.1/gcc/Xtensa-Options.html</a>
  </dl>
  <h2 class="no-num no-ref heading settled" id="issues-index"><span class="content">Issues Index</span><a class="self-link" href="#issues-index"></a></h2>
  <div style="counter-reset:issue">
   <div class="issue"> We would like guidance on <code class="highlight"><c- k>volatile</c-></code> when combined with <code class="highlight"><c- k>operator</c-><c- o>->*</c-></code>.
That guidance will depend on choices made with respect to <code class="highlight"><c- k>volatile</c-></code> aggregates.<a href="#issue-c1a9b9d1"> ↵ </a></div>
   <div class="issue"> There’s a related problem in <a data-link-type="biblio" href="#biblio-trouble">[TROUBLE]</a> with chained assignments of <code class="highlight"><c- k>volatile</c-></code> values, such as <code class="highlight"><c- n>a</c-> <c- o>=</c-> <c- n>b</c-> <c- o>=</c-> <c- n>c</c-></code>. This is equally misleading, and it’s not
intuitive whether the value stored to <code class="highlight"><c- n>b</c-></code> is re-read before storing to <code class="highlight"><c- n>a</c-></code>. We
would like guidance on whether this is worth addressing.<a href="#issue-16eb408f"> ↵ </a></div>
   <div class="issue"> Which of the above approaches (deprecate <code class="highlight"><c- k>volatile</c-></code>-qualified member
functions, all-or-nothing, <code class="highlight"><c- k>struct</c-> <c- k>volatile</c-></code>, or deprecate <code class="highlight"><c- k>volatile</c-></code> aggregates, should we pursue?<a href="#issue-c3997c0a"> ↵ </a></div>
   <div class="issue"> If we keep <code class="highlight"><c- k>volatile</c-></code> aggregates, it seems like <code class="highlight"><c- k>volatile</c-></code> aggregates
should have constructors which initialize all members with <code class="highlight"><c- k>volatile</c-></code> semantics,
and destroy them with <code class="highlight"><c- k>volatile</c-></code> semantics. Otherwise, we encourage the use of
initialization / cleanup member functions. Alternatively, triviality could be
mandated for constructors and destructors of <code class="highlight"><c- k>volatile</c-></code> aggregates. The author
is told by some embedded developers that it’s very common to have an aggregate
that describes some hardware, and to access hardware registers (member variables
of the aggregate) by indirection through a pointer to <code class="highlight"><c- k>volatile</c-></code> struct.<a href="#issue-5b42e15e"> ↵ </a></div>
   <div class="issue"> If we keep <code class="highlight"><c- k>volatile</c-></code> aggregates, what does it mean to have a <code class="highlight"><c- k>volatile</c-></code> virtual function table pointer?<a href="#issue-0ae133a2"> ↵ </a></div>
   <div class="issue"> It is unclear how <code class="highlight"><c- k>volatile</c-> <c- k>union</c-></code> should be accessed when all types in
the <code class="highlight"><c- k>union</c-></code> aren’t stored using the same bits (i.e. should <code class="highlight"><c- k>union</c-> <c- p>{</c-> <c- b>char</c-> <c- n>c</c-><c- p>;</c-> <c- b>int</c-> <c- n>i</c-><c- p>;</c-> <c- p>}</c-></code> always access the full union, even when only accessing <code class="highlight"><c- n>c</c-></code>?). Some
hardware defines different semantics to MMIO register accesses of different
sizes to the same address. A union would be a natural way to represent such
hardware. This could be outside the scope of the current paper.<a href="#issue-8a3b6c52"> ↵ </a></div>
   <div class="issue"> We would like guidance on whether <code class="highlight"><c- k>volatile</c-></code> bit-fields should be
constrained. At the moment no guarantee is made about read-modify-write
operations required when mixing <code class="highlight"><c- k>volatile</c-></code> and non-<code class="highlight"><c- k>volatile</c-></code> bit-field data
members. It seems like, at a minimum, bit fields should always cause alignment
when subsequent data members change their cv-qualification. This could be
outside the scope of the current paper.<a href="#issue-601cb919"> ↵ </a></div>
   <div class="issue"> Should we go further and forbid <code class="highlight"><c- k>volatile</c-></code> in containers? Some containers
seem useful for signal handlers and such, however how loads and stores are
performed to these containers isn’t mandated by the Standard which means that to
use containers in signal handlers one needs to synchronize separately with <code class="highlight"><c- n>atomic_signal_fence</c-></code> and some form of token. Containers of <code class="highlight"><c- k>volatile</c-></code> data are
therefore misleading at best.<a href="#issue-3b9bc2e5"> ↵ </a></div>
   <div class="issue"> We would like guidance on whether other read-modify-write operations
should be maintained with implementation-defined semantics. Specifically, <code class="highlight"><c- n>exchange</c-></code>, <code class="highlight"><c- n>compare_exchange_strong</c-></code>, <code class="highlight"><c- n>compare_exchange_weak</c-></code>, <code class="highlight"><c- n>fetch_add</c-></code> / <code class="highlight"><c- n>fetch_sub</c-></code> (for integral, pointer, and floating-point), and <code class="highlight"><c- n>fetch_and</c-></code> / <code class="highlight"><c- n>fetch_or</c-></code> / <code class="highlight"><c- n>fetch_xor</c-></code> (for integral), can be given useful semantics by an
implementation which wishes to guarantee that particular instructions will be
emitted. This would maintain the status-quo whereby <code class="highlight"><c- k>volatile</c-></code> is a
semi-portable abstraction for hardware, and still allows us to consider
deprecation in the future. Keeping these for now is the conservative option.<a href="#issue-f23f6518"> ↵ </a></div>
  </div>