From 698b8b1e3bab915cf386e7e6d05c704c81466e3e Mon Sep 17 00:00:00 2001 From: Alisdair Meredith Date: Sun, 28 Jul 2024 16:56:33 -0400 Subject: [PATCH 01/18] [dcl.dcl][stmt.stmt] Remove tautonyms from top level stable labels Per comment on issue #5315. Thanks to Jonathan Wakely for the notion of tautonyms. --- source/basic.tex | 2 +- source/compatibility.tex | 18 +++++++++--------- source/declarations.tex | 6 +++--- source/expressions.tex | 4 ++-- source/statements.tex | 4 ++-- source/xrefdelta.tex | 10 ++++++++++ 6 files changed, 27 insertions(+), 17 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 9524265f81..6164d3deb3 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -135,7 +135,7 @@ \indextext{declaration!definition versus}% \indextext{declaration}% \indextext{declaration!name}% -A declaration\iref{dcl.dcl} may (re)introduce +A declaration\iref{dcl} may (re)introduce one or more names and/or entities into a translation unit. If so, the diff --git a/source/compatibility.tex b/source/compatibility.tex index 93baac8554..8840243133 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -53,7 +53,7 @@ \end{codeblock} \end{example} -\rSec2[diff.cpp23.dcl.dcl]{\ref{dcl.dcl}: declarations} +\rSec2[diff.cpp23.dcl]{\ref{dcl}: declarations} \diffref{dcl.init.list} \change @@ -359,7 +359,7 @@ \end{codeblock} \end{example} -\rSec2[diff.cpp20.stmt]{\ref{stmt.stmt}: statements} +\rSec2[diff.cpp20.stmt]{\ref{stmt}: statements} \diffref{stmt.ranged} \change @@ -383,7 +383,7 @@ \end{codeblock} \end{example} -\rSec2[diff.cpp20.dcl]{\ref{dcl.dcl}: declarations} +\rSec2[diff.cpp20.dcl]{\ref{dcl}: declarations} \diffref{dcl.init.string} \change @@ -850,7 +850,7 @@ if those entities are only referenced in contexts that do not result in an odr-use. -\rSec2[diff.cpp17.dcl.dcl]{\ref{dcl.dcl}: declarations} +\rSec2[diff.cpp17.dcl]{\ref{dcl}: declarations} \diffref{dcl.typedef} \change @@ -1489,7 +1489,7 @@ \tcode{::operator new(std::size_t, std::align_val_t)} is used instead. -\rSec2[diff.cpp14.dcl.dcl]{\ref{dcl.dcl}: declarations} +\rSec2[diff.cpp14.dcl]{\ref{dcl}: declarations} \diffref{dcl.stc} \indextext{\idxcode{register} storage class}% @@ -1875,7 +1875,7 @@ revision of \Cpp{}, it yields \tcode{sizeof(const char[1])}. \end{example} -\rSec2[diff.cpp11.dcl.dcl]{\ref{dcl.dcl}: declarations} +\rSec2[diff.cpp11.dcl]{\ref{dcl}: declarations} \diffref{dcl.constexpr} \change @@ -2117,7 +2117,7 @@ \end{codeblock} \end{example} -\rSec2[diff.cpp03.dcl.dcl]{\ref{dcl.dcl}: declarations} +\rSec2[diff.cpp03.dcl]{\ref{dcl}: declarations} \diffref{dcl.spec} \change @@ -2923,7 +2923,7 @@ \howwide Rare. -\rSec2[diff.stat]{\ref{stmt.stmt}: statements} +\rSec2[diff.stmt]{\ref{stmt}: statements} \diffref{stmt.switch,stmt.goto} \change @@ -2971,7 +2971,7 @@ For several years, many existing C implementations have produced warnings in this case. -\rSec2[diff.dcl]{\ref{dcl.dcl}: declarations} +\rSec2[diff.dcl]{\ref{dcl}: declarations} \diffref{dcl.stc} \change diff --git a/source/declarations.tex b/source/declarations.tex index 446aebd3aa..2dc2ada3ba 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -1,5 +1,5 @@ %!TEX root = std.tex -\rSec0[dcl.dcl]{Declarations}% +\rSec0[dcl]{Declarations}% \indextext{declaration|(} \gramSec[gram.dcl]{Declarations} @@ -129,7 +129,7 @@ \indextext{scope}% Certain declarations contain one or more scopes\iref{basic.scope.scope}. Unless otherwise stated, utterances in -\ref{dcl.dcl} about components in, of, or contained by a +\ref{dcl} about components in, of, or contained by a declaration or subcomponent thereof refer only to those components of the declaration that are \emph{not} nested within scopes nested within the declaration. @@ -8838,7 +8838,7 @@ \pnum Each \grammarterm{attribute-specifier-seq} is said to \defn{appertain} to some entity or statement, identified by the syntactic context -where it appears\iref{stmt.stmt,dcl.dcl,dcl.decl}. +where it appears\iref{stmt,dcl,dcl.decl}. If an \grammarterm{attribute-specifier-seq} that appertains to some entity or statement contains an \grammarterm{attribute} or \grammarterm{alignment-specifier} that is not allowed to apply to that diff --git a/source/expressions.tex b/source/expressions.tex index 389ac435b8..4a9b68e574 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -1478,7 +1478,7 @@ \indextext{identifier}% An \grammarterm{identifier} is only an \grammarterm{id-expression} if it has -been suitably declared\iref{dcl.dcl} +been suitably declared\iref{dcl} or if it appears as part of a \grammarterm{declarator-id}\iref{dcl.decl}. An \grammarterm{identifier} that names a coroutine parameter refers to the copy of the parameter\iref{dcl.fct.def.coroutine}. @@ -7714,7 +7714,7 @@ \item a \keyword{goto} statement\iref{stmt.goto}. \begin{note} -A \keyword{goto} statement introduced by equivalence\iref{stmt.stmt} +A \keyword{goto} statement introduced by equivalence\iref{stmt} is not in scope. For example, a \keyword{while} statement\iref{stmt.while} can be executed during constant evaluation. diff --git a/source/statements.tex b/source/statements.tex index 9940ee28de..1e134ecee5 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -1,5 +1,5 @@ %!TEX root = std.tex -\rSec0[stmt.stmt]{Statements}% +\rSec0[stmt]{Statements}% \indextext{statement|(} \gramSec[gram.stmt]{Statements} @@ -92,7 +92,7 @@ the \grammarterm{condition} is a structured binding declaration\iref{dcl.pre}. A \grammarterm{condition} that is neither an \grammarterm{expression} nor a structured binding declaration -is a declaration\iref{dcl.dcl}. +is a declaration\iref{dcl}. The \grammarterm{declarator} shall not specify a function or an array. The \grammarterm{decl-specifier-seq} shall not define a class or enumeration. If the \keyword{auto} \grammarterm{type-specifier} appears in diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index fd1251057e..bbb25cae1e 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -90,6 +90,16 @@ \movedxref{stoptoken.cons}{stopsource} \movedxref{stoptoken.nonmembers}{stopsource} +% https://github.com/cplusplus/draft/pull/7179 +\movedxref{dcl.dcl}{dcl} +\movedxref{diff.cpp03.dcl.dcl}{diff.cpp03.dcl} +\movedxref{diff.cpp11.dcl.dcl}{diff.cpp11.dcl} +\movedxref{diff.cpp14.dcl.dcl}{diff.cpp14.dcl} +\movedxref{diff.cpp17.dcl.dcl}{diff.cpp17.dcl} +\movedxref{diff.cpp23.dcl.dcl}{diff.cpp23.dcl} +\movedxref{diff.stat}{diff.stmt} +\movedxref{stmt.stmt}{stmt} + %%% Deprecated features. %%% Example: % From 9c3581ca6c1c13efacee8a6dcc278767a5203ca8 Mon Sep 17 00:00:00 2001 From: Alisdair Meredith Date: Sun, 28 Jul 2024 17:13:41 -0400 Subject: [PATCH 02/18] [xref cpp23] Remove reference to diff against C++23 Oops. Clearly the section describing the diffs against C++23 was not present in C++23 itself. --- source/xrefdelta.tex | 1 - 1 file changed, 1 deletion(-) diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index bbb25cae1e..f2d2baa2e8 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -96,7 +96,6 @@ \movedxref{diff.cpp11.dcl.dcl}{diff.cpp11.dcl} \movedxref{diff.cpp14.dcl.dcl}{diff.cpp14.dcl} \movedxref{diff.cpp17.dcl.dcl}{diff.cpp17.dcl} -\movedxref{diff.cpp23.dcl.dcl}{diff.cpp23.dcl} \movedxref{diff.stat}{diff.stmt} \movedxref{stmt.stmt}{stmt} From 23b5f8841a0b8dc26f4147dead7b7d7122c7f8be Mon Sep 17 00:00:00 2001 From: Alisdair Meredith Date: Tue, 30 Jul 2024 11:08:32 -0400 Subject: [PATCH 03/18] [config.tex] Create and apply macros to denote first and last core chapters This PR should show no difference in the rendered document, but will make it much easier to refactor the Core clauses in the future --- just as we can refactor Library clauses today. --- source/config.tex | 4 ++++ source/expressions.tex | 2 +- source/intro.tex | 10 +++++----- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/source/config.tex b/source/config.tex index 990cc07b44..95407bff06 100644 --- a/source/config.tex +++ b/source/config.tex @@ -8,6 +8,10 @@ %% Release date \newcommand{\reldate}{\today} +%% Core chapters +\newcommand{\firstcorechapter}{lex} +\newcommand{\lastcorechapter}{cpp} + %% Library chapters \newcommand{\firstlibchapter}{support} \newcommand{\lastlibchapter}{exec} diff --git a/source/expressions.tex b/source/expressions.tex index 4a9b68e574..7a8ef724ec 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -7543,7 +7543,7 @@ \item an operation that would have undefined or erroneous behavior -as specified in \ref{intro} through \ref{cpp}, +as specified in \ref{intro} through \ref{\lastcorechapter}, excluding \ref{dcl.attr.assume} and \ref{dcl.attr.noreturn}; \begin{footnote} This includes, diff --git a/source/intro.tex b/source/intro.tex index 4f2984457d..743638b8eb 100644 --- a/source/intro.tex +++ b/source/intro.tex @@ -256,7 +256,7 @@ Implementations are allowed, but not required, to diagnose it\iref{intro.compliance.general}. Evaluation of a constant expression\iref{expr.const} -never exhibits behavior specified as erroneous in \ref{intro} through \ref{cpp}. +never exhibits behavior specified as erroneous in \ref{intro} through \ref{\lastcorechapter}. \end{defnote} \definition{expression-equivalent}{defns.expression.equivalent} @@ -644,7 +644,7 @@ issuance of a diagnostic message). Many incorrect program constructs do not engender undefined behavior; they are required to be diagnosed. Evaluation of a constant expression\iref{expr.const} never exhibits behavior explicitly -specified as undefined in \ref{intro} through \ref{cpp}. +specified as undefined in \ref{intro} through \ref{\lastcorechapter}. \end{defnote} \indexdefn{behavior!unspecified}% @@ -722,7 +722,7 @@ \begin{itemize} \item If a program contains no violations of the rules in -\ref{lex} through \ref{\lastlibchapter} as well as those specified in \ref{depr}, +\ref{\firstcorechapter} through \ref{\lastlibchapter} as well as those specified in \ref{depr}, a conforming implementation shall accept and correctly execute \begin{footnote} ``Correct execution'' can include undefined behavior @@ -808,7 +808,7 @@ supports all the facilities described in this document, while a freestanding implementation supports the entire \Cpp{} language -described in \ref{lex} through \ref{cpp} and +described in \ref{\firstcorechapter} through \ref{\lastcorechapter} and the subset of the library facilities described in \ref{compliance}. \pnum @@ -958,7 +958,7 @@ \pnum \indextext{standard!structure of|(}% \indextext{standard!structure of}% -\ref{lex} through \ref{cpp} describe the \Cpp{} programming +\ref{\firstcorechapter} through \ref{\lastcorechapter} describe the \Cpp{} programming language. That description includes detailed syntactic specifications in a form described in~\ref{syntax}. For convenience, \ref{gram} repeats all such syntactic specifications. From fda3af0d57387dba6bec6f6d48577ad80c26d7e6 Mon Sep 17 00:00:00 2001 From: Alisdair Meredith Date: Mon, 8 Jul 2024 12:33:25 -0400 Subject: [PATCH 04/18] [basic.pre] Defragment specification of names and entities The current contents of [basic.pre] jump between specifying different things. This PR moves all the specification of names to the front, followed by the specification of entities. There are two main benefits: (1) the specification for when two names are the same is a list of 4 rules that correspond to the 4 things than can form a name --- the connection is much clearer when the paragraphs are adjacent and the list is sorted to the same order; (2) in this form, even though all the words are the same, the reordering and merging of paragraphs a fit on a single page. The very last paragraph was forced over a page-break in the original layout. --- source/basic.tex | 54 ++++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 6164d3deb3..7b81037ea3 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -32,18 +32,22 @@ \indextext{storage class}% \indextext{scope}% \indextext{linkage}% -An \defn{entity} is a value, object, reference, -structured binding, -function, enumerator, type, -class member, bit-field, template, template specialization, namespace, or -pack. - -\pnum A \defn{name} is an \grammarterm{identifier}\iref{lex.name}, \grammarterm{operator-function-id}\iref{over.oper}, \grammarterm{literal-operator-id}\iref{over.literal}, or \grammarterm{conversion-function-id}\iref{class.conv.fct}. +\pnum +Two names are \defnx{the same}{name!same} if +\begin{itemize} +\item they are \grammarterm{identifier}{s} composed of the same character sequence, or +\item they are \grammarterm{operator-function-id}{s} formed with the same operator, or +\item they are \grammarterm{literal-operator-id}{s} formed with the same +literal suffix identifier, or +\item they are \grammarterm{conversion-function-id}{s} formed with +equivalent\iref{temp.over.link} types. +\end{itemize} + \pnum Every name is introduced by a \defn{declaration}, which is a \begin{itemize} @@ -85,9 +89,13 @@ The interpretation of a \grammarterm{for-range-declaration} produces one or more of the above\iref{stmt.ranged}. \end{note} -An entity $E$ is denoted by the name (if any) -that is introduced by a declaration of $E$ or -by a \grammarterm{typedef-name} introduced by a declaration specifying $E$. + +\pnum +Some names denote types or templates. In general, whenever a name is +encountered it is necessary to determine whether that name denotes one of these +entities before continuing to parse the program that contains it. The process +that determines this is called +\defnx{name lookup}{lookup!name}\iref{basic.lookup}. \pnum A \defn{variable} is introduced by the @@ -95,6 +103,13 @@ a reference other than a non-static data member or of an object. The variable's name, if any, denotes the reference or object. +\pnum +An \defn{entity} is a value, object, reference, structured binding, function, +enumerator, type, class member, bit-field, template, template specialization, +namespace, or pack. An entity $E$ is denoted by the name (if any) that is +introduced by a declaration of $E$ or by a \grammarterm{typedef-name} +introduced by a declaration specifying $E$. + \pnum A \defnadj{local}{entity} is a variable with automatic storage duration\iref{basic.stc.auto}, @@ -102,25 +117,6 @@ whose corresponding variable is such an entity, or the \tcode{*\keyword{this}} object\iref{expr.prim.this}. -\pnum -Some names denote types or templates. In general, -whenever a name is encountered it is necessary to determine whether that name denotes -one of these entities before continuing to parse the program that contains it. The -process that determines this is called -\defnx{name lookup}{lookup!name}\iref{basic.lookup}. - -\pnum -Two names are \defnx{the same}{name!same} if -\begin{itemize} -\item they are \grammarterm{identifier}{s} composed of the same character sequence, or -\item they are \grammarterm{operator-function-id}{s} formed with -the same operator, or -\item they are \grammarterm{conversion-function-id}{s} formed -with equivalent\iref{temp.over.link} types, or -\item they are \grammarterm{literal-operator-id}{s}\iref{over.literal} formed with -the same literal suffix identifier. -\end{itemize} - \pnum \indextext{translation unit!name and}% \indextext{linkage}% From 0d728e15e28804c6c4e897434062e85accff4a92 Mon Sep 17 00:00:00 2001 From: Alisdair Meredith Date: Tue, 16 Jul 2024 15:03:23 -0400 Subject: [PATCH 05/18] [lex.separate][module.unit] move definitions of program and translation unit The definition of program at the top of [basic.link] should move to the front of [lex.separate] so that it is defined before its first usage, and also clarifies that the phases of translation produce. Similarly, move the definition of the grammar production translation-unit to the top of the first clause to actually use it, [module.unit]. Finally, retitle [basic.link] as just Linkage, rather than prgrams and linkage. --- source/basic.tex | 15 +-------------- source/intro.tex | 2 +- source/lex.tex | 5 +++++ source/modules.tex | 8 ++++++++ 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 7b81037ea3..08f0ded558 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -2644,23 +2644,10 @@ only namespace names are considered.% \indextext{lookup!name|)}% -\rSec1[basic.link]{Program and linkage}% +\rSec1[basic.link]{Linkage}% \indextext{linkage|(} \pnum -\indextext{program}% -A \defn{program} consists of one or more translation units\iref{lex.separate} -linked together. A translation unit consists -of a sequence of declarations. - -\begin{bnf} -\nontermdef{translation-unit}\br - \opt{declaration-seq}\br - \opt{global-module-fragment} module-declaration \opt{declaration-seq} \opt{private-module-fragment} -\end{bnf} - -\pnum -\indextext{translation unit}% A name can have \defnadj{external}{linkage}, \defnadj{module}{linkage}, diff --git a/source/intro.tex b/source/intro.tex index 743638b8eb..f56652dab5 100644 --- a/source/intro.tex +++ b/source/intro.tex @@ -476,7 +476,7 @@ \begin{defnote} Only one definition for such a function is in effect for the duration of the program's execution, as the result of creating the program\iref{lex.phases} and resolving the -definitions of all translation units\iref{basic.link}. +definitions of all translation units\iref{module.unit}. \end{defnote} \definition{required behavior}{defns.required.behavior} diff --git a/source/lex.tex b/source/lex.tex index adb82aa862..ebe324bf07 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -24,6 +24,11 @@ \rSec1[lex.separate]{Separate translation} +\pnum +\indextext{program}% +A \defn{program} consists of one or more translation units\iref{lex.phases,module.unit} +linked together. + \pnum \indextext{conventions!lexical|(}% \indextext{compilation!separate|(}% diff --git a/source/modules.tex b/source/modules.tex index 2ed009a3b6..9298ba4dee 100644 --- a/source/modules.tex +++ b/source/modules.tex @@ -6,6 +6,10 @@ \rSec1[module.unit]{Module units and purviews} \begin{bnf} +\nontermdef{translation-unit}\br + \opt{declaration-seq}\br + \opt{global-module-fragment} module-declaration \opt{declaration-seq} \opt{private-module-fragment} + \nontermdef{module-declaration}\br \opt{export-keyword} module-keyword module-name \opt{module-partition} \opt{attribute-specifier-seq} \terminal{;} \end{bnf} @@ -26,6 +30,10 @@ module-name-qualifier identifier \terminal{.} \end{bnf} +\pnum +\indextext{translation unit}% +A translation unit consists of a sequence of declarations. + \pnum A \defn{module unit} is a translation unit that contains a \grammarterm{module-declaration}. From 14e914707ddafcd40c0cccdfa96e88f5d4f2f202 Mon Sep 17 00:00:00 2001 From: Alisdair Meredith Date: Tue, 30 Jul 2024 16:15:43 -0400 Subject: [PATCH 06/18] [lex] Reorganize contents to follow grammar and phases of translation This PR purely moves existing words around, and does not create any new content. It would be the precursor to a larger change set that might integrate [cpp] into lex, or move it adjactent, and similarly move [modules] adjactent. This may be more significant than we want to land in C++26, but I offer it while time is still available, and as inspiration for the C++29 reorg otherwise. --- source/lex.tex | 321 +++++++++++++++++++++++++------------------------ 1 file changed, 161 insertions(+), 160 deletions(-) diff --git a/source/lex.tex b/source/lex.tex index ebe324bf07..95a12d362a 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -470,30 +470,48 @@ for the respective Unicode encoding form. \indextext{character set|)} +\rSec1[lex.comment]{Comments} + +\pnum +\indextext{comment|(}% +\indextext{comment!\tcode{/*} \tcode{*/}}% +\indextext{comment!\tcode{//}}% +The characters \tcode{/*} start a comment, which terminates with the +characters \tcode{*/}. These comments do not nest. +\indextext{comment!\tcode{//}}% +The characters \tcode{//} start a comment, which terminates immediately before the +next new-line character. If there is a form-feed or a vertical-tab +character in such a comment, only whitespace characters shall appear +between it and the new-line that terminates the comment; no diagnostic +is required. +\begin{note} +The comment characters \tcode{//}, \tcode{/*}, +and \tcode{*/} have no special meaning within a \tcode{//} comment and +are treated just like other characters. Similarly, the comment +characters \tcode{//} and \tcode{/*} have no special meaning within a +\tcode{/*} comment. +\end{note} +\indextext{comment|)} + \rSec1[lex.pptoken]{Preprocessing tokens} \indextext{token!preprocessing|(}% \begin{bnf} \nontermdef{preprocessing-token}\br - header-name\br import-keyword\br module-keyword\br export-keyword\br - identifier\br + header-name\br pp-number\br + preprocessing-op-or-punc\br + identifier\br character-literal\br user-defined-character-literal\br string-literal\br user-defined-string-literal\br - preprocessing-op-or-punc\br \textnormal{each non-whitespace character that cannot be one of the above} \end{bnf} -\pnum -Each preprocessing token that is converted to a token\iref{lex.token} -shall have the lexical form of a keyword, an identifier, a literal, -or an operator or punctuator. - \pnum A preprocessing token is the minimal lexical element of the language in translation phases 3 through 6. @@ -528,6 +546,22 @@ between the quotation characters in a character literal or string literal. +\pnum +Each preprocessing token that is converted to a token\iref{lex.token} +shall have the lexical form of a keyword, an identifier, a literal, +or an operator or punctuator. + +\pnum +The \grammarterm{import-keyword} is produced +by processing an \keyword{import} directive\iref{cpp.import}, +the \grammarterm{module-keyword} is produced +by preprocessing a \keyword{module} directive\iref{cpp.module}, and +the \grammarterm{export-keyword} is produced +by preprocessing either of the previous two directives. +\begin{note} +None has any observable spelling. +\end{note} + \pnum If the input stream has been parsed into preprocessing tokens up to a given character: @@ -567,6 +601,7 @@ \end{itemize} \end{itemize} +\pnum \begin{example} \begin{codeblock} #define R "x" @@ -574,17 +609,6 @@ \end{codeblock} \end{example} -\pnum -The \grammarterm{import-keyword} is produced -by preprocessing an \keyword{import} directive\iref{cpp.import}, -the \grammarterm{module-keyword} is produced -by preprocessing a \keyword{module} directive\iref{cpp.module}, and -the \grammarterm{export-keyword} is produced -by preprocessing either of the previous two directives. -\begin{note} -None has any observable spelling. -\end{note} - \pnum \begin{example} The program fragment \tcode{0xe+foo} is parsed as a @@ -607,106 +631,6 @@ \end{example} \indextext{token!preprocessing|)} -\rSec1[lex.digraph]{Alternative tokens} - -\pnum -\indextext{token!alternative|(}% -Alternative token representations are provided for some operators and -punctuators. -\begin{footnote} -\indextext{digraph}% -These include ``digraphs'' and additional reserved words. The term -``digraph'' (token consisting of two characters) is not perfectly -descriptive, since one of the alternative \grammarterm{preprocessing-token}s is -\tcode{\%:\%:} and of course several primary tokens contain two -characters. Nonetheless, those alternative tokens that aren't lexical -keywords are colloquially known as ``digraphs''. -\end{footnote} - -\pnum -In all respects of the language, each alternative token behaves the -same, respectively, as its primary token, except for its spelling. -\begin{footnote} -Thus the ``stringized'' values\iref{cpp.stringize} of -\tcode{[} and \tcode{<:} will be different, maintaining the source -spelling, but the tokens can otherwise be freely interchanged. -\end{footnote} -The set of alternative tokens is defined in -\tref{lex.digraph}. - -\begin{tokentable}{Alternative tokens}{lex.digraph}{Alternative}{Primary} -\tcode{<\%} & \tcode{\{} & -\keyword{and} & \tcode{\&\&} & -\keyword{and_eq} & \tcode{\&=} \\ \rowsep -\tcode{\%>} & \tcode{\}} & -\keyword{bitor} & \tcode{|} & -\keyword{or_eq} & \tcode{|=} \\ \rowsep -\tcode{<:} & \tcode{[} & -\keyword{or} & \tcode{||} & -\keyword{xor_eq} & \tcode{\caret=} \\ \rowsep -\tcode{:>} & \tcode{]} & -\keyword{xor} & \tcode{\caret} & -\keyword{not} & \tcode{!} \\ \rowsep -\tcode{\%:} & \tcode{\#} & -\keyword{compl} & \tcode{\~} & -\keyword{not_eq} & \tcode{!=} \\ \rowsep -\tcode{\%:\%:} & \tcode{\#\#} & -\keyword{bitand} & \tcode{\&} & - & \\ -\end{tokentable}% -\indextext{token!alternative|)} - -\rSec1[lex.token]{Tokens} - -\indextext{token|(}% -\begin{bnf} -\nontermdef{token}\br - identifier\br - keyword\br - literal\br - operator-or-punctuator -\end{bnf} - -\pnum -\indextext{\idxgram{token}}% -There are five kinds of tokens: identifiers, keywords, literals,% -\begin{footnote} -Literals include strings and character and numeric literals. -\end{footnote} -operators, and other separators. -\indextext{whitespace}% -Blanks, horizontal and vertical tabs, newlines, formfeeds, and comments -(collectively, ``whitespace''), as described below, are ignored except -as they serve to separate tokens. -\begin{note} -Whitespace can separate otherwise adjacent identifiers, keywords, numeric -literals, and alternative tokens containing alphabetic characters. -\end{note} -\indextext{token|)} - -\rSec1[lex.comment]{Comments} - -\pnum -\indextext{comment|(}% -\indextext{comment!\tcode{/*} \tcode{*/}}% -\indextext{comment!\tcode{//}}% -The characters \tcode{/*} start a comment, which terminates with the -characters \tcode{*/}. These comments do not nest. -\indextext{comment!\tcode{//}}% -The characters \tcode{//} start a comment, which terminates immediately before the -next new-line character. If there is a form-feed or a vertical-tab -character in such a comment, only whitespace characters shall appear -between it and the new-line that terminates the comment; no diagnostic -is required. -\begin{note} -The comment characters \tcode{//}, \tcode{/*}, -and \tcode{*/} have no special meaning within a \tcode{//} comment and -are treated just like other characters. Similarly, the comment -characters \tcode{//} and \tcode{/*} have no special meaning within a -\tcode{/*} comment. -\end{note} -\indextext{comment|)} - \rSec1[lex.header]{Header names} \indextext{header!name|(}% @@ -796,6 +720,96 @@ a \grammarterm{floating-point-literal} token.% \indextext{number!preprocessing|)} +\rSec1[lex.operators]{Operators and punctuators} + +\pnum +\indextext{operator|(}% +\indextext{punctuator|(}% +The lexical representation of \Cpp{} programs includes a number of +preprocessing tokens that are used in the syntax of the preprocessor or +are converted into tokens for operators and punctuators: + +\begin{bnf} +\nontermdef{preprocessing-op-or-punc}\br + preprocessing-operator\br + operator-or-punctuator +\end{bnf} + +\begin{bnf} +%% Ed. note: character protrusion would misalign various operators. +\microtypesetup{protrusion=false}\obeyspaces +\nontermdef{preprocessing-operator} \textnormal{one of}\br + \terminal{\# \#\# \%: \%:\%:} +\end{bnf} + +\begin{bnf} +\microtypesetup{protrusion=false}\obeyspaces +\nontermdef{operator-or-punctuator} \textnormal{one of}\br + \terminal{\{ \} [ ] ( )}\br + \terminal{<: :> <\% \%> ; : ...}\br + \terminal{? :: . .* -> ->* \~}\br + \terminal{! + - * / \% \caret{} \& |}\br + \terminal{= += -= *= /= \%= \caret{}= \&= |=}\br + \terminal{== != < > <= >= <=> \&\& ||}\br + \terminal{<< >> <<= >>= ++ -- ,}\br + \terminal{\keyword{and} \keyword{or} \keyword{xor} \keyword{not} \keyword{bitand} \keyword{bitor} \keyword{compl}}\br + \terminal{\keyword{and_eq} \keyword{or_eq} \keyword{xor_eq} \keyword{not_eq}} +\end{bnf} + +Each \grammarterm{operator-or-punctuator} is converted to a single token +in translation phase 7\iref{lex.phases}.% +\indextext{punctuator|)}% +\indextext{operator|)} + +\rSec1[lex.digraph]{Alternative tokens} + +\pnum +\indextext{token!alternative|(}% +Alternative token representations are provided for some operators and +punctuators. +\begin{footnote} +\indextext{digraph}% +These include ``digraphs'' and additional reserved words. The term +``digraph'' (token consisting of two characters) is not perfectly +descriptive, since one of the alternative \grammarterm{preprocessing-token}s is +\tcode{\%:\%:} and of course several primary tokens contain two +characters. Nonetheless, those alternative tokens that aren't lexical +keywords are colloquially known as ``digraphs''. +\end{footnote} + +\pnum +In all respects of the language, each alternative token behaves the +same, respectively, as its primary token, except for its spelling. +\begin{footnote} +Thus the ``stringized'' values\iref{cpp.stringize} of +\tcode{[} and \tcode{<:} will be different, maintaining the source +spelling, but the tokens can otherwise be freely interchanged. +\end{footnote} +The set of alternative tokens is defined in +\tref{lex.digraph}. + +\begin{tokentable}{Alternative tokens}{lex.digraph}{Alternative}{Primary} +\tcode{<\%} & \tcode{\{} & +\keyword{and} & \tcode{\&\&} & +\keyword{and_eq} & \tcode{\&=} \\ \rowsep +\tcode{\%>} & \tcode{\}} & +\keyword{bitor} & \tcode{|} & +\keyword{or_eq} & \tcode{|=} \\ \rowsep +\tcode{<:} & \tcode{[} & +\keyword{or} & \tcode{||} & +\keyword{xor_eq} & \tcode{\caret=} \\ \rowsep +\tcode{:>} & \tcode{]} & +\keyword{xor} & \tcode{\caret} & +\keyword{not} & \tcode{!} \\ \rowsep +\tcode{\%:} & \tcode{\#} & +\keyword{compl} & \tcode{\~} & +\keyword{not_eq} & \tcode{!=} \\ \rowsep +\tcode{\%:\%:} & \tcode{\#\#} & +\keyword{bitand} & \tcode{\&} & + & \\ +\end{tokentable}% +\indextext{token!alternative|)} + \rSec1[lex.name]{Identifiers} \indextext{identifier|(}% @@ -917,6 +931,34 @@ \end{itemize}% \indextext{identifier|)} +\rSec1[lex.token]{Tokens} + +\indextext{token|(}% +\begin{bnf} +\nontermdef{token}\br + identifier\br + keyword\br + literal\br + operator-or-punctuator +\end{bnf} + +\pnum +\indextext{\idxgram{token}}% +There are five kinds of tokens: identifiers, keywords, literals,% +\begin{footnote} +Literals include strings and character and numeric literals. +\end{footnote} +operators, and other separators. +\indextext{whitespace}% +Blanks, horizontal and vertical tabs, newlines, formfeeds, and comments +(collectively, ``whitespace''), as described below, are ignored except +as they serve to separate tokens. +\begin{note} +Whitespace can separate otherwise adjacent identifiers, keywords, numeric +literals, and alternative tokens containing alphabetic characters. +\end{note} +\indextext{token|)} + \rSec1[lex.key]{Keywords} \begin{bnf} @@ -1041,47 +1083,6 @@ \indextext{keyword|)}% -\rSec1[lex.operators]{Operators and punctuators} - -\pnum -\indextext{operator|(}% -\indextext{punctuator|(}% -The lexical representation of \Cpp{} programs includes a number of -preprocessing tokens that are used in the syntax of the preprocessor or -are converted into tokens for operators and punctuators: - -\begin{bnf} -\nontermdef{preprocessing-op-or-punc}\br - preprocessing-operator\br - operator-or-punctuator -\end{bnf} - -\begin{bnf} -%% Ed. note: character protrusion would misalign various operators. -\microtypesetup{protrusion=false}\obeyspaces -\nontermdef{preprocessing-operator} \textnormal{one of}\br - \terminal{\# \#\# \%: \%:\%:} -\end{bnf} - -\begin{bnf} -\microtypesetup{protrusion=false}\obeyspaces -\nontermdef{operator-or-punctuator} \textnormal{one of}\br - \terminal{\{ \} [ ] ( )}\br - \terminal{<: :> <\% \%> ; : ...}\br - \terminal{? :: . .* -> ->* \~}\br - \terminal{! + - * / \% \caret{} \& |}\br - \terminal{= += -= *= /= \%= \caret{}= \&= |=}\br - \terminal{== != < > <= >= <=> \&\& ||}\br - \terminal{<< >> <<= >>= ++ -- ,}\br - \terminal{\keyword{and} \keyword{or} \keyword{xor} \keyword{not} \keyword{bitand} \keyword{bitor} \keyword{compl}}\br - \terminal{\keyword{and_eq} \keyword{or_eq} \keyword{xor_eq} \keyword{not_eq}} -\end{bnf} - -Each \grammarterm{operator-or-punctuator} is converted to a single token -in translation phase 7\iref{lex.phases}.% -\indextext{punctuator|)}% -\indextext{operator|)} - \rSec1[lex.literal]{Literals}% \indextext{literal|(} From e5af480142478c4aa1cbf9dbc59bf2b17f70f3b5 Mon Sep 17 00:00:00 2001 From: Alisdair Meredith Date: Mon, 17 Jun 2024 10:19:40 +0700 Subject: [PATCH 07/18] [lex.charset] Extract universal-character-name grammar to new subclause The grammar for universal-character-name is oddly sandwiched into the middle of the subcluase talking about the different character sets used by the standard. To improve the flow, extract that grammar into its own subclause. In the extraction, I make two other clarifying changes. First, describe this new subclause as 'a way to name any element of the of the tranlation character set using just the basic character set' rather than simply 'a way to name other characters'. Secondly, remove the 'one of' in the grammar where there is only one option to choose. --- source/lex.tex | 128 +++++++++++++++++++++++++------------------------ 1 file changed, 65 insertions(+), 63 deletions(-) diff --git a/source/lex.tex b/source/lex.tex index 95a12d362a..2091b7cab6 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -331,11 +331,69 @@ \end{floattable} \pnum -The \grammarterm{universal-character-name} construct provides a way to name -other characters. +The \defnadj{basic literal}{character set} consists of +all characters of the basic character set, +plus the control characters specified in \tref{lex.charset.literal}. + +\begin{floattable}{Additional control characters in the basic literal character set}{lex.charset.literal}{ll} +\topline +\ohdrx{2}{character} \\ \capsep +\ucode{0000} & \uname{null} \\ +\ucode{0007} & \uname{alert} \\ +\ucode{0008} & \uname{backspace} \\ +\ucode{000d} & \uname{carriage return} \\ +\end{floattable} + +\pnum +A \defn{code unit} is an integer value +of character type\iref{basic.fundamental}. +Characters in a \grammarterm{character-literal} +other than a multicharacter or non-encodable character literal or +in a \grammarterm{string-literal} are encoded as +a sequence of one or more code units, as determined +by the \grammarterm{encoding-prefix}\iref{lex.ccon,lex.string}; +this is termed the respective \defnadj{literal}{encoding}. +The \defnadj{ordinary literal}{encoding} is +the encoding applied to an ordinary character or string literal. +The \defnadj{wide literal}{encoding} is the encoding applied +to a wide character or string literal. + +\pnum +A literal encoding or a locale-specific encoding of one of +the execution character sets\iref{character.seq} +encodes each element of the basic literal character set as +a single code unit with non-negative value, +distinct from the code unit for any other such element. +\begin{note} +A character not in the basic literal character set +can be encoded with more than one code unit; +the value of such a code unit can be the same as +that of a code unit for an element of the basic literal character set. +\end{note} +\indextext{character!null}% +\indextext{wide-character!null}% +The \unicode{0000}{null} character is encoded as the value \tcode{0}. +No other element of the translation character set +is encoded with a code unit of value \tcode{0}. +The code unit value of each decimal digit character after the digit \tcode{0} (\ucode{0030}) +shall be one greater than the value of the previous. +The ordinary and wide literal encodings are otherwise +\impldef{ordinary and wide literal encodings}. +\indextext{UTF-8}% +\indextext{UTF-16}% +\indextext{UTF-32}% +For a UTF-8, UTF-16, or UTF-32 literal, +the implementation shall encode +the Unicode scalar value +corresponding to each character of the translation character set +as specified in the Unicode Standard +for the respective Unicode encoding form. +\indextext{character set|)} + +\rSec1[lex.universal.char]{Universal Character Names} \begin{bnf} -\nontermdef{n-char} \textnormal{one of}\br +\nontermdef{n-char}\br \textnormal{any member of the translation character set except the \unicode{007d}{right curly bracket} or new-line character} \end{bnf} @@ -369,6 +427,10 @@ named-universal-character \end{bnf} +\pnum +The \grammarterm{universal-character-name} construct provides a way to name +any element in the translation character set using just the basic character set. + \pnum A \grammarterm{universal-character-name} of the form \tcode{\textbackslash u} \grammarterm{hex-quad}, @@ -410,66 +472,6 @@ \grammarterm{universal-character-name}. \end{note} -\pnum -The \defnadj{basic literal}{character set} consists of -all characters of the basic character set, -plus the control characters specified in \tref{lex.charset.literal}. - -\begin{floattable}{Additional control characters}{lex.charset.literal}{ll} -\topline -\ohdrx{2}{character} \\ \capsep -\ucode{0000} & \uname{null} \\ -\ucode{0007} & \uname{alert} \\ -\ucode{0008} & \uname{backspace} \\ -\ucode{000d} & \uname{carriage return} \\ -\end{floattable} - -\pnum -A \defn{code unit} is an integer value -of character type\iref{basic.fundamental}. -Characters in a \grammarterm{character-literal} -other than a multicharacter or non-encodable character literal or -in a \grammarterm{string-literal} are encoded as -a sequence of one or more code units, as determined -by the \grammarterm{encoding-prefix}\iref{lex.ccon,lex.string}; -this is termed the respective \defnadj{literal}{encoding}. -The \defnadj{ordinary literal}{encoding} is -the encoding applied to an ordinary character or string literal. -The \defnadj{wide literal}{encoding} is the encoding applied -to a wide character or string literal. - -\pnum -A literal encoding or a locale-specific encoding of one of -the execution character sets\iref{character.seq} -encodes each element of the basic literal character set as -a single code unit with non-negative value, -distinct from the code unit for any other such element. -\begin{note} -A character not in the basic literal character set -can be encoded with more than one code unit; -the value of such a code unit can be the same as -that of a code unit for an element of the basic literal character set. -\end{note} -\indextext{character!null}% -\indextext{wide-character!null}% -The \unicode{0000}{null} character is encoded as the value \tcode{0}. -No other element of the translation character set -is encoded with a code unit of value \tcode{0}. -The code unit value of each decimal digit character after the digit \tcode{0} (\ucode{0030}) -shall be one greater than the value of the previous. -The ordinary and wide literal encodings are otherwise -\impldef{ordinary and wide literal encodings}. -\indextext{UTF-8}% -\indextext{UTF-16}% -\indextext{UTF-32}% -For a UTF-8, UTF-16, or UTF-32 literal, -the implementation shall encode -the Unicode scalar value -corresponding to each character of the translation character set -as specified in the Unicode Standard -for the respective Unicode encoding form. -\indextext{character set|)} - \rSec1[lex.comment]{Comments} \pnum From 61a5ad434bdcb5f5b9f0645d810f55626cea7015 Mon Sep 17 00:00:00 2001 From: Alisdair Meredith Date: Mon, 17 Jun 2024 23:48:09 +0700 Subject: [PATCH 08/18] [lex.charset] Introduced parent [lax.char] clause for character sets and UCNs --- source/lex.tex | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/lex.tex b/source/lex.tex index 2091b7cab6..e32a145c63 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -254,7 +254,9 @@ \indextext{translation!phases|)} \end{enumerate} -\rSec1[lex.charset]{Character sets} +\rSec1[lex.char]{Characters}% + +\rSec2[lex.charset]{Character sets} \pnum \indextext{character set|(}% @@ -390,7 +392,7 @@ for the respective Unicode encoding form. \indextext{character set|)} -\rSec1[lex.universal.char]{Universal Character Names} +\rSec2[lex.universal.char]{Universal character names} \begin{bnf} \nontermdef{n-char}\br From 4750450d810544bd0ed21d5cd4f35a93d8994153 Mon Sep 17 00:00:00 2001 From: Alisdair Meredith Date: Tue, 16 Jul 2024 11:56:00 -0400 Subject: [PATCH 09/18] [lex.charset] Rebase onto main Also, merge the sentence on where universal characters are prohibited into the sentence describing universal characters, to make clear that there is no contradiction between nominating a character, and how that character can be used. --- source/lex.tex | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/source/lex.tex b/source/lex.tex index e32a145c63..e15f5bd48e 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -430,8 +430,20 @@ \end{bnf} \pnum -The \grammarterm{universal-character-name} construct provides a way to name -any element in the translation character set using just the basic character set. +The \grammarterm{universal-character-name} construct provides a way to name any +element in the translation character set using just the basic character set. +If a \grammarterm{universal-character-name} outside +the \grammarterm{c-char-sequence}, \grammarterm{s-char-sequence}, or +\grammarterm{r-char-sequence} of a \grammarterm{character-literal} or +\grammarterm{string-literal} +(in either case, including within a \grammarterm{user-defined-literal}) +corresponds to a control character or to a character in the basic character set, +the program is ill-formed. +\begin{note} +A sequence of characters resembling a \grammarterm{universal-character-name} in an +\grammarterm{r-char-sequence}\iref{lex.string} does not form a +\grammarterm{universal-character-name}. +\end{note} \pnum A \grammarterm{universal-character-name} @@ -460,20 +472,6 @@ None of these names or aliases have leading or trailing spaces. \end{note} -\pnum -If a \grammarterm{universal-character-name} outside -the \grammarterm{c-char-sequence}, \grammarterm{s-char-sequence}, or -\grammarterm{r-char-sequence} of -a \grammarterm{character-literal} or \grammarterm{string-literal} -(in either case, including within a \grammarterm{user-defined-literal}) -corresponds to a control character or -to a character in the basic character set, the program is ill-formed. -\begin{note} -A sequence of characters resembling a \grammarterm{universal-character-name} in an -\grammarterm{r-char-sequence}\iref{lex.string} does not form a -\grammarterm{universal-character-name}. -\end{note} - \rSec1[lex.comment]{Comments} \pnum From e954ff893d23ecc210ebabcd041e279c4670ff15 Mon Sep 17 00:00:00 2001 From: Alisdair Meredith Date: Sun, 29 Sep 2024 02:05:33 -0400 Subject: [PATCH 10/18] [module] Move modules clause to immediately follow lexing --- source/std.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/std.tex b/source/std.tex index 2761dbee82..8abd2d6d1e 100644 --- a/source/std.tex +++ b/source/std.tex @@ -112,11 +112,11 @@ \include{intro} \include{lex} +\include{modules} \include{basic} \include{expressions} \include{statements} \include{declarations} -\include{modules} \include{classes} \include{overloading} \include{templates} From 8c913caaf4718943cfea22c1e1aa999d1f388901 Mon Sep 17 00:00:00 2001 From: Alisdair Meredith Date: Sun, 29 Sep 2024 17:09:45 -0400 Subject: [PATCH 11/18] [lex] Prepare to merge phase 4 preprocessor into lex This commit makes substantial changes to the organization of the Core clauses, without changing wording. Notably, [lex] is now titled as Program construction rather than Lexical conventions, as its contents are significatly more than mere conventions, and with the phases of translation detail how a program is constructed and built. [lex] itself is now more clearly modeled after the phases of translation for each of the level 2 subheadings, grouping the relevant specification for how to process each phases that needs more than the simple text in the phases themsevles. The whole Core sections are reorganized, promoting overload and exception handling above classes and templates. The idea is that overloading is relevant to understanding how functions are called, while functions are well specified before we get to classes and templates. Exception handling moves forward as the last control flow, which is relevant for functions before we get to defining classes. Classes still precede templates, as clearly we support both function and class templates. For neatness, we integrate the fix for tautonyms in stable labels. Finally, we try to disentagle some of the wording around basic definitions of names etc. --- source/basic.tex | 2 - source/config.tex | 2 +- source/declarations.tex | 2 +- source/lex.tex | 2112 ++++++++++++++++++++------------------- source/preprocessor.tex | 4 +- source/std.tex | 6 +- source/xrefdelta.tex | 3 + 7 files changed, 1069 insertions(+), 1062 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 08f0ded558..20aff54707 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -1,8 +1,6 @@ %!TEX root = std.tex \rSec0[basic]{Basics} -\gramSec[gram.basic]{Basics} - \rSec1[basic.pre]{Preamble} \pnum diff --git a/source/config.tex b/source/config.tex index 95407bff06..79b76aef5c 100644 --- a/source/config.tex +++ b/source/config.tex @@ -10,7 +10,7 @@ %% Core chapters \newcommand{\firstcorechapter}{lex} -\newcommand{\lastcorechapter}{cpp} +\newcommand{\lastcorechapter}{temp} %% Library chapters \newcommand{\firstlibchapter}{support} diff --git a/source/declarations.tex b/source/declarations.tex index 2dc2ada3ba..8f89479a9b 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -8827,7 +8827,7 @@ effect. The order in which the \grammarterm{attribute-token}{s} appear in an \grammarterm{attribute-list} is not significant. If a keyword\iref{lex.key} -or an alternative token\iref{lex.digraph} that satisfies the syntactic requirements +or an alternative token\iref{lex.operators} that satisfies the syntactic requirements of an \grammarterm{identifier}\iref{lex.name} is contained in an \grammarterm{attribute-token}, it is considered an identifier. No name diff --git a/source/lex.tex b/source/lex.tex index e15f5bd48e..339ef0e611 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -1,5 +1,5 @@ %!TEX root = std.tex -\rSec0[lex]{Lexical conventions} +\rSec0[lex]{Program Construction} \gramSec[gram.lex]{Lexical conventions} @@ -255,7 +255,6 @@ \end{enumerate} \rSec1[lex.char]{Characters}% - \rSec2[lex.charset]{Character sets} \pnum @@ -495,7 +494,8 @@ \end{note} \indextext{comment|)} -\rSec1[lex.pptoken]{Preprocessing tokens} +\rSec1[lex.pptokenize]{Preprocessor tokenization} +\rSec2[lex.pptoken]{Preprocessing tokens} \indextext{token!preprocessing|(}% \begin{bnf} @@ -633,7 +633,7 @@ \end{example} \indextext{token!preprocessing|)} -\rSec1[lex.header]{Header names} +\rSec2[lex.header]{Header names} \indextext{header!name|(}% \begin{bnf} @@ -693,7 +693,7 @@ \end{footnote} \indextext{header!name|)} -\rSec1[lex.ppnumber]{Preprocessing numbers} +\rSec2[lex.ppnumber]{Preprocessing numbers} \indextext{number!preprocessing|(}% \begin{bnf} @@ -722,7 +722,7 @@ a \grammarterm{floating-point-literal} token.% \indextext{number!preprocessing|)} -\rSec1[lex.operators]{Operators and punctuators} +\rSec2[lex.operators]{Operators and punctuators} \pnum \indextext{operator|(}% @@ -758,13 +758,6 @@ \terminal{\keyword{and_eq} \keyword{or_eq} \keyword{xor_eq} \keyword{not_eq}} \end{bnf} -Each \grammarterm{operator-or-punctuator} is converted to a single token -in translation phase 7\iref{lex.phases}.% -\indextext{punctuator|)}% -\indextext{operator|)} - -\rSec1[lex.digraph]{Alternative tokens} - \pnum \indextext{token!alternative|(}% Alternative token representations are provided for some operators and @@ -778,8 +771,6 @@ characters. Nonetheless, those alternative tokens that aren't lexical keywords are colloquially known as ``digraphs''. \end{footnote} - -\pnum In all respects of the language, each alternative token behaves the same, respectively, as its primary token, except for its spelling. \begin{footnote} @@ -812,891 +803,1219 @@ \end{tokentable}% \indextext{token!alternative|)} -\rSec1[lex.name]{Identifiers} +\pnum +Each \grammarterm{operator-or-punctuator} is converted to a single token +in translation phase 7\iref{lex.phases}.% +\indextext{punctuator|)}% +\indextext{operator|)} -\indextext{identifier|(}% +\rSec2[lex.ccon]{Character literals} + +\indextext{literal!character}% \begin{bnf} -\nontermdef{identifier}\br - identifier-start\br - identifier identifier-continue +\nontermdef{character-literal}\br + \opt{encoding-prefix} \terminal{'} c-char-sequence \terminal{'} \end{bnf} \begin{bnf} -\nontermdef{identifier-start}\br - nondigit\br - \textnormal{an element of the translation character set with the Unicode property XID_Start} +\nontermdef{encoding-prefix} \textnormal{one of}\br + \terminal{u8}\quad\terminal{u}\quad\terminal{U}\quad\terminal{L} \end{bnf} \begin{bnf} -\nontermdef{identifier-continue}\br - digit\br - nondigit\br - \textnormal{an element of the translation character set with the Unicode property XID_Continue} +\nontermdef{c-char-sequence}\br + c-char\br + c-char-sequence c-char \end{bnf} \begin{bnf} -\nontermdef{nondigit} \textnormal{one of}\br - \terminal{a b c d e f g h i j k l m}\br - \terminal{n o p q r s t u v w x y z}\br - \terminal{A B C D E F G H I J K L M}\br - \terminal{N O P Q R S T U V W X Y Z _} +\nontermdef{c-char}\br + basic-c-char\br + escape-sequence\br + universal-character-name \end{bnf} \begin{bnf} -\nontermdef{digit} \textnormal{one of}\br - \terminal{0 1 2 3 4 5 6 7 8 9} +\nontermdef{basic-c-char}\br + \textnormal{any member of the translation character set except the \unicode{0027}{apostrophe},}\br + \bnfindent\textnormal{\unicode{005c}{reverse solidus}, or new-line character} \end{bnf} -\pnum -\indextext{name!length of}% -\indextext{name}% -\begin{note} -The character properties XID_Start and XID_Continue are Derived Core Properties -as described by \UAX{44} of the Unicode Standard. -\begin{footnote} -On systems in which linkers cannot accept extended -characters, an encoding of the \grammarterm{universal-character-name} can be used in -forming valid external identifiers. For example, some otherwise unused -character or sequence of characters can be used to encode the -\tcode{\textbackslash u} in a \grammarterm{universal-character-name}. Extended -characters can produce a long external identifier, but \Cpp{} does not -place a translation limit on significant characters for external -identifiers. -\end{footnote} -\end{note} -The program is ill-formed -if an \grammarterm{identifier} does not conform to -Normalization Form C as specified in the Unicode Standard. -\begin{note} -Identifiers are case-sensitive. -\end{note} -\begin{note} -\ref{uaxid} compares the requirements of \UAX{31} of the Unicode Standard -with the \Cpp{} rules for identifiers. -\end{note} -\begin{note} -In translation phase 4, -\grammarterm{identifier} also includes -those \grammarterm{preprocessing-token}s\iref{lex.pptoken} -differentiated as keywords\iref{lex.key} -in the later translation phase 7\iref{lex.token}. -\end{note} +\begin{bnf} +\nontermdef{escape-sequence}\br + simple-escape-sequence\br + numeric-escape-sequence\br + conditional-escape-sequence +\end{bnf} -\pnum -\indextext{\idxcode{import}}% -\indextext{\idxcode{final}}% -\indextext{\idxcode{module}}% -\indextext{\idxcode{override}}% -The identifiers in \tref{lex.name.special} have a special meaning when -appearing in a certain context. When referred to in the grammar, these identifiers -are used explicitly rather than using the \grammarterm{identifier} grammar production. -Unless otherwise specified, any ambiguity as to whether a given -\grammarterm{identifier} has a special meaning is resolved to interpret the -token as a regular \grammarterm{identifier}. +\begin{bnf} +\nontermdef{simple-escape-sequence}\br + \terminal{\textbackslash} simple-escape-sequence-char +\end{bnf} -\begin{multicolfloattable}{Identifiers with special meaning}{lex.name.special} -{llll} -\keyword{final} \\ -\columnbreak -\keyword{import} \\ -\columnbreak -\keyword{module} \\ -\columnbreak -\keyword{override} \\ -\end{multicolfloattable} +\begin{bnf} +\nontermdef{simple-escape-sequence-char} \textnormal{one of}\br + \terminal{' " ? \textbackslash{} a b f n r t v} +\end{bnf} -\pnum -\indextext{\idxcode{_}|see{character, underscore}}% -\indextext{character!underscore!in identifier}% -\indextext{reserved identifier}% -In addition, some identifiers -appearing as a \grammarterm{token} or \grammarterm{preprocessing-token} -are reserved for use by \Cpp{} -implementations and shall -not be used otherwise; no diagnostic is required. -\begin{itemize} -\item -Each identifier that contains a double underscore -\tcode{\unun} -\indextext{character!underscore}% -or begins with an underscore followed by -an uppercase letter, -other than those specified in this document -(for example, \xname{cplusplus}\iref{cpp.predefined}), -\indextext{uppercase}% -is reserved to the implementation for any use. -\item -Each identifier that begins with an underscore is -\indextext{character!underscore}% -reserved to the implementation for use as a name in the global namespace.% -\indextext{namespace!global} -\end{itemize}% -\indextext{identifier|)} +\begin{bnf} +\nontermdef{numeric-escape-sequence}\br + octal-escape-sequence\br + hexadecimal-escape-sequence +\end{bnf} -\rSec1[lex.token]{Tokens} +\begin{bnf} +\nontermdef{simple-octal-digit-sequence}\br + octal-digit\br + simple-octal-digit-sequence octal-digit +\end{bnf} -\indextext{token|(}% \begin{bnf} -\nontermdef{token}\br - identifier\br - keyword\br - literal\br - operator-or-punctuator +\nontermdef{octal-escape-sequence}\br + \terminal{\textbackslash} octal-digit\br + \terminal{\textbackslash} octal-digit octal-digit\br + \terminal{\textbackslash} octal-digit octal-digit octal-digit\br + \terminal{\textbackslash o\{} simple-octal-digit-sequence \terminal{\}}\br \end{bnf} -\pnum -\indextext{\idxgram{token}}% -There are five kinds of tokens: identifiers, keywords, literals,% -\begin{footnote} -Literals include strings and character and numeric literals. -\end{footnote} -operators, and other separators. -\indextext{whitespace}% -Blanks, horizontal and vertical tabs, newlines, formfeeds, and comments -(collectively, ``whitespace''), as described below, are ignored except -as they serve to separate tokens. -\begin{note} -Whitespace can separate otherwise adjacent identifiers, keywords, numeric -literals, and alternative tokens containing alphabetic characters. -\end{note} -\indextext{token|)} +\begin{bnf} +\nontermdef{hexadecimal-escape-sequence}\br + \terminal{\textbackslash x} simple-hexadecimal-digit-sequence\br + \terminal{\textbackslash x\{} simple-hexadecimal-digit-sequence \terminal{\}} +\end{bnf} -\rSec1[lex.key]{Keywords} +\begin{bnf} +\nontermdef{conditional-escape-sequence}\br + \terminal{\textbackslash} conditional-escape-sequence-char +\end{bnf} \begin{bnf} -\nontermdef{keyword}\br - \textnormal{any identifier listed in \tref{lex.key}}\br - \grammarterm{import-keyword}\br - \grammarterm{module-keyword}\br - \grammarterm{export-keyword} +\nontermdef{conditional-escape-sequence-char}\br + \textnormal{any member of the basic character set that is not an} octal-digit\textnormal{, a} simple-escape-sequence-char\textnormal{, or the characters \terminal{N}, \terminal{o}, \terminal{u}, \terminal{U}, or \terminal{x}} \end{bnf} \pnum -\indextext{keyword|(}% -The identifiers shown in \tref{lex.key} are reserved for use -as keywords (that is, they are unconditionally treated as keywords in -phase 7) except in an \grammarterm{attribute-token}\iref{dcl.attr.grammar}. -\begin{note} -The \keyword{register} keyword is unused but -is reserved for future use. -\end{note} - -\begin{multicolfloattable}{Keywords}{lex.key} -{lllll} -\keyword{alignas} \\ -\keyword{alignof} \\ -\keyword{asm} \\ -\keyword{auto} \\ -\keyword{bool} \\ -\keyword{break} \\ -\keyword{case} \\ -\keyword{catch} \\ -\keyword{char} \\ -\keyword{char8_t} \\ -\keyword{char16_t} \\ -\keyword{char32_t} \\ -\keyword{class} \\ -\keyword{concept} \\ -\keyword{const} \\ -\keyword{consteval} \\ -\keyword{constexpr} \\ -\columnbreak -\keyword{constinit} \\ -\keyword{const_cast} \\ -\keyword{continue} \\ -\keyword{co_await} \\ -\keyword{co_return} \\ -\keyword{co_yield} \\ -\keyword{decltype} \\ -\keyword{default} \\ -\keyword{delete} \\ -\keyword{do} \\ -\keyword{double} \\ -\keyword{dynamic_cast} \\ -\keyword{else} \\ -\keyword{enum} \\ -\keyword{explicit} \\ -\keyword{export} \\ -\keyword{extern} \\ -\columnbreak -\keyword{false} \\ -\keyword{float} \\ -\keyword{for} \\ -\keyword{friend} \\ -\keyword{goto} \\ -\keyword{if} \\ -\keyword{inline} \\ -\keyword{int} \\ -\keyword{long} \\ -\keyword{mutable} \\ -\keyword{namespace} \\ -\keyword{new} \\ -\keyword{noexcept} \\ -\keyword{nullptr} \\ -\keyword{operator} \\ -\keyword{private} \\ -\keyword{protected} \\ -\columnbreak -\keyword{public} \\ -\keyword{register} \\ -\keyword{reinterpret_cast} \\ -\keyword{requires} \\ -\keyword{return} \\ -\keyword{short} \\ -\keyword{signed} \\ -\keyword{sizeof} \\ -\keyword{static} \\ -\keyword{static_assert} \\ -\keyword{static_cast} \\ -\keyword{struct} \\ -\keyword{switch} \\ -\keyword{template} \\ -\keyword{this} \\ -\keyword{thread_local} \\ -\keyword{throw} \\ -\columnbreak -\keyword{true} \\ -\keyword{try} \\ -\keyword{typedef} \\ -\keyword{typeid} \\ -\keyword{typename} \\ -\keyword{union} \\ -\keyword{unsigned} \\ -\keyword{using} \\ -\keyword{virtual} \\ -\keyword{void} \\ -\keyword{volatile} \\ -\keyword{wchar_t} \\ -\keyword{while} \\ -\end{multicolfloattable} +\indextext{literal!character}% +\indextext{literal!\idxcode{char8_t}}% +\indextext{literal!\idxcode{char16_t}}% +\indextext{literal!\idxcode{char32_t}}% +\indextext{literal!type of character}% +\indextext{type!\idxcode{char8_t}}% +\indextext{type!\idxcode{char16_t}}% +\indextext{type!\idxcode{char32_t}}% +\indextext{wide-character}% +\indextext{type!\idxcode{wchar_t}}% +A \defnadj{multicharacter}{literal} is a \grammarterm{character-literal} +whose \grammarterm{c-char-sequence} consists of +more than one \grammarterm{c-char}. +A multicharacter literal shall not have an \grammarterm{encoding-prefix}. +If a multicharacter literal contains a \grammarterm{c-char} +that is not encodable as a single code unit in the ordinary literal encoding, +the program is ill-formed. +Multicharacter literals are conditionally-supported. \pnum -Furthermore, the alternative representations shown in -\tref{lex.key.digraph} for certain operators and -punctuators\iref{lex.digraph} are reserved and shall not be used -otherwise. +The kind of a \grammarterm{character-literal}, +its type, and its associated character encoding\iref{lex.charset} +are determined by +its \grammarterm{encoding-prefix} and its \grammarterm{c-char-sequence} +as defined by \tref{lex.ccon.literal}. -\begin{floattable}{Alternative representations}{lex.key.digraph} -{llllll} +\begin{floattable}{Character literals}{lex.ccon.literal} +{l|l|l|l|l} \topline -\keyword{and} & \keyword{and_eq} & \keyword{bitand} & \keyword{bitor} & \keyword{compl} & \keyword{not} \\ -\keyword{not_eq} & \keyword{or} & \keyword{or_eq} & \keyword{xor} & \keyword{xor_eq} & \\ -\end{floattable}% -\indextext{keyword|)}% - - -\rSec1[lex.literal]{Literals}% -\indextext{literal|(} - -\rSec2[lex.literal.kinds]{Kinds of literals} +\lhdr{Encoding} & \chdr{Kind} & \chdr{Type} & \chdr{Associated char-} & \rhdr{Example} \\ +\lhdr{prefix} & \chdr{} & \chdr{} & \chdr{acter encoding} & \\ +\capsep +none & +\defnx{ordinary character literal}{literal!character!ordinary} & +\keyword{char} & +ordinary literal & +\tcode{'v'} \\ \cline{2-3}\cline{5-5} + & +multicharacter literal & +\keyword{int} & +encoding & +\tcode{'abcd'} \\ \hline +\tcode{L} & +\defnx{wide character literal}{literal!character!wide} & +\keyword{wchar_t} & +wide literal & +\tcode{L'w'} \\ + & & & encoding & \\ \hline +\tcode{u8} & +\defnx{UTF-8 character literal}{literal!character!UTF-8} & +\keyword{char8_t} & +UTF-8 & +\tcode{u8'x'} \\ \hline +\tcode{u} & +\defnx{UTF-16 character literal}{literal!character!UTF-16} & +\keyword{char16_t} & +UTF-16 & +\tcode{u'y'} \\ \hline +\tcode{U} & +\defnx{UTF-32 character literal}{literal!character!UTF-32} & +\keyword{char32_t} & +UTF-32 & +\tcode{U'z'} \\ +\end{floattable} \pnum -\indextext{constant}% -\indextext{literal!constant}% -There are several kinds of literals. -\begin{footnote} -The term ``literal'' generally designates, in this -document, those tokens that are called ``constants'' in C. -\end{footnote} +In translation phase 4, +the value of a \grammarterm{character-literal} is determined +using the range of representable values +of the \grammarterm{character-literal}'s type in translation phase 7. +A multicharacter literal has an +\impldef{value of non-encodable character literal or multicharacter literal} +value. +The value of any other kind of \grammarterm{character-literal} +is determined as follows: +\begin{itemize} +\item +A \grammarterm{character-literal} with +a \grammarterm{c-char-sequence} consisting of a single +\grammarterm{basic-c-char}, +\grammarterm{simple-escape-sequence}, or +\grammarterm{universal-character-name} +is the code unit value of the specified character +as encoded in the literal's associated character encoding. +If the specified character lacks +representation in the literal's associated character encoding or +if it cannot be encoded as a single code unit, +then the program is ill-formed. +\item +A \grammarterm{character-literal} with +a \grammarterm{c-char-sequence} consisting of +a single \grammarterm{numeric-escape-sequence} +has a value as follows: +\begin{itemize} +\item +Let $v$ be the integer value represented by +the octal number comprising +the sequence of \grammarterm{octal-digit}{s} in +an \grammarterm{octal-escape-sequence} or by +the hexadecimal number comprising +the sequence of \grammarterm{hexadecimal-digit}{s} in +a \grammarterm{hexadecimal-escape-sequence}. +\item +If $v$ does not exceed +the range of representable values of the \grammarterm{character-literal}'s type, +then the value is $v$. +\item +Otherwise, +if the \grammarterm{character-literal}'s \grammarterm{encoding-prefix} +is absent or \tcode{L}, and +$v$ does not exceed the range of representable values of the corresponding unsigned type for the underlying type of the \grammarterm{character-literal}'s type, +then the value is the unique value of the \grammarterm{character-literal}'s type \tcode{T} that is congruent to $v$ modulo $2^N$, where $N$ is the width of \tcode{T}. +\item +Otherwise, the program is ill-formed. +\end{itemize} +\item +A \grammarterm{character-literal} with +a \grammarterm{c-char-sequence} consisting of +a single \grammarterm{conditional-escape-sequence} +is conditionally-supported and +has an \impldef{value of \grammarterm{conditional-escape-sequence}} value. +\end{itemize} -\begin{bnf} -\nontermdef{literal}\br - integer-literal\br - character-literal\br - floating-point-literal\br - string-literal\br - boolean-literal\br - pointer-literal\br - user-defined-literal -\end{bnf} +\pnum +\indextext{backslash character}% +\indextext{\idxcode{\textbackslash}|see{backslash character}}% +\indextext{escape character|see{backslash character}}% +The character specified by a \grammarterm{simple-escape-sequence} +is specified in \tref{lex.ccon.esc}. \begin{note} -When appearing as an \grammarterm{expression}, -a literal has a type and a value category\iref{expr.prim.literal}. +Using an escape sequence for a question mark +is supported for compatibility with \CppXIV{} and C. \end{note} -\rSec2[lex.icon]{Integer literals} +\begin{floattable}{Simple escape sequences}{lex.ccon.esc} +{lll} +\topline +\lhdrx{2}{character} & \rhdr{\grammarterm{simple-escape-sequence}} \\ \capsep +\ucode{000a} & \uname{line feed} & \tcode{\textbackslash n} \\ +\ucode{0009} & \uname{character tabulation} & \tcode{\textbackslash t} \\ +\ucode{000b} & \uname{line tabulation} & \tcode{\textbackslash v} \\ +\ucode{0008} & \uname{backspace} & \tcode{\textbackslash b} \\ +\ucode{000d} & \uname{carriage return} & \tcode{\textbackslash r} \\ +\ucode{000c} & \uname{form feed} & \tcode{\textbackslash f} \\ +\ucode{0007} & \uname{alert} & \tcode{\textbackslash a} \\ +\ucode{005c} & \uname{reverse solidus} & \tcode{\textbackslash\textbackslash} \\ +\ucode{003f} & \uname{question mark} & \tcode{\textbackslash ?} \\ +\ucode{0027} & \uname{apostrophe} & \tcode{\textbackslash '} \\ +\ucode{0022} & \uname{quotation mark} & \tcode{\textbackslash "} \\ +\end{floattable} -\indextext{literal!integer}% -\begin{bnf} -\nontermdef{integer-literal}\br - binary-literal \opt{integer-suffix}\br - octal-literal \opt{integer-suffix}\br - decimal-literal \opt{integer-suffix}\br - hexadecimal-literal \opt{integer-suffix} -\end{bnf} +\rSec2[lex.string]{String literals} +\indextext{literal!string}% \begin{bnf} -\nontermdef{binary-literal}\br - \terminal{0b} binary-digit\br - \terminal{0B} binary-digit\br - binary-literal \opt{\terminal{'}} binary-digit +\nontermdef{string-literal}\br + \opt{encoding-prefix} \terminal{"} \opt{s-char-sequence} \terminal{"}\br + \opt{encoding-prefix} \terminal{R} raw-string \end{bnf} \begin{bnf} -\nontermdef{octal-literal}\br - \terminal{0}\br - octal-literal \opt{\terminal{'}} octal-digit +\nontermdef{s-char-sequence}\br + s-char\br + s-char-sequence s-char \end{bnf} \begin{bnf} -\nontermdef{decimal-literal}\br - nonzero-digit\br - decimal-literal \opt{\terminal{'}} digit +\nontermdef{s-char}\br + basic-s-char\br + escape-sequence\br + universal-character-name \end{bnf} \begin{bnf} -\nontermdef{hexadecimal-literal}\br - hexadecimal-prefix hexadecimal-digit-sequence +\nontermdef{basic-s-char}\br + \textnormal{any member of the translation character set except the \unicode{0022}{quotation mark},}\br + \bnfindent\textnormal{\unicode{005c}{reverse solidus}, or new-line character} \end{bnf} \begin{bnf} -\nontermdef{binary-digit} \textnormal{one of}\br - \terminal{0 1} +\nontermdef{raw-string}\br + \terminal{"} \opt{d-char-sequence} \terminal{(} \opt{r-char-sequence} \terminal{)} \opt{d-char-sequence} \terminal{"} \end{bnf} \begin{bnf} -\nontermdef{octal-digit} \textnormal{one of}\br - \terminal{0 1 2 3 4 5 6 7} +\nontermdef{r-char-sequence}\br + r-char\br + r-char-sequence r-char \end{bnf} \begin{bnf} -\nontermdef{nonzero-digit} \textnormal{one of}\br - \terminal{1 2 3 4 5 6 7 8 9} +\nontermdef{r-char}\br + \textnormal{any member of the translation character set, except a \unicode{0029}{right parenthesis} followed by}\br + \bnfindent\textnormal{the initial \grammarterm{d-char-sequence} (which may be empty) followed by a \unicode{0022}{quotation mark}} \end{bnf} \begin{bnf} -\nontermdef{hexadecimal-prefix} \textnormal{one of}\br - \terminal{0x 0X} +\nontermdef{d-char-sequence}\br + d-char\br + d-char-sequence d-char \end{bnf} \begin{bnf} -\nontermdef{hexadecimal-digit-sequence}\br - hexadecimal-digit\br - hexadecimal-digit-sequence \opt{\terminal{'}} hexadecimal-digit +\nontermdef{d-char}\br + \textnormal{any member of the basic character set except:}\br + \bnfindent\textnormal{\unicode{0020}{space}, \unicode{0028}{left parenthesis}, \unicode{0029}{right parenthesis}, \unicode{005c}{reverse solidus},}\br + \bnfindent\textnormal{\unicode{0009}{character tabulation}, \unicode{000b}{line tabulation}, \unicode{000c}{form feed}, and new-line} \end{bnf} -\begin{bnf} -\nontermdef{hexadecimal-digit} \textnormal{one of}\br - \terminal{0 1 2 3 4 5 6 7 8 9}\br - \terminal{a b c d e f}\br - \terminal{A B C D E F} -\end{bnf} +\pnum +\indextext{literal!string}% +\indextext{character string}% +\indextext{string!type of}% +\indextext{type!\idxcode{wchar_t}}% +\indextext{prefix!\idxcode{L}}% +\indextext{literal!string!\idxcode{char16_t}}% +\indextext{type!\idxcode{char16_t}}% +\indextext{literal!string!\idxcode{char32_t}}% +\indextext{type!\idxcode{char32_t}}% +The kind of a \grammarterm{string-literal}, +its type, and +its associated character encoding\iref{lex.charset} +are determined by its encoding prefix and sequence of +\grammarterm{s-char}s or \grammarterm{r-char}s +as defined by \tref{lex.string.literal} +where $n$ is the number of encoded code units as described below. -\begin{bnf} -\nontermdef{integer-suffix}\br - unsigned-suffix \opt{long-suffix} \br - unsigned-suffix \opt{long-long-suffix} \br - unsigned-suffix \opt{size-suffix} \br - long-suffix \opt{unsigned-suffix} \br - long-long-suffix \opt{unsigned-suffix} \br - size-suffix \opt{unsigned-suffix} -\end{bnf} +\begin{floattable}{String literals}{lex.string.literal} +{llp{2.6cm}p{2.3cm}p{4.7cm}} +\topline +\lhdr{Enco-} & \chdr{Kind} & \chdr{Type} & \chdr{Associated} & \rhdr{Examples} \\ +\lhdr{ding} & \chdr{} & \chdr{} & \chdr{character} & \rhdr{} \\ +\lhdr{prefix} & \chdr{} & \chdr{} & \chdr{encoding} & \rhdr{} \\ +\capsep +none & +\defnx{ordinary string literal}{literal!string!ordinary} & +array of $n$\newline \tcode{\keyword{const} \keyword{char}} & +ordinary literal encoding & +\tcode{"ordinary string"}\newline +\tcode{R"(ordinary raw string)"} \\ +\tcode{L} & +\defnx{wide string literal}{literal!string!wide} & +array of $n$\newline \tcode{\keyword{const} \keyword{wchar_t}} & +wide literal\newline encoding & +\tcode{L"wide string"}\newline +\tcode{LR"w(wide raw string)w"} \\ +\tcode{u8} & +\defnx{UTF-8 string literal}{literal!string!UTF-8} & +array of $n$\newline \tcode{\keyword{const} \keyword{char8_t}} & +UTF-8 & +\tcode{u8"UTF-8 string"}\newline +\tcode{u8R"x(UTF-8 raw string)x"} \\ +\tcode{u} & +\defnx{UTF-16 string literal}{literal!string!UTF-16} & +array of $n$\newline \tcode{\keyword{const} \keyword{char16_t}} & +UTF-16 & +\tcode{u"UTF-16 string"}\newline +\tcode{uR"y(UTF-16 raw string)y"} \\ +\tcode{U} & +\defnx{UTF-32 string literal}{literal!string!UTF-32} & +array of $n$\newline \tcode{\keyword{const} \keyword{char32_t}} & +UTF-32 & +\tcode{U"UTF-32 string"}\newline +\tcode{UR"z(UTF-32 raw string)z"} \\ +\end{floattable} -\begin{bnf} -\nontermdef{unsigned-suffix} \textnormal{one of}\br - \terminal{u U} -\end{bnf} +\pnum +\indextext{literal!string!raw}% +A \grammarterm{string-literal} that has an \tcode{R} +\indextext{prefix!\idxcode{R}}% +in the prefix is a \defn{raw string literal}. The +\grammarterm{d-char-sequence} serves as a delimiter. The terminating +\grammarterm{d-char-sequence} of a \grammarterm{raw-string} is the same sequence of +characters as the initial \grammarterm{d-char-sequence}. A \grammarterm{d-char-sequence} +shall consist of at most 16 characters. -\begin{bnf} -\nontermdef{long-suffix} \textnormal{one of}\br - \terminal{l L} -\end{bnf} +\pnum +\begin{note} +The characters \tcode{'('} and \tcode{')'} can appear in a +\grammarterm{raw-string}. Thus, \tcode{R"delimiter((a|b))delimiter"} is equivalent to +\tcode{"(a|b)"}. +\end{note} -\begin{bnf} -\nontermdef{long-long-suffix} \textnormal{one of}\br - \terminal{ll LL} -\end{bnf} +\pnum +\begin{note} +A source-file new-line in a raw string literal results in a new-line in the +resulting execution string literal. Assuming no +whitespace at the beginning of lines in the following example, the assert will succeed: +\begin{codeblock} +const char* p = R"(a\ +b +c)"; +assert(std::strcmp(p, "a\\\nb\nc") == 0); +\end{codeblock} +\end{note} -\begin{bnf} -\nontermdef{size-suffix} \textnormal{one of}\br - \terminal{z Z} -\end{bnf} +\pnum +\begin{example} +The raw string +\begin{codeblock} +R"a( +)\ +a" +)a" +\end{codeblock} +is equivalent to \tcode{"\textbackslash n)\textbackslash \textbackslash \textbackslash na\textbackslash"\textbackslash n"}. The raw string +\begin{codeblock} +R"(x = "\"y\"")" +\end{codeblock} +is equivalent to \tcode{"x = \textbackslash "\textbackslash\textbackslash\textbackslash "y\textbackslash\textbackslash\textbackslash "\textbackslash ""}. +\end{example} \pnum -\indextext{literal!\idxcode{unsigned}}% -\indextext{literal!\idxcode{long}}% -\indextext{literal!base of integer}% -In an \grammarterm{integer-literal}, -the sequence of -\grammarterm{binary-digit}s, -\grammarterm{octal-digit}s, -\grammarterm{digit}s, or -\grammarterm{hexadecimal-digit}s -is interpreted as a base $N$ integer as shown in table \tref{lex.icon.base}; -the lexically first digit of the sequence of digits is the most significant. +\indextext{literal!narrow-character}% +Ordinary string literals and UTF-8 string literals are +also referred to as \defnx{narrow string literals}{literal!string!narrow}. + +\pnum +\indextext{concatenation!string}% +The \grammarterm{string-literal}{s} in +any sequence of adjacent \grammarterm{string-literal}{s} +shall have at most one unique \grammarterm{encoding-prefix} among them. +The common \grammarterm{encoding-prefix} of the sequence is +that \grammarterm{encoding-prefix}, if any. \begin{note} -The prefix and any optional separating single quotes are ignored -when determining the value. +A \grammarterm{string-literal}'s rawness has +no effect on the determination of the common \grammarterm{encoding-prefix}. \end{note} -\begin{simpletypetable} -{Base of \grammarterm{integer-literal}{s}} -{lex.icon.base} -{lr} -\topline -\lhdr{Kind of \grammarterm{integer-literal}} & \rhdr{base $N$} \\ \capsep -\grammarterm{binary-literal} & 2 \\ -\grammarterm{octal-literal} & 8 \\ -\grammarterm{decimal-literal} & 10 \\ -\grammarterm{hexadecimal-literal} & 16 \\ -\end{simpletypetable} - \pnum -The \grammarterm{hexadecimal-digit}s -\tcode{a} through \tcode{f} and \tcode{A} through \tcode{F} -have decimal values ten through fifteen. +In translation phase 6\iref{lex.phases}, +adjacent \grammarterm{string-literal}s are concatenated. +The lexical structure and grouping of +the contents of the individual \grammarterm{string-literal}s is retained. \begin{example} -The number twelve can be written \tcode{12}, \tcode{014}, -\tcode{0XC}, or \tcode{0b1100}. The \grammarterm{integer-literal}s \tcode{1048576}, -\tcode{1'048'576}, \tcode{0X100000}, \tcode{0x10'0000}, and -\tcode{0'004'000'000} all have the same value. +\begin{codeblock} +"\xA" "B" +\end{codeblock} +represents +the code unit \tcode{'\textbackslash xA'} and the character \tcode{'B'} +after concatenation +(and not the single code unit \tcode{'\textbackslash xAB'}). +Similarly, +\begin{codeblock} +R"(\u00)" "41" +\end{codeblock} +represents six characters, +starting with a backslash and ending with the digit \tcode{1} +(and not the single character \tcode{'A'} +specified by a \grammarterm{universal-character-name}). + +\tref{lex.string.concat} has some examples of valid concatenations. \end{example} +\begin{floattable}{String literal concatenations}{lex.string.concat} +{lll|lll|lll} +\topline +\multicolumn{2}{|c}{Source} & +Means & +\multicolumn{2}{c}{Source} & +Means & +\multicolumn{2}{c}{Source} & +Means \\ +\tcode{u"a"} & \tcode{u"b"} & \tcode{u"ab"} & +\tcode{U"a"} & \tcode{U"b"} & \tcode{U"ab"} & +\tcode{L"a"} & \tcode{L"b"} & \tcode{L"ab"} \\ +\tcode{u"a"} & \tcode{"b"} & \tcode{u"ab"} & +\tcode{U"a"} & \tcode{"b"} & \tcode{U"ab"} & +\tcode{L"a"} & \tcode{"b"} & \tcode{L"ab"} \\ +\tcode{"a"} & \tcode{u"b"} & \tcode{u"ab"} & +\tcode{"a"} & \tcode{U"b"} & \tcode{U"ab"} & +\tcode{"a"} & \tcode{L"b"} & \tcode{L"ab"} \\ +\end{floattable} + \pnum -\indextext{literal!\idxcode{long}}% -\indextext{literal!\idxcode{unsigned}}% -\indextext{literal!integer}% -\indextext{literal!type of integer}% -\indextext{suffix!\idxcode{L}}% -\indextext{suffix!\idxcode{U}}% -\indextext{suffix!\idxcode{l}}% -\indextext{suffix!\idxcode{u}}% -The type of an \grammarterm{integer-literal} is -the first type in the list in \tref{lex.icon.type} -corresponding to its optional \grammarterm{integer-suffix} -in which its value can be represented. - -\begin{floattable}{Types of \grammarterm{integer-literal}s}{lex.icon.type}{l|l|l} -\topline -\lhdr{\grammarterm{integer-suffix}} & \chdr{\grammarterm{decimal-literal}} & \rhdr{\grammarterm{integer-literal} other than \grammarterm{decimal-literal}} \\ \capsep -none & - \tcode{int} & - \tcode{int}\\ - & - \tcode{long int} & - \tcode{unsigned int}\\ - & - \tcode{long long int} & - \tcode{long int}\\ - & - & - \tcode{unsigned long int}\\ - & - & - \tcode{long long int}\\ - & - & - \tcode{unsigned long long int}\\\hline -\tcode{u} or \tcode{U} & - \tcode{unsigned int} & - \tcode{unsigned int}\\ - & - \tcode{unsigned long int} & - \tcode{unsigned long int}\\ - & - \tcode{unsigned long long int} & - \tcode{unsigned long long int}\\\hline -\tcode{l} or \tcode{L} & - \tcode{long int} & - \tcode{long int}\\ - & - \tcode{long long int} & - \tcode{unsigned long int}\\ - & - & - \tcode{long long int}\\ - & - & - \tcode{unsigned long long int}\\\hline -Both \tcode{u} or \tcode{U} & - \tcode{unsigned long int} & - \tcode{unsigned long int}\\ -and \tcode{l} or \tcode{L} & - \tcode{unsigned long long int} & - \tcode{unsigned long long int}\\\hline -\tcode{ll} or \tcode{LL} & - \tcode{long long int} & - \tcode{long long int}\\ - & - & - \tcode{unsigned long long int}\\\hline -Both \tcode{u} or \tcode{U} & - \tcode{unsigned long long int} & - \tcode{unsigned long long int}\\ -and \tcode{ll} or \tcode{LL} & - & - \\\hline -\tcode{z} or \tcode{Z} & - the signed integer type corresponding & - the signed integer type \\ - & - \qquad to \tcode{std::size_t}\iref{support.types.layout} & - \qquad corresponding to \tcode{std::size_t} \\ - & - & - \tcode{std::size_t}\\\hline -Both \tcode{u} or \tcode{U} & - \tcode{std::size_t} & - \tcode{std::size_t} \\ -and \tcode{z} or \tcode{Z} & - & - \\ -\end{floattable} +Evaluating a \grammarterm{string-literal} results in a string literal object +with static storage duration\iref{basic.stc}. +\begin{note} +String literal objects are potentially non-unique\iref{intro.object}. +Whether successive evaluations of a +\grammarterm{string-literal} yield the same or a different object is +unspecified. +\end{note} +\begin{note} +\indextext{literal!string!undefined change to}% +The effect of attempting to modify a string literal object is undefined. +\end{note} \pnum -Except for \grammarterm{integer-literal}{s} containing -a \grammarterm{size-suffix}, -if the value of an \grammarterm{integer-literal} -cannot be represented by any type in its list and -an extended integer type\iref{basic.fundamental} can represent its value, -it may have that extended integer type. -If all of the types in the list for the \grammarterm{integer-literal} -are signed, -the extended integer type is signed. -If all of the types in the list for the \grammarterm{integer-literal} -are unsigned, -the extended integer type is unsigned. -If the list contains both signed and unsigned types, -the extended integer type may be signed or unsigned. -If an \grammarterm{integer-literal} -cannot be represented by any of the allowed types, -the program is ill-formed. +\indextext{\idxcode{0}!string terminator}% +\indextext{\idxcode{0}!null character|see {character, null}}% +String literal objects are initialized with +the sequence of code unit values +corresponding to the \grammarterm{string-literal}'s sequence of +\grammarterm{s-char}s (originally from non-raw string literals) and +\grammarterm{r-char}s (originally from raw string literals), +plus a terminating \unicode{0000}{null} character, +in order as follows: +\begin{itemize} +\item +The sequence of characters denoted by each contiguous sequence of +\grammarterm{basic-s-char}s, +\grammarterm{r-char}s, +\grammarterm{simple-escape-sequence}s\iref{lex.ccon}, and +\grammarterm{universal-character-name}s\iref{lex.charset} +is encoded to a code unit sequence +using the \grammarterm{string-literal}'s associated character encoding. +If a character lacks representation in the associated character encoding, +then the program is ill-formed. \begin{note} -An \grammarterm{integer-literal} with a \tcode{z} or \tcode{Z} suffix -is ill-formed if it cannot be represented by \tcode{std::size_t}. +No character lacks representation in any Unicode encoding form. +\end{note} +When encoding a stateful character encoding, +implementations should encode the first such sequence +beginning with the initial encoding state and +encode subsequent sequences +beginning with the final encoding state of the prior sequence. +\begin{note} +The encoded code unit sequence can differ from +the sequence of code units that would be obtained by +encoding each character independently. \end{note} +\item +Each \grammarterm{numeric-escape-sequence}\iref{lex.ccon} +contributes a single code unit with a value as follows: +\begin{itemize} +\item +Let $v$ be the integer value represented by +the octal number comprising +the sequence of \grammarterm{octal-digit}{s} in +an \grammarterm{octal-escape-sequence} or by +the hexadecimal number comprising +the sequence of \grammarterm{hexadecimal-digit}{s} in +a \grammarterm{hexadecimal-escape-sequence}. +\item +If $v$ does not exceed the range of representable values of +the \grammarterm{string-literal}'s array element type, +then the value is $v$. +\item +Otherwise, +if the \grammarterm{string-literal}'s \grammarterm{encoding-prefix} +is absent or \tcode{L}, and +$v$ does not exceed the range of representable values of +the corresponding unsigned type for the underlying type of +the \grammarterm{string-literal}'s array element type, +then the value is the unique value of +the \grammarterm{string-literal}'s array element type \tcode{T} +that is congruent to $v$ modulo $2^N$, where $N$ is the width of \tcode{T}. +\item +Otherwise, the program is ill-formed. +\end{itemize} +When encoding a stateful character encoding, +these sequences should have no effect on encoding state. +\item +Each \grammarterm{conditional-escape-sequence}\iref{lex.ccon} +contributes an +\impldef{code unit sequence for \grammarterm{conditional-escape-sequence}} +code unit sequence. +When encoding a stateful character encoding, +it is +\impldef{effect of \grammarterm{conditional-escape-sequence} on encoding state} +what effect these sequences have on encoding state. +\end{itemize} -\rSec2[lex.ccon]{Character literals} +\rSec2[lex.name]{Identifiers} -\indextext{literal!character}% +\indextext{identifier|(}% \begin{bnf} -\nontermdef{character-literal}\br - \opt{encoding-prefix} \terminal{'} c-char-sequence \terminal{'} +\nontermdef{identifier}\br + identifier-start\br + identifier identifier-continue \end{bnf} \begin{bnf} -\nontermdef{encoding-prefix} \textnormal{one of}\br - \terminal{u8}\quad\terminal{u}\quad\terminal{U}\quad\terminal{L} +\nontermdef{identifier-start}\br + nondigit\br + \textnormal{an element of the translation character set with the Unicode property XID_Start} \end{bnf} \begin{bnf} -\nontermdef{c-char-sequence}\br - c-char\br - c-char-sequence c-char +\nontermdef{identifier-continue}\br + digit\br + nondigit\br + \textnormal{an element of the translation character set with the Unicode property XID_Continue} \end{bnf} \begin{bnf} -\nontermdef{c-char}\br - basic-c-char\br - escape-sequence\br - universal-character-name +\nontermdef{nondigit} \textnormal{one of}\br + \terminal{a b c d e f g h i j k l m}\br + \terminal{n o p q r s t u v w x y z}\br + \terminal{A B C D E F G H I J K L M}\br + \terminal{N O P Q R S T U V W X Y Z _} \end{bnf} \begin{bnf} -\nontermdef{basic-c-char}\br - \textnormal{any member of the translation character set except the \unicode{0027}{apostrophe},}\br - \bnfindent\textnormal{\unicode{005c}{reverse solidus}, or new-line character} +\nontermdef{digit} \textnormal{one of}\br + \terminal{0 1 2 3 4 5 6 7 8 9} \end{bnf} -\begin{bnf} -\nontermdef{escape-sequence}\br - simple-escape-sequence\br - numeric-escape-sequence\br - conditional-escape-sequence -\end{bnf} +\pnum +\indextext{name!length of}% +\indextext{name}% +\begin{note} +The character properties XID_Start and XID_Continue are Derived Core Properties +as described by \UAX{44} of the Unicode Standard. +\begin{footnote} +On systems in which linkers cannot accept extended +characters, an encoding of the \grammarterm{universal-character-name} can be used in +forming valid external identifiers. For example, some otherwise unused +character or sequence of characters can be used to encode the +\tcode{\textbackslash u} in a \grammarterm{universal-character-name}. Extended +characters can produce a long external identifier, but \Cpp{} does not +place a translation limit on significant characters for external +identifiers. +\end{footnote} +\end{note} +The program is ill-formed +if an \grammarterm{identifier} does not conform to +Normalization Form C as specified in the Unicode Standard. +\begin{note} +Identifiers are case-sensitive. +\end{note} +\begin{note} +\ref{uaxid} compares the requirements of \UAX{31} of the Unicode Standard +with the \Cpp{} rules for identifiers. +\end{note} +\begin{note} +In translation phase 4, +\grammarterm{identifier} also includes +those \grammarterm{preprocessing-token}s\iref{lex.pptoken} +differentiated as keywords\iref{lex.key} +in the later translation phase 7\iref{lex.token}. +\end{note} -\begin{bnf} -\nontermdef{simple-escape-sequence}\br - \terminal{\textbackslash} simple-escape-sequence-char -\end{bnf} +\pnum +\indextext{\idxcode{import}}% +\indextext{\idxcode{final}}% +\indextext{\idxcode{module}}% +\indextext{\idxcode{override}}% +The identifiers in \tref{lex.name.special} have a special meaning when +appearing in a certain context. When referred to in the grammar, these identifiers +are used explicitly rather than using the \grammarterm{identifier} grammar production. +Unless otherwise specified, any ambiguity as to whether a given +\grammarterm{identifier} has a special meaning is resolved to interpret the +token as a regular \grammarterm{identifier}. -\begin{bnf} -\nontermdef{simple-escape-sequence-char} \textnormal{one of}\br - \terminal{' " ? \textbackslash{} a b f n r t v} +\begin{multicolfloattable}{Identifiers with special meaning}{lex.name.special} +{llll} +\keyword{final} \\ +\columnbreak +\keyword{import} \\ +\columnbreak +\keyword{module} \\ +\columnbreak +\keyword{override} \\ +\end{multicolfloattable} + +\pnum +\indextext{\idxcode{_}|see{character, underscore}}% +\indextext{character!underscore!in identifier}% +\indextext{reserved identifier}% +In addition, some identifiers +appearing as a \grammarterm{token} or \grammarterm{preprocessing-token} +are reserved for use by \Cpp{} +implementations and shall +not be used otherwise; no diagnostic is required. +\begin{itemize} +\item +Each identifier that contains a double underscore +\tcode{\unun} +\indextext{character!underscore}% +or begins with an underscore followed by +an uppercase letter, +other than those specified in this document +(for example, \xname{cplusplus}\iref{cpp.predefined}), +\indextext{uppercase}% +is reserved to the implementation for any use. +\item +Each identifier that begins with an underscore is +\indextext{character!underscore}% +reserved to the implementation for use as a name in the global namespace.% +\indextext{namespace!global} +\end{itemize}% +\indextext{identifier|)} + + + + +\rSec1[lex.ppexec]{Preprocessor execution} + + + + +\rSec1[lex.tokenize]{Tokenization} +\rSec2[lex.token]{Tokens} + +\indextext{token|(}% +\begin{bnf} +\nontermdef{token}\br + identifier\br + keyword\br + literal\br + operator-or-punctuator \end{bnf} +\pnum +\indextext{\idxgram{token}}% +There are five kinds of tokens: identifiers, keywords, literals,% +\begin{footnote} +Literals include strings and character and numeric literals. +\end{footnote} +operators, and other separators. +\indextext{whitespace}% +Blanks, horizontal and vertical tabs, newlines, formfeeds, and comments +(collectively, ``whitespace''), as described below, are ignored except +as they serve to separate tokens. +\begin{note} +Whitespace can separate otherwise adjacent identifiers, keywords, numeric +literals, and alternative tokens containing alphabetic characters. +\end{note} +\indextext{token|)} + +\rSec2[lex.key]{Keywords} + \begin{bnf} -\nontermdef{numeric-escape-sequence}\br - octal-escape-sequence\br - hexadecimal-escape-sequence +\nontermdef{keyword}\br + \textnormal{any identifier listed in \tref{lex.key}}\br + \grammarterm{import-keyword}\br + \grammarterm{module-keyword}\br + \grammarterm{export-keyword} \end{bnf} +\pnum +\indextext{keyword|(}% +The identifiers shown in \tref{lex.key} are reserved for use +as keywords (that is, they are unconditionally treated as keywords in +phase 7) except in an \grammarterm{attribute-token}\iref{dcl.attr.grammar}. +\begin{note} +The \keyword{register} keyword is unused but +is reserved for future use. +\end{note} + +\begin{multicolfloattable}{Keywords}{lex.key} +{lllll} +\keyword{alignas} \\ +\keyword{alignof} \\ +\keyword{asm} \\ +\keyword{auto} \\ +\keyword{bool} \\ +\keyword{break} \\ +\keyword{case} \\ +\keyword{catch} \\ +\keyword{char} \\ +\keyword{char8_t} \\ +\keyword{char16_t} \\ +\keyword{char32_t} \\ +\keyword{class} \\ +\keyword{concept} \\ +\keyword{const} \\ +\keyword{consteval} \\ +\keyword{constexpr} \\ +\columnbreak +\keyword{constinit} \\ +\keyword{const_cast} \\ +\keyword{continue} \\ +\keyword{co_await} \\ +\keyword{co_return} \\ +\keyword{co_yield} \\ +\keyword{decltype} \\ +\keyword{default} \\ +\keyword{delete} \\ +\keyword{do} \\ +\keyword{double} \\ +\keyword{dynamic_cast} \\ +\keyword{else} \\ +\keyword{enum} \\ +\keyword{explicit} \\ +\keyword{export} \\ +\keyword{extern} \\ +\columnbreak +\keyword{false} \\ +\keyword{float} \\ +\keyword{for} \\ +\keyword{friend} \\ +\keyword{goto} \\ +\keyword{if} \\ +\keyword{inline} \\ +\keyword{int} \\ +\keyword{long} \\ +\keyword{mutable} \\ +\keyword{namespace} \\ +\keyword{new} \\ +\keyword{noexcept} \\ +\keyword{nullptr} \\ +\keyword{operator} \\ +\keyword{private} \\ +\keyword{protected} \\ +\columnbreak +\keyword{public} \\ +\keyword{register} \\ +\keyword{reinterpret_cast} \\ +\keyword{requires} \\ +\keyword{return} \\ +\keyword{short} \\ +\keyword{signed} \\ +\keyword{sizeof} \\ +\keyword{static} \\ +\keyword{static_assert} \\ +\keyword{static_cast} \\ +\keyword{struct} \\ +\keyword{switch} \\ +\keyword{template} \\ +\keyword{this} \\ +\keyword{thread_local} \\ +\keyword{throw} \\ +\columnbreak +\keyword{true} \\ +\keyword{try} \\ +\keyword{typedef} \\ +\keyword{typeid} \\ +\keyword{typename} \\ +\keyword{union} \\ +\keyword{unsigned} \\ +\keyword{using} \\ +\keyword{virtual} \\ +\keyword{void} \\ +\keyword{volatile} \\ +\keyword{wchar_t} \\ +\keyword{while} \\ +\end{multicolfloattable} + +\pnum +Furthermore, the alternative representations shown in +\tref{lex.key.digraph} for certain operators and +punctuators\iref{lex.operators} are reserved and shall not be used +otherwise. + +\begin{floattable}{Alternative representations}{lex.key.digraph} +{llllll} +\topline +\keyword{and} & \keyword{and_eq} & \keyword{bitand} & \keyword{bitor} & \keyword{compl} & \keyword{not} \\ +\keyword{not_eq} & \keyword{or} & \keyword{or_eq} & \keyword{xor} & \keyword{xor_eq} & \\ +\end{floattable}% +\indextext{keyword|)}% + + +\rSec2[lex.literal]{Literals}% +\indextext{literal|(} + +\rSec3[lex.literal.kinds]{Kinds of literals} + +\pnum +\indextext{constant}% +\indextext{literal!constant}% +There are several kinds of literals. +\begin{footnote} +The term ``literal'' generally designates, in this +document, those tokens that are called ``constants'' in C. +\end{footnote} + \begin{bnf} -\nontermdef{simple-octal-digit-sequence}\br - octal-digit\br - simple-octal-digit-sequence octal-digit +\nontermdef{literal}\br + integer-literal\br + character-literal\br + floating-point-literal\br + string-literal\br + boolean-literal\br + pointer-literal\br + user-defined-literal \end{bnf} +\begin{note} +When appearing as an \grammarterm{expression}, +a literal has a type and a value category\iref{expr.prim.literal}. +\end{note} +\rSec3[lex.icon]{Integer literals} + +\indextext{literal!integer}% \begin{bnf} -\nontermdef{octal-escape-sequence}\br - \terminal{\textbackslash} octal-digit\br - \terminal{\textbackslash} octal-digit octal-digit\br - \terminal{\textbackslash} octal-digit octal-digit octal-digit\br - \terminal{\textbackslash o\{} simple-octal-digit-sequence \terminal{\}}\br +\nontermdef{integer-literal}\br + binary-literal \opt{integer-suffix}\br + octal-literal \opt{integer-suffix}\br + decimal-literal \opt{integer-suffix}\br + hexadecimal-literal \opt{integer-suffix} \end{bnf} \begin{bnf} -\nontermdef{hexadecimal-escape-sequence}\br - \terminal{\textbackslash x} simple-hexadecimal-digit-sequence\br - \terminal{\textbackslash x\{} simple-hexadecimal-digit-sequence \terminal{\}} +\nontermdef{binary-literal}\br + \terminal{0b} binary-digit\br + \terminal{0B} binary-digit\br + binary-literal \opt{\terminal{'}} binary-digit \end{bnf} \begin{bnf} -\nontermdef{conditional-escape-sequence}\br - \terminal{\textbackslash} conditional-escape-sequence-char +\nontermdef{octal-literal}\br + \terminal{0}\br + octal-literal \opt{\terminal{'}} octal-digit \end{bnf} \begin{bnf} -\nontermdef{conditional-escape-sequence-char}\br - \textnormal{any member of the basic character set that is not an} octal-digit\textnormal{, a} simple-escape-sequence-char\textnormal{, or the characters \terminal{N}, \terminal{o}, \terminal{u}, \terminal{U}, or \terminal{x}} +\nontermdef{decimal-literal}\br + nonzero-digit\br + decimal-literal \opt{\terminal{'}} digit \end{bnf} -\pnum -\indextext{literal!character}% -\indextext{literal!\idxcode{char8_t}}% -\indextext{literal!\idxcode{char16_t}}% -\indextext{literal!\idxcode{char32_t}}% -\indextext{literal!type of character}% -\indextext{type!\idxcode{char8_t}}% -\indextext{type!\idxcode{char16_t}}% -\indextext{type!\idxcode{char32_t}}% -\indextext{wide-character}% -\indextext{type!\idxcode{wchar_t}}% -A \defnadj{multicharacter}{literal} is a \grammarterm{character-literal} -whose \grammarterm{c-char-sequence} consists of -more than one \grammarterm{c-char}. -A multicharacter literal shall not have an \grammarterm{encoding-prefix}. -If a multicharacter literal contains a \grammarterm{c-char} -that is not encodable as a single code unit in the ordinary literal encoding, -the program is ill-formed. -Multicharacter literals are conditionally-supported. - -\pnum -The kind of a \grammarterm{character-literal}, -its type, and its associated character encoding\iref{lex.charset} -are determined by -its \grammarterm{encoding-prefix} and its \grammarterm{c-char-sequence} -as defined by \tref{lex.ccon.literal}. - -\begin{floattable}{Character literals}{lex.ccon.literal} -{l|l|l|l|l} -\topline -\lhdr{Encoding} & \chdr{Kind} & \chdr{Type} & \chdr{Associated char-} & \rhdr{Example} \\ -\lhdr{prefix} & \chdr{} & \chdr{} & \chdr{acter encoding} & \\ -\capsep -none & -\defnx{ordinary character literal}{literal!character!ordinary} & -\keyword{char} & -ordinary literal & -\tcode{'v'} \\ \cline{2-3}\cline{5-5} - & -multicharacter literal & -\keyword{int} & -encoding & -\tcode{'abcd'} \\ \hline -\tcode{L} & -\defnx{wide character literal}{literal!character!wide} & -\keyword{wchar_t} & -wide literal & -\tcode{L'w'} \\ - & & & encoding & \\ \hline -\tcode{u8} & -\defnx{UTF-8 character literal}{literal!character!UTF-8} & -\keyword{char8_t} & -UTF-8 & -\tcode{u8'x'} \\ \hline -\tcode{u} & -\defnx{UTF-16 character literal}{literal!character!UTF-16} & -\keyword{char16_t} & -UTF-16 & -\tcode{u'y'} \\ \hline -\tcode{U} & -\defnx{UTF-32 character literal}{literal!character!UTF-32} & -\keyword{char32_t} & -UTF-32 & -\tcode{U'z'} \\ -\end{floattable} - -\pnum -In translation phase 4, -the value of a \grammarterm{character-literal} is determined -using the range of representable values -of the \grammarterm{character-literal}'s type in translation phase 7. -A multicharacter literal has an -\impldef{value of non-encodable character literal or multicharacter literal} -value. -The value of any other kind of \grammarterm{character-literal} -is determined as follows: -\begin{itemize} -\item -A \grammarterm{character-literal} with -a \grammarterm{c-char-sequence} consisting of a single -\grammarterm{basic-c-char}, -\grammarterm{simple-escape-sequence}, or -\grammarterm{universal-character-name} -is the code unit value of the specified character -as encoded in the literal's associated character encoding. -If the specified character lacks -representation in the literal's associated character encoding or -if it cannot be encoded as a single code unit, -then the program is ill-formed. -\item -A \grammarterm{character-literal} with -a \grammarterm{c-char-sequence} consisting of -a single \grammarterm{numeric-escape-sequence} -has a value as follows: -\begin{itemize} -\item -Let $v$ be the integer value represented by -the octal number comprising -the sequence of \grammarterm{octal-digit}{s} in -an \grammarterm{octal-escape-sequence} or by -the hexadecimal number comprising -the sequence of \grammarterm{hexadecimal-digit}{s} in -a \grammarterm{hexadecimal-escape-sequence}. -\item -If $v$ does not exceed -the range of representable values of the \grammarterm{character-literal}'s type, -then the value is $v$. -\item -Otherwise, -if the \grammarterm{character-literal}'s \grammarterm{encoding-prefix} -is absent or \tcode{L}, and -$v$ does not exceed the range of representable values of the corresponding unsigned type for the underlying type of the \grammarterm{character-literal}'s type, -then the value is the unique value of the \grammarterm{character-literal}'s type \tcode{T} that is congruent to $v$ modulo $2^N$, where $N$ is the width of \tcode{T}. -\item -Otherwise, the program is ill-formed. -\end{itemize} -\item -A \grammarterm{character-literal} with -a \grammarterm{c-char-sequence} consisting of -a single \grammarterm{conditional-escape-sequence} -is conditionally-supported and -has an \impldef{value of \grammarterm{conditional-escape-sequence}} value. -\end{itemize} - -\pnum -\indextext{backslash character}% -\indextext{\idxcode{\textbackslash}|see{backslash character}}% -\indextext{escape character|see{backslash character}}% -The character specified by a \grammarterm{simple-escape-sequence} -is specified in \tref{lex.ccon.esc}. -\begin{note} -Using an escape sequence for a question mark -is supported for compatibility with \CppXIV{} and C. -\end{note} - -\begin{floattable}{Simple escape sequences}{lex.ccon.esc} -{lll} -\topline -\lhdrx{2}{character} & \rhdr{\grammarterm{simple-escape-sequence}} \\ \capsep -\ucode{000a} & \uname{line feed} & \tcode{\textbackslash n} \\ -\ucode{0009} & \uname{character tabulation} & \tcode{\textbackslash t} \\ -\ucode{000b} & \uname{line tabulation} & \tcode{\textbackslash v} \\ -\ucode{0008} & \uname{backspace} & \tcode{\textbackslash b} \\ -\ucode{000d} & \uname{carriage return} & \tcode{\textbackslash r} \\ -\ucode{000c} & \uname{form feed} & \tcode{\textbackslash f} \\ -\ucode{0007} & \uname{alert} & \tcode{\textbackslash a} \\ -\ucode{005c} & \uname{reverse solidus} & \tcode{\textbackslash\textbackslash} \\ -\ucode{003f} & \uname{question mark} & \tcode{\textbackslash ?} \\ -\ucode{0027} & \uname{apostrophe} & \tcode{\textbackslash '} \\ -\ucode{0022} & \uname{quotation mark} & \tcode{\textbackslash "} \\ -\end{floattable} +\begin{bnf} +\nontermdef{hexadecimal-literal}\br + hexadecimal-prefix hexadecimal-digit-sequence +\end{bnf} -\rSec2[lex.fcon]{Floating-point literals} +\begin{bnf} +\nontermdef{binary-digit} \textnormal{one of}\br + \terminal{0 1} +\end{bnf} -\indextext{literal!floating-point}% \begin{bnf} -\nontermdef{floating-point-literal}\br - decimal-floating-point-literal\br - hexadecimal-floating-point-literal +\nontermdef{octal-digit} \textnormal{one of}\br + \terminal{0 1 2 3 4 5 6 7} \end{bnf} \begin{bnf} -\nontermdef{decimal-floating-point-literal}\br - fractional-constant \opt{exponent-part} \opt{floating-point-suffix}\br - digit-sequence exponent-part \opt{floating-point-suffix} +\nontermdef{nonzero-digit} \textnormal{one of}\br + \terminal{1 2 3 4 5 6 7 8 9} \end{bnf} \begin{bnf} -\nontermdef{hexadecimal-floating-point-literal}\br - hexadecimal-prefix hexadecimal-fractional-constant binary-exponent-part \opt{floating-point-suffix}\br - hexadecimal-prefix hexadecimal-digit-sequence binary-exponent-part \opt{floating-point-suffix} +\nontermdef{hexadecimal-prefix} \textnormal{one of}\br + \terminal{0x 0X} \end{bnf} \begin{bnf} -\nontermdef{fractional-constant}\br - \opt{digit-sequence} \terminal{.} digit-sequence\br - digit-sequence \terminal{.} +\nontermdef{hexadecimal-digit-sequence}\br + hexadecimal-digit\br + hexadecimal-digit-sequence \opt{\terminal{'}} hexadecimal-digit \end{bnf} \begin{bnf} -\nontermdef{hexadecimal-fractional-constant}\br - \opt{hexadecimal-digit-sequence} \terminal{.} hexadecimal-digit-sequence\br - hexadecimal-digit-sequence \terminal{.} +\nontermdef{hexadecimal-digit} \textnormal{one of}\br + \terminal{0 1 2 3 4 5 6 7 8 9}\br + \terminal{a b c d e f}\br + \terminal{A B C D E F} \end{bnf} \begin{bnf} -\nontermdef{exponent-part}\br - \terminal{e} \opt{sign} digit-sequence\br - \terminal{E} \opt{sign} digit-sequence +\nontermdef{integer-suffix}\br + unsigned-suffix \opt{long-suffix} \br + unsigned-suffix \opt{long-long-suffix} \br + unsigned-suffix \opt{size-suffix} \br + long-suffix \opt{unsigned-suffix} \br + long-long-suffix \opt{unsigned-suffix} \br + size-suffix \opt{unsigned-suffix} \end{bnf} \begin{bnf} -\nontermdef{binary-exponent-part}\br - \terminal{p} \opt{sign} digit-sequence\br - \terminal{P} \opt{sign} digit-sequence +\nontermdef{unsigned-suffix} \textnormal{one of}\br + \terminal{u U} \end{bnf} \begin{bnf} -\nontermdef{sign} \textnormal{one of}\br - \terminal{+ -} +\nontermdef{long-suffix} \textnormal{one of}\br + \terminal{l L} \end{bnf} \begin{bnf} -\nontermdef{digit-sequence}\br - digit\br - digit-sequence \opt{\terminal{'}} digit +\nontermdef{long-long-suffix} \textnormal{one of}\br + \terminal{ll LL} \end{bnf} \begin{bnf} -\nontermdef{floating-point-suffix} \textnormal{one of}\br - \terminal{f l f16 f32 f64 f128 bf16 F L F16 F32 F64 F128 BF16} +\nontermdef{size-suffix} \textnormal{one of}\br + \terminal{z Z} \end{bnf} \pnum -\indextext{literal!type of floating-point}% -\indextext{literal!\idxcode{float}}% -\indextext{suffix!\idxcode{F}}% -\indextext{suffix!\idxcode{f}}% -\indextext{suffix!\idxcode{L}}% -\indextext{suffix!\idxcode{l}}% -\indextext{literal!\idxcode{long double}}% -The type of -a \grammarterm{floating-point-literal}\iref{basic.fundamental,basic.extended.fp} -is determined by -its \grammarterm{floating-point-suffix} as specified in \tref{lex.fcon.type}. +\indextext{literal!\idxcode{unsigned}}% +\indextext{literal!\idxcode{long}}% +\indextext{literal!base of integer}% +In an \grammarterm{integer-literal}, +the sequence of +\grammarterm{binary-digit}s, +\grammarterm{octal-digit}s, +\grammarterm{digit}s, or +\grammarterm{hexadecimal-digit}s +is interpreted as a base $N$ integer as shown in table \tref{lex.icon.base}; +the lexically first digit of the sequence of digits is the most significant. \begin{note} -The floating-point suffixes -\tcode{f16}, \tcode{f32}, \tcode{f64}, \tcode{f128}, \tcode{bf16}, -\tcode{F16}, \tcode{F32}, \tcode{F64}, \tcode{F128}, and \tcode{BF16} -are conditionally-supported. See \ref{basic.extended.fp}. +The prefix and any optional separating single quotes are ignored +when determining the value. \end{note} + \begin{simpletypetable} -{Types of \grammarterm{floating-point-literal}{s}} -{lex.fcon.type} -{ll} +{Base of \grammarterm{integer-literal}{s}} +{lex.icon.base} +{lr} \topline -\lhdr{\grammarterm{floating-point-suffix}} & \rhdr{type} \\ \capsep -none & \keyword{double} \\ -\tcode{f} or \tcode{F} & \keyword {float} \\ -\tcode{l} or \tcode{L} & \keyword{long} \keyword{double} \\ -\tcode{f16} or \tcode{F16} & \tcode{std::float16_t} \\ -\tcode{f32} or \tcode{F32} & \tcode{std::float32_t} \\ -\tcode{f64} or \tcode{F64} & \tcode{std::float64_t} \\ -\tcode{f128} or \tcode{F128} & \tcode{std::float128_t} \\ -\tcode{bf16} or \tcode{BF16} & \tcode{std::bfloat16_t} \\ -\end{simpletypetable} +\lhdr{Kind of \grammarterm{integer-literal}} & \rhdr{base $N$} \\ \capsep +\grammarterm{binary-literal} & 2 \\ +\grammarterm{octal-literal} & 8 \\ +\grammarterm{decimal-literal} & 10 \\ +\grammarterm{hexadecimal-literal} & 16 \\ +\end{simpletypetable} + +\pnum +The \grammarterm{hexadecimal-digit}s +\tcode{a} through \tcode{f} and \tcode{A} through \tcode{F} +have decimal values ten through fifteen. +\begin{example} +The number twelve can be written \tcode{12}, \tcode{014}, +\tcode{0XC}, or \tcode{0b1100}. The \grammarterm{integer-literal}s \tcode{1048576}, +\tcode{1'048'576}, \tcode{0X100000}, \tcode{0x10'0000}, and +\tcode{0'004'000'000} all have the same value. +\end{example} + +\pnum +\indextext{literal!\idxcode{long}}% +\indextext{literal!\idxcode{unsigned}}% +\indextext{literal!integer}% +\indextext{literal!type of integer}% +\indextext{suffix!\idxcode{L}}% +\indextext{suffix!\idxcode{U}}% +\indextext{suffix!\idxcode{l}}% +\indextext{suffix!\idxcode{u}}% +The type of an \grammarterm{integer-literal} is +the first type in the list in \tref{lex.icon.type} +corresponding to its optional \grammarterm{integer-suffix} +in which its value can be represented. + +\begin{floattable}{Types of \grammarterm{integer-literal}s}{lex.icon.type}{l|l|l} +\topline +\lhdr{\grammarterm{integer-suffix}} & \chdr{\grammarterm{decimal-literal}} & \rhdr{\grammarterm{integer-literal} other than \grammarterm{decimal-literal}} \\ \capsep +none & + \tcode{int} & + \tcode{int}\\ + & + \tcode{long int} & + \tcode{unsigned int}\\ + & + \tcode{long long int} & + \tcode{long int}\\ + & + & + \tcode{unsigned long int}\\ + & + & + \tcode{long long int}\\ + & + & + \tcode{unsigned long long int}\\\hline +\tcode{u} or \tcode{U} & + \tcode{unsigned int} & + \tcode{unsigned int}\\ + & + \tcode{unsigned long int} & + \tcode{unsigned long int}\\ + & + \tcode{unsigned long long int} & + \tcode{unsigned long long int}\\\hline +\tcode{l} or \tcode{L} & + \tcode{long int} & + \tcode{long int}\\ + & + \tcode{long long int} & + \tcode{unsigned long int}\\ + & + & + \tcode{long long int}\\ + & + & + \tcode{unsigned long long int}\\\hline +Both \tcode{u} or \tcode{U} & + \tcode{unsigned long int} & + \tcode{unsigned long int}\\ +and \tcode{l} or \tcode{L} & + \tcode{unsigned long long int} & + \tcode{unsigned long long int}\\\hline +\tcode{ll} or \tcode{LL} & + \tcode{long long int} & + \tcode{long long int}\\ + & + & + \tcode{unsigned long long int}\\\hline +Both \tcode{u} or \tcode{U} & + \tcode{unsigned long long int} & + \tcode{unsigned long long int}\\ +and \tcode{ll} or \tcode{LL} & + & + \\\hline +\tcode{z} or \tcode{Z} & + the signed integer type corresponding & + the signed integer type \\ + & + \qquad to \tcode{std::size_t}\iref{support.types.layout} & + \qquad corresponding to \tcode{std::size_t} \\ + & + & + \tcode{std::size_t}\\\hline +Both \tcode{u} or \tcode{U} & + \tcode{std::size_t} & + \tcode{std::size_t} \\ +and \tcode{z} or \tcode{Z} & + & + \\ +\end{floattable} + +\pnum +Except for \grammarterm{integer-literal}{s} containing +a \grammarterm{size-suffix}, +if the value of an \grammarterm{integer-literal} +cannot be represented by any type in its list and +an extended integer type\iref{basic.fundamental} can represent its value, +it may have that extended integer type. +If all of the types in the list for the \grammarterm{integer-literal} +are signed, +the extended integer type is signed. +If all of the types in the list for the \grammarterm{integer-literal} +are unsigned, +the extended integer type is unsigned. +If the list contains both signed and unsigned types, +the extended integer type may be signed or unsigned. +If an \grammarterm{integer-literal} +cannot be represented by any of the allowed types, +the program is ill-formed. +\begin{note} +An \grammarterm{integer-literal} with a \tcode{z} or \tcode{Z} suffix +is ill-formed if it cannot be represented by \tcode{std::size_t}. +\end{note} + +\rSec3[lex.fcon]{Floating-point literals} + +\indextext{literal!floating-point}% +\begin{bnf} +\nontermdef{floating-point-literal}\br + decimal-floating-point-literal\br + hexadecimal-floating-point-literal +\end{bnf} + +\begin{bnf} +\nontermdef{decimal-floating-point-literal}\br + fractional-constant \opt{exponent-part} \opt{floating-point-suffix}\br + digit-sequence exponent-part \opt{floating-point-suffix} +\end{bnf} + +\begin{bnf} +\nontermdef{hexadecimal-floating-point-literal}\br + hexadecimal-prefix hexadecimal-fractional-constant binary-exponent-part \opt{floating-point-suffix}\br + hexadecimal-prefix hexadecimal-digit-sequence binary-exponent-part \opt{floating-point-suffix} +\end{bnf} + +\begin{bnf} +\nontermdef{fractional-constant}\br + \opt{digit-sequence} \terminal{.} digit-sequence\br + digit-sequence \terminal{.} +\end{bnf} + +\begin{bnf} +\nontermdef{hexadecimal-fractional-constant}\br + \opt{hexadecimal-digit-sequence} \terminal{.} hexadecimal-digit-sequence\br + hexadecimal-digit-sequence \terminal{.} +\end{bnf} + +\begin{bnf} +\nontermdef{exponent-part}\br + \terminal{e} \opt{sign} digit-sequence\br + \terminal{E} \opt{sign} digit-sequence +\end{bnf} + +\begin{bnf} +\nontermdef{binary-exponent-part}\br + \terminal{p} \opt{sign} digit-sequence\br + \terminal{P} \opt{sign} digit-sequence +\end{bnf} + +\begin{bnf} +\nontermdef{sign} \textnormal{one of}\br + \terminal{+ -} +\end{bnf} + +\begin{bnf} +\nontermdef{digit-sequence}\br + digit\br + digit-sequence \opt{\terminal{'}} digit +\end{bnf} + +\begin{bnf} +\nontermdef{floating-point-suffix} \textnormal{one of}\br + \terminal{f l f16 f32 f64 f128 bf16 F L F16 F32 F64 F128 BF16} +\end{bnf} + +\pnum +\indextext{literal!type of floating-point}% +\indextext{literal!\idxcode{float}}% +\indextext{suffix!\idxcode{F}}% +\indextext{suffix!\idxcode{f}}% +\indextext{suffix!\idxcode{L}}% +\indextext{suffix!\idxcode{l}}% +\indextext{literal!\idxcode{long double}}% +The type of +a \grammarterm{floating-point-literal}\iref{basic.fundamental,basic.extended.fp} +is determined by +its \grammarterm{floating-point-suffix} as specified in \tref{lex.fcon.type}. +\begin{note} +The floating-point suffixes +\tcode{f16}, \tcode{f32}, \tcode{f64}, \tcode{f128}, \tcode{bf16}, +\tcode{F16}, \tcode{F32}, \tcode{F64}, \tcode{F128}, and \tcode{BF16} +are conditionally-supported. See \ref{basic.extended.fp}. +\end{note} +\begin{simpletypetable} +{Types of \grammarterm{floating-point-literal}{s}} +{lex.fcon.type} +{ll} +\topline +\lhdr{\grammarterm{floating-point-suffix}} & \rhdr{type} \\ \capsep +none & \keyword{double} \\ +\tcode{f} or \tcode{F} & \keyword {float} \\ +\tcode{l} or \tcode{L} & \keyword{long} \keyword{double} \\ +\tcode{f16} or \tcode{F16} & \tcode{std::float16_t} \\ +\tcode{f32} or \tcode{F32} & \tcode{std::float32_t} \\ +\tcode{f64} or \tcode{F64} & \tcode{std::float64_t} \\ +\tcode{f128} or \tcode{F128} & \tcode{std::float128_t} \\ +\tcode{bf16} or \tcode{BF16} & \tcode{std::bfloat16_t} \\ +\end{simpletypetable} \pnum \indextext{literal!floating-point}% @@ -1741,320 +2060,7 @@ chosen in an \impldef{choice of larger or smaller value of \grammarterm{floating-point-literal}} manner. -\rSec2[lex.string]{String literals} - -\indextext{literal!string}% -\begin{bnf} -\nontermdef{string-literal}\br - \opt{encoding-prefix} \terminal{"} \opt{s-char-sequence} \terminal{"}\br - \opt{encoding-prefix} \terminal{R} raw-string -\end{bnf} - -\begin{bnf} -\nontermdef{s-char-sequence}\br - s-char\br - s-char-sequence s-char -\end{bnf} - -\begin{bnf} -\nontermdef{s-char}\br - basic-s-char\br - escape-sequence\br - universal-character-name -\end{bnf} - -\begin{bnf} -\nontermdef{basic-s-char}\br - \textnormal{any member of the translation character set except the \unicode{0022}{quotation mark},}\br - \bnfindent\textnormal{\unicode{005c}{reverse solidus}, or new-line character} -\end{bnf} - -\begin{bnf} -\nontermdef{raw-string}\br - \terminal{"} \opt{d-char-sequence} \terminal{(} \opt{r-char-sequence} \terminal{)} \opt{d-char-sequence} \terminal{"} -\end{bnf} - -\begin{bnf} -\nontermdef{r-char-sequence}\br - r-char\br - r-char-sequence r-char -\end{bnf} - -\begin{bnf} -\nontermdef{r-char}\br - \textnormal{any member of the translation character set, except a \unicode{0029}{right parenthesis} followed by}\br - \bnfindent\textnormal{the initial \grammarterm{d-char-sequence} (which may be empty) followed by a \unicode{0022}{quotation mark}} -\end{bnf} - -\begin{bnf} -\nontermdef{d-char-sequence}\br - d-char\br - d-char-sequence d-char -\end{bnf} - -\begin{bnf} -\nontermdef{d-char}\br - \textnormal{any member of the basic character set except:}\br - \bnfindent\textnormal{\unicode{0020}{space}, \unicode{0028}{left parenthesis}, \unicode{0029}{right parenthesis}, \unicode{005c}{reverse solidus},}\br - \bnfindent\textnormal{\unicode{0009}{character tabulation}, \unicode{000b}{line tabulation}, \unicode{000c}{form feed}, and new-line} -\end{bnf} - -\pnum -\indextext{literal!string}% -\indextext{character string}% -\indextext{string!type of}% -\indextext{type!\idxcode{wchar_t}}% -\indextext{prefix!\idxcode{L}}% -\indextext{literal!string!\idxcode{char16_t}}% -\indextext{type!\idxcode{char16_t}}% -\indextext{literal!string!\idxcode{char32_t}}% -\indextext{type!\idxcode{char32_t}}% -The kind of a \grammarterm{string-literal}, -its type, and -its associated character encoding\iref{lex.charset} -are determined by its encoding prefix and sequence of -\grammarterm{s-char}s or \grammarterm{r-char}s -as defined by \tref{lex.string.literal} -where $n$ is the number of encoded code units as described below. - -\begin{floattable}{String literals}{lex.string.literal} -{llp{2.6cm}p{2.3cm}p{4.7cm}} -\topline -\lhdr{Enco-} & \chdr{Kind} & \chdr{Type} & \chdr{Associated} & \rhdr{Examples} \\ -\lhdr{ding} & \chdr{} & \chdr{} & \chdr{character} & \rhdr{} \\ -\lhdr{prefix} & \chdr{} & \chdr{} & \chdr{encoding} & \rhdr{} \\ -\capsep -none & -\defnx{ordinary string literal}{literal!string!ordinary} & -array of $n$\newline \tcode{\keyword{const} \keyword{char}} & -ordinary literal encoding & -\tcode{"ordinary string"}\newline -\tcode{R"(ordinary raw string)"} \\ -\tcode{L} & -\defnx{wide string literal}{literal!string!wide} & -array of $n$\newline \tcode{\keyword{const} \keyword{wchar_t}} & -wide literal\newline encoding & -\tcode{L"wide string"}\newline -\tcode{LR"w(wide raw string)w"} \\ -\tcode{u8} & -\defnx{UTF-8 string literal}{literal!string!UTF-8} & -array of $n$\newline \tcode{\keyword{const} \keyword{char8_t}} & -UTF-8 & -\tcode{u8"UTF-8 string"}\newline -\tcode{u8R"x(UTF-8 raw string)x"} \\ -\tcode{u} & -\defnx{UTF-16 string literal}{literal!string!UTF-16} & -array of $n$\newline \tcode{\keyword{const} \keyword{char16_t}} & -UTF-16 & -\tcode{u"UTF-16 string"}\newline -\tcode{uR"y(UTF-16 raw string)y"} \\ -\tcode{U} & -\defnx{UTF-32 string literal}{literal!string!UTF-32} & -array of $n$\newline \tcode{\keyword{const} \keyword{char32_t}} & -UTF-32 & -\tcode{U"UTF-32 string"}\newline -\tcode{UR"z(UTF-32 raw string)z"} \\ -\end{floattable} - -\pnum -\indextext{literal!string!raw}% -A \grammarterm{string-literal} that has an \tcode{R} -\indextext{prefix!\idxcode{R}}% -in the prefix is a \defn{raw string literal}. The -\grammarterm{d-char-sequence} serves as a delimiter. The terminating -\grammarterm{d-char-sequence} of a \grammarterm{raw-string} is the same sequence of -characters as the initial \grammarterm{d-char-sequence}. A \grammarterm{d-char-sequence} -shall consist of at most 16 characters. - -\pnum -\begin{note} -The characters \tcode{'('} and \tcode{')'} can appear in a -\grammarterm{raw-string}. Thus, \tcode{R"delimiter((a|b))delimiter"} is equivalent to -\tcode{"(a|b)"}. -\end{note} - -\pnum -\begin{note} -A source-file new-line in a raw string literal results in a new-line in the -resulting execution string literal. Assuming no -whitespace at the beginning of lines in the following example, the assert will succeed: -\begin{codeblock} -const char* p = R"(a\ -b -c)"; -assert(std::strcmp(p, "a\\\nb\nc") == 0); -\end{codeblock} -\end{note} - -\pnum -\begin{example} -The raw string -\begin{codeblock} -R"a( -)\ -a" -)a" -\end{codeblock} -is equivalent to \tcode{"\textbackslash n)\textbackslash \textbackslash \textbackslash na\textbackslash"\textbackslash n"}. The raw string -\begin{codeblock} -R"(x = "\"y\"")" -\end{codeblock} -is equivalent to \tcode{"x = \textbackslash "\textbackslash\textbackslash\textbackslash "y\textbackslash\textbackslash\textbackslash "\textbackslash ""}. -\end{example} - -\pnum -\indextext{literal!narrow-character}% -Ordinary string literals and UTF-8 string literals are -also referred to as \defnx{narrow string literals}{literal!string!narrow}. - -\pnum -\indextext{concatenation!string}% -The \grammarterm{string-literal}{s} in -any sequence of adjacent \grammarterm{string-literal}{s} -shall have at most one unique \grammarterm{encoding-prefix} among them. -The common \grammarterm{encoding-prefix} of the sequence is -that \grammarterm{encoding-prefix}, if any. -\begin{note} -A \grammarterm{string-literal}'s rawness has -no effect on the determination of the common \grammarterm{encoding-prefix}. -\end{note} - -\pnum -In translation phase 6\iref{lex.phases}, -adjacent \grammarterm{string-literal}s are concatenated. -The lexical structure and grouping of -the contents of the individual \grammarterm{string-literal}s is retained. -\begin{example} -\begin{codeblock} -"\xA" "B" -\end{codeblock} -represents -the code unit \tcode{'\textbackslash xA'} and the character \tcode{'B'} -after concatenation -(and not the single code unit \tcode{'\textbackslash xAB'}). -Similarly, -\begin{codeblock} -R"(\u00)" "41" -\end{codeblock} -represents six characters, -starting with a backslash and ending with the digit \tcode{1} -(and not the single character \tcode{'A'} -specified by a \grammarterm{universal-character-name}). - -\tref{lex.string.concat} has some examples of valid concatenations. -\end{example} - -\begin{floattable}{String literal concatenations}{lex.string.concat} -{lll|lll|lll} -\topline -\multicolumn{2}{|c}{Source} & -Means & -\multicolumn{2}{c}{Source} & -Means & -\multicolumn{2}{c}{Source} & -Means \\ -\tcode{u"a"} & \tcode{u"b"} & \tcode{u"ab"} & -\tcode{U"a"} & \tcode{U"b"} & \tcode{U"ab"} & -\tcode{L"a"} & \tcode{L"b"} & \tcode{L"ab"} \\ -\tcode{u"a"} & \tcode{"b"} & \tcode{u"ab"} & -\tcode{U"a"} & \tcode{"b"} & \tcode{U"ab"} & -\tcode{L"a"} & \tcode{"b"} & \tcode{L"ab"} \\ -\tcode{"a"} & \tcode{u"b"} & \tcode{u"ab"} & -\tcode{"a"} & \tcode{U"b"} & \tcode{U"ab"} & -\tcode{"a"} & \tcode{L"b"} & \tcode{L"ab"} \\ -\end{floattable} - -\pnum -Evaluating a \grammarterm{string-literal} results in a string literal object -with static storage duration\iref{basic.stc}. -\begin{note} -String literal objects are potentially non-unique\iref{intro.object}. -Whether successive evaluations of a -\grammarterm{string-literal} yield the same or a different object is -unspecified. -\end{note} -\begin{note} -\indextext{literal!string!undefined change to}% -The effect of attempting to modify a string literal object is undefined. -\end{note} - -\pnum -\indextext{\idxcode{0}!string terminator}% -\indextext{\idxcode{0}!null character|see {character, null}}% -String literal objects are initialized with -the sequence of code unit values -corresponding to the \grammarterm{string-literal}'s sequence of -\grammarterm{s-char}s (originally from non-raw string literals) and -\grammarterm{r-char}s (originally from raw string literals), -plus a terminating \unicode{0000}{null} character, -in order as follows: -\begin{itemize} -\item -The sequence of characters denoted by each contiguous sequence of -\grammarterm{basic-s-char}s, -\grammarterm{r-char}s, -\grammarterm{simple-escape-sequence}s\iref{lex.ccon}, and -\grammarterm{universal-character-name}s\iref{lex.charset} -is encoded to a code unit sequence -using the \grammarterm{string-literal}'s associated character encoding. -If a character lacks representation in the associated character encoding, -then the program is ill-formed. -\begin{note} -No character lacks representation in any Unicode encoding form. -\end{note} -When encoding a stateful character encoding, -implementations should encode the first such sequence -beginning with the initial encoding state and -encode subsequent sequences -beginning with the final encoding state of the prior sequence. -\begin{note} -The encoded code unit sequence can differ from -the sequence of code units that would be obtained by -encoding each character independently. -\end{note} -\item -Each \grammarterm{numeric-escape-sequence}\iref{lex.ccon} -contributes a single code unit with a value as follows: -\begin{itemize} -\item -Let $v$ be the integer value represented by -the octal number comprising -the sequence of \grammarterm{octal-digit}{s} in -an \grammarterm{octal-escape-sequence} or by -the hexadecimal number comprising -the sequence of \grammarterm{hexadecimal-digit}{s} in -a \grammarterm{hexadecimal-escape-sequence}. -\item -If $v$ does not exceed the range of representable values of -the \grammarterm{string-literal}'s array element type, -then the value is $v$. -\item -Otherwise, -if the \grammarterm{string-literal}'s \grammarterm{encoding-prefix} -is absent or \tcode{L}, and -$v$ does not exceed the range of representable values of -the corresponding unsigned type for the underlying type of -the \grammarterm{string-literal}'s array element type, -then the value is the unique value of -the \grammarterm{string-literal}'s array element type \tcode{T} -that is congruent to $v$ modulo $2^N$, where $N$ is the width of \tcode{T}. -\item -Otherwise, the program is ill-formed. -\end{itemize} -When encoding a stateful character encoding, -these sequences should have no effect on encoding state. -\item -Each \grammarterm{conditional-escape-sequence}\iref{lex.ccon} -contributes an -\impldef{code unit sequence for \grammarterm{conditional-escape-sequence}} -code unit sequence. -When encoding a stateful character encoding, -it is -\impldef{effect of \grammarterm{conditional-escape-sequence} on encoding state} -what effect these sequences have on encoding state. -\end{itemize} - -\rSec2[lex.string.uneval]{Unevaluated strings} +\rSec3[lex.string.uneval]{Unevaluated strings} \begin{bnf} \nontermdef{unevaluated-string}\br @@ -2076,7 +2082,7 @@ An \grammarterm{unevaluated-string} is never evaluated and its interpretation depends on the context in which it appears. -\rSec2[lex.bool]{Boolean literals} +\rSec3[lex.bool]{Boolean literals} \indextext{literal!boolean}% \begin{bnf} @@ -2090,7 +2096,7 @@ The Boolean literals are the keywords \tcode{false} and \tcode{true}. Such literals have type \tcode{bool}. -\rSec2[lex.nullptr]{Pointer literals} +\rSec3[lex.nullptr]{Pointer literals} \indextext{literal!pointer}% \begin{bnf} @@ -2108,7 +2114,7 @@ and~\ref{conv.mem}. \end{note} -\rSec2[lex.ext]{User-defined literals} +\rSec3[lex.ext]{User-defined literals} \indextext{literal!user-defined}% \begin{bnf} diff --git a/source/preprocessor.tex b/source/preprocessor.tex index 2b9e3e7e05..d0a80dadaf 100644 --- a/source/preprocessor.tex +++ b/source/preprocessor.tex @@ -465,7 +465,7 @@ and then each preprocessing token is converted into a token. \begin{note} An alternative -token\iref{lex.digraph} is not an identifier, +token\iref{lex.operators} is not an identifier, even when its spelling consists entirely of letters and underscores. Therefore it is not subject to this replacement. \end{note} @@ -1092,7 +1092,7 @@ to be replaced by the replacement list of preprocessing tokens that constitute the remainder of the directive. \begin{footnote} -An alternative token\iref{lex.digraph} is not an identifier, +An alternative token\iref{lex.operators} is not an identifier, even when its spelling consists entirely of letters and underscores. Therefore it is not possible to define a macro whose name is the same as that of an alternative token. diff --git a/source/std.tex b/source/std.tex index 8abd2d6d1e..373c487476 100644 --- a/source/std.tex +++ b/source/std.tex @@ -112,16 +112,16 @@ \include{intro} \include{lex} +\include{preprocessor} \include{modules} \include{basic} \include{expressions} \include{statements} \include{declarations} -\include{classes} \include{overloading} -\include{templates} \include{exceptions} -\include{preprocessor} +\include{classes} +\include{templates} \include{lib-intro} \include{support} \include{concepts} diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index f2d2baa2e8..2fe56a4680 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -99,6 +99,9 @@ \movedxref{diff.stat}{diff.stmt} \movedxref{stmt.stmt}{stmt} +% Lexing reorganization +\movedxref{lex.digraph}{lex.operators} + %%% Deprecated features. %%% Example: % From 04c96f6dd74839616ec8abbb5e65f3e544e599dc Mon Sep 17 00:00:00 2001 From: Alisdair Meredith Date: Sun, 29 Sep 2024 19:43:40 -0400 Subject: [PATCH 12/18] [lex][cpp] Merge [cpp] into [lex] This commit completes the planned Core reorganization by merging the preprocessor properly into Program construction, placed consistently for phase 4 of translation. The subclauses of [cpp] are similarly reorganized to put the more primitive functionality first, and putting the module related text up front, consistent with the order of the grammar. We finally bring the prohibition on defining keywords as macros out of the library introduction and directly into the specification for keywords. This is around the limit of what can be achieved before rewriting text to further reduce duplication, and to make the distinction of preprocessor-identifiers and TU-identifiers clear. --- source/lex.tex | 2107 ++++++++++++++++++++++++++++++++++++++- source/lib-intro.tex | 10 - source/modules.tex | 2 +- source/preprocessor.tex | 2009 ------------------------------------- source/std.tex | 1 - source/xrefdelta.tex | 1 + 6 files changed, 2061 insertions(+), 2069 deletions(-) delete mode 100644 source/preprocessor.tex diff --git a/source/lex.tex b/source/lex.tex index 339ef0e611..db46cd0ffe 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -1430,65 +1430,2044 @@ \end{note} \pnum -\indextext{\idxcode{import}}% -\indextext{\idxcode{final}}% -\indextext{\idxcode{module}}% -\indextext{\idxcode{override}}% -The identifiers in \tref{lex.name.special} have a special meaning when -appearing in a certain context. When referred to in the grammar, these identifiers -are used explicitly rather than using the \grammarterm{identifier} grammar production. -Unless otherwise specified, any ambiguity as to whether a given -\grammarterm{identifier} has a special meaning is resolved to interpret the -token as a regular \grammarterm{identifier}. +\indextext{\idxcode{_}|see{character, underscore}}% +\indextext{character!underscore!in identifier}% +\indextext{reserved identifier}% +In addition, some identifiers +appearing as a \grammarterm{token} or \grammarterm{preprocessing-token} +are reserved for use by \Cpp{} +implementations and shall +not be used otherwise; no diagnostic is required. +\begin{itemize} +\item +Each identifier that contains a double underscore +\tcode{\unun} +\indextext{character!underscore}% +or begins with an underscore followed by +an uppercase letter, +other than those specified in this document +(for example, \xname{cplusplus}\iref{cpp.predefined}), +\indextext{uppercase}% +is reserved to the implementation for any use. +\item +Each identifier that begins with an underscore is +\indextext{character!underscore}% +reserved to the implementation for use as a name in the global namespace.% +\indextext{namespace!global} +\end{itemize}% +\indextext{identifier|)} + + +\rSec1[cpp]{Preprocessing directives}% +\indextext{preprocessing directive|(} + +\indextext{compiler control line|see{preprocessing directive}}% +\indextext{control line|see{preprocessing directive}}% +\indextext{directive, preprocessing|see{preprocessing directive}} + +\gramSec[gram.cpp]{Preprocessing directives} + +\rSec2[cpp.pre]{Preamble} + +\begin{bnf} +\nontermdef{preprocessing-file}\br + \opt{group}\br + module-file +\end{bnf} + +\begin{bnf} +\nontermdef{module-file}\br + \opt{pp-global-module-fragment} pp-module \opt{group} \opt{pp-private-module-fragment} +\end{bnf} + +\begin{bnf} +\nontermdef{pp-global-module-fragment}\br + \keyword{module} \terminal{;} new-line \opt{group} +\end{bnf} + +\begin{bnf} +\nontermdef{pp-private-module-fragment}\br + \keyword{module} \terminal{:} \keyword{private} \terminal{;} new-line \opt{group} +\end{bnf} + +\begin{bnf} +\nontermdef{group}\br + group-part\br + group group-part +\end{bnf} + +\begin{bnf} +\nontermdef{group-part}\br + control-line\br + if-section\br + text-line\br + \terminal{\#} conditionally-supported-directive +\end{bnf} + +\begin{bnf}\obeyspaces +\nontermdef{control-line}\br + \terminal{\# include} pp-tokens new-line\br + pp-import\br + \terminal{\# define } identifier replacement-list new-line\br + \terminal{\# define } identifier lparen \opt{identifier-list} \terminal{)} replacement-list new-line\br + \terminal{\# define } identifier lparen \terminal{... )} replacement-list new-line\br + \terminal{\# define } identifier lparen identifier-list \terminal{, ... )} replacement-list new-line\br + \terminal{\# undef } identifier new-line\br + \terminal{\# line } pp-tokens new-line\br + \terminal{\# error } \opt{pp-tokens} new-line\br + \terminal{\# warning} \opt{pp-tokens} new-line\br + \terminal{\# pragma } \opt{pp-tokens} new-line\br + \terminal{\# }new-line +\end{bnf} + +\begin{bnf} +\nontermdef{if-section}\br + if-group \opt{elif-groups} \opt{else-group} endif-line +\end{bnf} + +\begin{bnf}\obeyspaces +\nontermdef{if-group}\br + \terminal{\# if } constant-expression new-line \opt{group}\br + \terminal{\# ifdef } identifier new-line \opt{group}\br + \terminal{\# ifndef } identifier new-line \opt{group} +\end{bnf} + +\begin{bnf} +\nontermdef{elif-groups}\br + elif-group\br + elif-groups elif-group +\end{bnf} + +\begin{bnf}\obeyspaces +\nontermdef{elif-group}\br + \terminal{\# elif } constant-expression new-line \opt{group}\br + \terminal{\# elifdef } identifier new-line \opt{group}\br + \terminal{\# elifndef} identifier new-line \opt{group} +\end{bnf} + +\begin{bnf}\obeyspaces +\nontermdef{else-group}\br + \terminal{\# else } new-line \opt{group} +\end{bnf} + +\begin{bnf}\obeyspaces +\nontermdef{endif-line}\br + \terminal{\# endif } new-line +\end{bnf} + +\begin{bnf} +\nontermdef{text-line}\br + \opt{pp-tokens} new-line +\end{bnf} + +\begin{bnf} +\nontermdef{conditionally-supported-directive}\br + pp-tokens new-line +\end{bnf} + +\begin{bnf} +\nontermdef{lparen}\br + \descr{a \terminal{(} character not immediately preceded by whitespace} +\end{bnf} + +\begin{bnf} +\nontermdef{identifier-list}\br + identifier\br + identifier-list \terminal{,} identifier +\end{bnf} + +\begin{bnf} +\nontermdef{replacement-list}\br + \opt{pp-tokens} +\end{bnf} + +\begin{bnf} +\nontermdef{pp-tokens}\br + preprocessing-token\br + pp-tokens preprocessing-token +\end{bnf} + +\begin{bnf} +\nontermdef{new-line}\br + \descr{the new-line character} +\end{bnf} + +\pnum +A \defn{preprocessing directive} consists of a sequence of preprocessing tokens +that satisfies the following constraints: +At the start of translation phase 4, +the first token in the sequence, +referred to as a \defnadj{directive-introducing}{token}, +begins with the first character in the source file +(optionally after whitespace containing no new-line characters) or +follows whitespace containing at least one new-line character, +and is + +\begin{itemize} +\item +a \tcode{\#} preprocessing token, or + +\item +an \keyword{import} preprocessing token +immediately followed on the same logical source line by a +\grammarterm{header-name}, +\tcode{<}, +\grammarterm{identifier}, +\grammarterm{string-literal}, or +\tcode{:} +preprocessing token, or + +\item +a \keyword{module} preprocessing token +immediately followed on the same logical source line by an +\grammarterm{identifier}, +\tcode{:}, or +\tcode{;} +preprocessing token, or + +\item +an \keyword{export} preprocessing token +immediately followed on the same logical source line by +one of the two preceding forms. +\end{itemize} + +The last token in the sequence is the first token within the sequence that +is immediately followed by whitespace containing a new-line character. +\begin{footnote} +Thus, +preprocessing directives are commonly called ``lines''. +These ``lines'' have no other syntactic significance, +as all whitespace is equivalent except in certain situations +during preprocessing (see the +\tcode{\#} +character string literal creation operator in~\ref{cpp.stringize}, for example). +\end{footnote} +\begin{note} +A new-line character ends the preprocessing directive even if it occurs +within what would otherwise be an invocation of a function-like macro. +\end{note} + +\begin{example} +\begin{codeblock} +# // preprocessing directive +module ; // preprocessing directive +export module leftpad; // preprocessing directive +import ; // preprocessing directive +export import "squee"; // preprocessing directive +import rightpad; // preprocessing directive +import :part; // preprocessing directive + +module // not a preprocessing directive +; // not a preprocessing directive + +export // not a preprocessing directive +import // not a preprocessing directive +foo; // not a preprocessing directive + +export // not a preprocessing directive +import foo; // preprocessing directive (ill-formed at phase 7) + +import :: // not a preprocessing directive +import -> // not a preprocessing directive +\end{codeblock} +\end{example} + +\pnum +A sequence of preprocessing tokens is only a \grammarterm{text-line} +if it does not begin with a directive-introducing token. +A sequence of preprocessing tokens is only a \grammarterm{conditionally-supported-directive} +if it does not begin with any of the directive names +appearing after a \tcode{\#} in the syntax. +A \grammarterm{conditionally-supported-directive} is +conditionally-supported with +\impldef{additional supported forms of preprocessing directive} +semantics. + +\pnum +At the start of phase 4 of translation, +the \grammarterm{group} of a \grammarterm{pp-global-module-fragment} shall +contain neither a \grammarterm{text-line} nor a \grammarterm{pp-import}. + +\pnum +When in a group that is skipped\iref{cpp.cond}, the directive +syntax is relaxed to allow any sequence of preprocessing tokens to occur between +the directive name and the following new-line character. + +\pnum +The only whitespace characters that shall appear +between preprocessing tokens +within a preprocessing directive +(from just after the directive-introducing token +through just before the terminating new-line character) +are space and horizontal-tab +(including spaces that have replaced comments +or possibly other whitespace characters +in translation phase 3). + +\pnum +The implementation can +process and skip sections of source files conditionally, +include other source files, +import macros from header units, +and replace macros. +These capabilities are called +\defn{preprocessing}, +because conceptually they occur +before translation of the resulting translation unit. + +\pnum +The preprocessing tokens within a preprocessing directive +are not subject to macro expansion unless otherwise stated. + +\begin{example} +In: +\begin{codeblock} +#define EMPTY +EMPTY # include +\end{codeblock} +the sequence of preprocessing tokens on the second line is \textit{not} +a preprocessing directive, because it does not begin with a \tcode{\#} at the start of +translation phase 4, even though it will do so after the macro \tcode{EMPTY} +has been replaced. +\end{example} + +\rSec2[cpp.module]{Module directive} +\indextext{preprocessing directive!module}% + +\begin{bnf} +\nontermdef{pp-module}\br + \opt{\keyword{export}} \keyword{module} \opt{pp-tokens} \terminal{;} new-line +\end{bnf} + +\pnum +A \grammarterm{pp-module} shall not +appear in a context where \tcode{module} +or (if it is the first token of the \grammarterm{pp-module}) \tcode{export} +is an identifier defined as an object-like macro. + +\pnum +The \grammarterm{pp-tokens}, if any, of a \grammarterm{pp-module} +shall be of the form: +\begin{ncsimplebnf} +pp-module-name \opt{pp-module-partition} \opt{pp-tokens} +\end{ncsimplebnf} +where the \grammarterm{pp-tokens} (if any) shall not begin with +a \tcode{(} preprocessing token and +the grammar non-terminals are defined as: +\begin{ncbnf} +\nontermdef{pp-module-name}\br + \opt{pp-module-name-qualifier} identifier +\end{ncbnf} +\begin{ncbnf} +\nontermdef{pp-module-partition}\br + \terminal{:} \opt{pp-module-name-qualifier} identifier +\end{ncbnf} +\begin{ncbnf} +\nontermdef{pp-module-name-qualifier}\br + identifier \terminal{.}\br + pp-module-name-qualifier identifier \terminal{.} +\end{ncbnf} +No \grammarterm{identifier} in +the \grammarterm{pp-module-name} or \grammarterm{pp-module-partition} +shall currently be defined as an object-like macro. + +\pnum +Any preprocessing tokens after the \tcode{module} preprocessing token +in the \tcode{module} directive are processed just as in normal text. +\begin{note} +Each identifier currently defined as a macro name +is replaced by its replacement list of preprocessing tokens. +\end{note} + +\pnum +The \tcode{module} and \tcode{export} (if it exists) preprocessing tokens +are replaced by the \grammarterm{module-keyword} and +\grammarterm{export-keyword} preprocessing tokens respectively. +\begin{note} +This makes the line no longer a directive +so it is not removed at the end of phase 4. +\end{note} + +\rSec2[cpp.import]{Header unit importation} +\indextext{header unit!preprocessing}% +\indextext{preprocessing directive!import}% +\indextext{macro!import|(}% + +\begin{bnf} +\nontermdef{pp-import}\br + \opt{\keyword{export}} \keyword{import} header-name \opt{pp-tokens} \terminal{;} new-line\br + \opt{\keyword{export}} \keyword{import} header-name-tokens \opt{pp-tokens} \terminal{;} new-line\br + \opt{\keyword{export}} \keyword{import} pp-tokens \terminal{;} new-line +\end{bnf} + +\pnum +A \grammarterm{pp-import} shall not +appear in a context where \tcode{import} +or (if it is the first token of the \grammarterm{pp-import}) \tcode{export} +is an identifier defined as an object-like macro. + +\pnum +The preprocessing tokens after the \tcode{import} preprocessing token +in the \tcode{import} \grammarterm{control-line} +are processed just as in normal text +(i.e., each identifier currently defined as a macro name +is replaced by its replacement list of preprocessing tokens). +\begin{note} +An \tcode{import} directive +matching the first two forms of a \grammarterm{pp-import} +instructs the preprocessor to import macros +from the header unit\iref{module.import} +denoted by the \grammarterm{header-name}, +as described below. +\end{note} +\indextext{point of!macro import|see{macro, point of import}}% +The \defnx{point of macro import}{macro!point of import} for the +first two forms of \grammarterm{pp-import} is +immediately after the \grammarterm{new-line} terminating +the \grammarterm{pp-import}. +The last form of \grammarterm{pp-import} is only considered +if the first two forms did not match, and +does not have a point of macro import. + +\pnum +If a \grammarterm{pp-import} is produced by source file inclusion +(including by the rewrite produced +when a \tcode{\#include} directive names an importable header) +while processing the \grammarterm{group} of a \grammarterm{module-file}, +the program is ill-formed. + +\pnum +In all three forms of \grammarterm{pp-import}, +the \tcode{import} and \tcode{export} (if it exists) preprocessing tokens +are replaced by the \grammarterm{import-keyword} and +\grammarterm{export-keyword} preprocessing tokens respectively. +\begin{note} +This makes the line no longer a directive +so it is not removed at the end of phase 4. +\end{note} +Additionally, in the second form of \grammarterm{pp-import}, +a \grammarterm{header-name} token is formed as if +the \grammarterm{header-name-tokens} +were the \grammarterm{pp-tokens} of a \tcode{\#include} directive. +The \grammarterm{header-name-tokens} are replaced by +the \grammarterm{header-name} token. +\begin{note} +This ensures that imports are treated consistently by +the preprocessor and later phases of translation. +\end{note} + +\pnum +Each \tcode{\#define} directive encountered when preprocessing +each translation unit in a program results in a distinct +\defnx{macro definition}{macro!definition}. +\begin{note} +A predefined macro name\iref{cpp.predefined} +is not introduced by a \tcode{\#define} directive. +Implementations providing mechanisms to predefine additional macros +are encouraged to not treat them +as being introduced by a \tcode{\#define} directive. +\end{note} +Each macro definition has at most one point of definition in +each translation unit and at most one point of undefinition, as follows: +\begin{itemize} +\item +\indextext{point of!macro definition|see{macro, point of definition}}% +The \defnx{point of definition}{macro!point of definition} +of a macro definition within a translation unit $T$ is +\begin{itemize} +\item +if the \tcode{\#define} directive of the macro definition occurs within $T$, +the point at which that directive occurs, or otherwise, +\item +if the macro name is not lexically identical to a keyword\iref{lex.key} +or to the \grammarterm{identifier}{s} \tcode{module} or \tcode{import}, +the first point of macro import in $T$ of a header unit +containing a point of definition for the macro definition, if any. +\end{itemize} +In the latter case, the macro is said +to be \defnx{imported}{macro!import} from the header unit. + +\item +\indextext{point of!macro undefinition|see{macro, point of undefinition}}% +The \defnx{point of undefinition}{macro!point of undefinition} +of a macro definition within a translation unit +is the first point at which a \tcode{\#undef} directive naming the macro occurs +after its point of definition, or the first point +of macro import of a header unit containing a point of undefinition for the +macro definition, whichever (if any) occurs first. +\end{itemize} + +\pnum +\indextext{active macro directive|see{macro, active}}% +A macro directive is \defnx{active}{macro!active} at a source location +if it has a point of definition in that translation unit preceding the location, +and does not have a point of undefinition in that translation unit preceding +the location. + +\pnum +If a macro would be replaced or redefined, and multiple macro definitions +are active for that macro name, the active macro definitions shall all be +valid redefinitions of the same macro\iref{cpp.replace}. +\begin{note} +The relative order of \grammarterm{pp-import}{s} has no bearing on whether a +particular macro definition is active. +\end{note} + +\pnum +\begin{example} +\begin{codeblocktu}{Importable header \tcode{"a.h"}} +#define X 123 // \#1 +#define Y 45 // \#2 +#define Z a // \#3 +#undef X // point of undefinition of \#1 in \tcode{"a.h"} +\end{codeblocktu} + +\begin{codeblocktu}{Importable header \tcode{"b.h"}} +import "a.h"; // point of definition of \#1, \#2, and \#3, point of undefinition of \#1 in \tcode{"b.h"} +#define X 456 // OK, \#1 is not active +#define Y 6 // error: \#2 is active +\end{codeblocktu} + +\begin{codeblocktu}{Importable header \tcode{"c.h"}} +#define Y 45 // \#4 +#define Z c // \#5 +\end{codeblocktu} + +\begin{codeblocktu}{Importable header \tcode{"d.h"}} +import "c.h"; // point of definition of \#4 and \#5 in \tcode{"d.h"} +\end{codeblocktu} + +\begin{codeblocktu}{Importable header \tcode{"e.h"}} +import "a.h"; // point of definition of \#1, \#2, and \#3, point of undefinition of \#1 in \tcode{"e.h"} +import "d.h"; // point of definition of \#4 and \#5 in \tcode{"e.h"} +int a = Y; // OK, active macro definitions \#2 and \#4 are valid redefinitions +int c = Z; // error: active macro definitions \#3 and \#5 are not valid redefinitions of \tcode{Z} +\end{codeblocktu} + +\begin{codeblocktu}{Module unit \tcode{f}} +export module f; +export import "a.h"; + +int a = Y; // OK +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \tcode{\#1}} +import f; +int x = Y; // error: \tcode{Y} is neither a defined macro nor a declared name +\end{codeblocktu} +\end{example} +\indextext{macro!import|)} + +\rSec2[cpp.null]{Null directive}% +\indextext{preprocessing directive!null} + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\#} new-line +\end{ncsimplebnf} +has no effect. + +\rSec2[cpp.error]{Diagnostic directives}% +\indextext{preprocessing directive!error}% +\indextext{preprocessing directive!diagnostic}% +\indextext{preprocessing directive!warning}% +\indextext{\idxcode{\#error}|see{preprocessing directive, error}} + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# error} \opt{pp-tokens} new-line +\end{ncsimplebnf} +renders the program ill-formed. +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# warning} \opt{pp-tokens} new-line +\end{ncsimplebnf} +requires the implementation to produce at least one diagnostic message +for the preprocessing translation unit\iref{intro.compliance.general}. +\recommended +Any diagnostic message caused by either of these directives +should include the specified sequence of preprocessing tokens. + +\rSec2[cpp.line]{Line control}% +\indextext{preprocessing directive!line control}% +\indextext{\idxcode{\#line}|see{preprocessing directive, line control}} + +\pnum +The \grammarterm{string-literal} of a +\tcode{\#line} +directive, if present, +shall be a character string literal. + +\pnum +The +\defn{line number} +of the current source line is one greater than +the number of new-line characters read or introduced +in translation phase 1\iref{lex.phases} +while processing the source file to the current token. + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# line} digit-sequence new-line +\end{ncsimplebnf} +causes the implementation to behave as if +the following sequence of source lines begins with a +source line that has a line number as specified +by the digit sequence (interpreted as a decimal integer). +If the digit sequence specifies zero +or a number greater than 2147483647, +the behavior is undefined. + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# line} digit-sequence \terminal{"} \opt{s-char-sequence} \terminal{"} new-line +\end{ncsimplebnf} +sets the presumed line number similarly and changes the +presumed name of the source file to be the contents +of the character string literal. + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# line} pp-tokens new-line +\end{ncsimplebnf} +(that does not match one of the two previous forms) +is permitted. +The preprocessing tokens after +\tcode{line} +on the directive are processed just as in normal text +(each identifier currently defined as a macro name is replaced by its +replacement list of preprocessing tokens). +If the directive resulting after all replacements does not match +one of the two previous forms, the behavior is undefined; +otherwise, the result is processed as appropriate. + +\rSec2[cpp.pragma]{Pragma directive}% +\indextext{preprocessing directive!pragma}% +\indextext{\idxcode{\#pragma}|see{preprocessing directive, pragma}} + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# pragma} \opt{pp-tokens} new-line +\end{ncsimplebnf} +causes the implementation to behave +in an \impldef{\tcode{\#pragma}} manner. +The behavior may cause translation to fail or cause the translator or +the resulting program to behave in a non-conforming manner. +Any pragma that is not recognized by the implementation is ignored. + +\rSec2[cpp.pragma.op]{Pragma operator}% +\indextext{macro!pragma operator}% +\indextext{operator!pragma|see{macro, pragma operator}} + +\pnum +A unary operator expression of the form: +\begin{ncbnf} +\terminal{_Pragma} \terminal{(} string-literal \terminal{)} +\end{ncbnf} +is processed as follows: The \grammarterm{string-literal} is \defnx{destringized}{destringization} +by deleting the \tcode{L} prefix, if present, deleting the leading and trailing +double-quotes, replacing each escape sequence \tcode{\textbackslash"} by a double-quote, and +replacing each escape sequence \tcode{\textbackslash\textbackslash} by a single +backslash. The resulting sequence of characters is processed through translation phase 3 +to produce preprocessing tokens that are executed as if they were the +\grammarterm{pp-tokens} in a pragma directive. The original four preprocessing +tokens in the unary operator expression are removed. + +\pnum +\begin{example} +\begin{codeblock} +#pragma listing on "..\listing.dir" +\end{codeblock} +can also be expressed as: +\begin{codeblock} +_Pragma ( "listing on \"..\\listing.dir\"" ) +\end{codeblock} +The latter form is processed in the same way whether it appears literally +as shown, or results from macro replacement, as in: +\begin{codeblock} +#define LISTING(x) PRAGMA(listing on #x) +#define PRAGMA(x) _Pragma(#x) + +LISTING( ..\listing.dir ) +\end{codeblock} +\end{example} +\indextext{preprocessing directive|)} + +\rSec2[cpp.replace]{Macro replacement}% + +\rSec3[cpp.replace.general]{General}% +\indextext{macro!replacement|(}% +\indextext{replacement!macro|see{macro, replacement}}% +\indextext{preprocessing directive!macro replacement|see{macro, replacement}} + +\pnum +\indextext{macro!replacement list}% +Two replacement lists are identical if and only if +the preprocessing tokens in both have +the same number, ordering, spelling, and whitespace separation, +where all whitespace separations are considered identical. + +\pnum +An identifier currently defined as an +\indextext{macro!object-like}% +object-like macro (see below) may be redefined by another +\tcode{\#define} +preprocessing directive provided that the second definition is an +object-like macro definition and the two replacement lists +are identical, otherwise the program is ill-formed. +Likewise, an identifier currently defined as a +\indextext{macro!function-like}% +function-like macro (see below) may be redefined by another +\tcode{\#define} +preprocessing directive provided that the second definition is a +function-like macro definition that has the same number and spelling +of parameters, +and the two replacement lists are identical, +otherwise the program is ill-formed. + +\pnum +\begin{example} +The following sequence is valid: +\begin{codeblock} +#define OBJ_LIKE (1-1) +#define OBJ_LIKE @\tcode{/* whitespace */ (1-1) /* other */}@ +#define FUNC_LIKE(a) ( a ) +#define FUNC_LIKE( a )( @\tcode{/* note the whitespace */ \textbackslash}@ + a @\tcode{/* other stuff on this line}@ + @\tcode{*/}@ ) +\end{codeblock} +But the following redefinitions are invalid: +\begin{codeblock} +#define OBJ_LIKE (0) // different token sequence +#define OBJ_LIKE (1 - 1) // different whitespace +#define FUNC_LIKE(b) ( a ) // different parameter usage +#define FUNC_LIKE(b) ( b ) // different parameter spelling +\end{codeblock} +\end{example} + +\pnum +\indextext{macro!replacement list}% +There shall be whitespace between the identifier and the replacement list +in the definition of an object-like macro. + +\pnum +If the \grammarterm{identifier-list} in the macro definition does not end with +an ellipsis, the number of arguments (including those arguments consisting +of no preprocessing tokens) +in an invocation of a function-like macro shall +equal the number of parameters in the macro definition. +Otherwise, there shall be at least as many arguments in the invocation as there are +parameters in the macro definition (excluding the \tcode{...}). There +shall exist a +\tcode{)} +preprocessing token that terminates the invocation. + +\pnum +\indextext{__va_args__@\mname{VA_ARGS}}% +\indextext{__va_opt__@\mname{VA_OPT}}% +The identifiers \mname{VA_ARGS} and \mname{VA_OPT} +shall occur only in the \grammarterm{replacement-list} +of a function-like macro that uses the ellipsis notation in the parameters. + +\pnum +A parameter identifier in a function-like macro +shall be uniquely declared within its scope. + +\pnum +The identifier immediately following the +\tcode{define} +is called the +\indextext{name!macro|see{macro, name}}% +\defnx{macro name}{macro!name}. +There is one name space for macro names. +Any whitespace characters preceding or following the +replacement list of preprocessing tokens are not considered +part of the replacement list for either form of macro. + +\pnum +If a +\indextext{\#\#0 operator@\tcode{\#} operator} +\tcode{\#} +preprocessing token, +followed by an identifier, +occurs lexically +at the point at which a preprocessing directive can begin, +the identifier is not subject to macro replacement. + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# define} identifier replacement-list new-line +\indextext{\idxcode{\#define}}% +\end{ncsimplebnf} +defines an +\defnadj{object-like}{macro} that +causes each subsequent instance of the macro name +\begin{footnote} +Since, by macro-replacement time, +all \grammarterm{character-literal}s and \grammarterm{string-literal}s are preprocessing tokens, +not sequences possibly containing identifier-like subsequences +(see \ref{lex.phases}, translation phases), +they are never scanned for macro names or parameters. +\end{footnote} +to be replaced by the replacement list of preprocessing tokens +that constitute the remainder of the directive. +\begin{footnote} +An alternative token\iref{lex.operators} is not an identifier, +even when its spelling consists entirely of letters and underscores. +Therefore it is not possible to define a macro +whose name is the same as that of an alternative token. +\end{footnote} +The replacement list is then rescanned for more macro names as +specified below. + +\pnum +\begin{example} +The simplest use of this facility is to define a ``manifest constant'', +as in +\begin{codeblock} +#define TABSIZE 100 +int table[TABSIZE]; +\end{codeblock} +\end{example} + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# define} identifier lparen \opt{identifier-list} \terminal{)} replacement-list new-line\br +\terminal{\# define} identifier lparen \terminal{...} \terminal{)} replacement-list new-line\br +\terminal{\# define} identifier lparen identifier-list \terminal{, ...} \terminal{)} replacement-list new-line +\end{ncsimplebnf} +defines a \defnadj{function-like}{macro} +with parameters, whose use is +similar syntactically to a function call. +The parameters +\indextext{parameter!macro}% +are specified by the optional list of identifiers. +Each subsequent instance of the function-like macro name followed by a +\tcode{(} +as the next preprocessing token +introduces the sequence of preprocessing tokens that is replaced +by the replacement list in the definition +(an invocation of the macro). +\indextext{invocation!macro}% +The replaced sequence of preprocessing tokens is terminated by the matching +\tcode{)} +preprocessing token, skipping intervening matched pairs of left and +right parenthesis preprocessing tokens. +Within the sequence of preprocessing tokens making up an invocation +of a function-like macro, +new-line is considered a normal whitespace character. + +\pnum +\indextext{macro!function-like!arguments}% +The sequence of preprocessing tokens +bounded by the outside-most matching parentheses +forms the list of arguments for the function-like macro. +The individual arguments within the list +are separated by comma preprocessing tokens, +but comma preprocessing tokens between matching +inner parentheses do not separate arguments. +If there are sequences of preprocessing tokens within the list of +arguments that would otherwise act as preprocessing directives, +\begin{footnote} +A \grammarterm{conditionally-supported-directive} is a preprocessing directive regardless of whether the implementation supports it. +\end{footnote} +the behavior is undefined. + +\pnum +\begin{example} +The following defines a function-like +macro whose value is the maximum of its arguments. +It has the disadvantages of evaluating one or the other of its arguments +a second time +(including +\indextext{side effects}% +side effects) +and generating more code than a function if invoked several times. +It also cannot have its address taken, +as it has none. + +\begin{codeblock} +#define max(a, b) ((a) > (b) ? (a) : (b)) +\end{codeblock} + +The parentheses ensure that the arguments and +the resulting expression are bound properly. +\end{example} + +\pnum +\indextext{macro!function-like!arguments}% +If there is a \tcode{...} immediately preceding the \tcode{)} in the +function-like macro +definition, then the trailing arguments (if any), including any separating comma preprocessing +tokens, are merged to form a single item: the \defn{variable arguments}. The number of +arguments so combined is such that, following merger, the number of arguments is +either equal to or +one more than the number of parameters in the macro definition (excluding the +\tcode{...}). + +\rSec3[cpp.subst]{Argument substitution}% +\indextext{macro!argument substitution}% +\indextext{argument substitution|see{macro, argument substitution}}% + +\indextext{__va_opt__@\mname{VA_OPT}}% +\begin{bnf} +\nontermdef{va-opt-replacement}\br + \terminal{\mname{VA_OPT} (} \opt{pp-tokens} \terminal{)} +\end{bnf} + +\pnum +After the arguments for the invocation of a function-like macro have +been identified, argument substitution takes place. +For each parameter in the replacement list that is neither +preceded by a \tcode{\#} or \tcode{\#\#} preprocessing token nor +followed by a \tcode{\#\#} preprocessing token, the preprocessing tokens +naming the parameter are replaced by a token sequence determined as follows: +\begin{itemize} +\item + If the parameter is of the form \grammarterm{va-opt-replacement}, + the replacement preprocessing tokens are the + preprocessing token sequence for the corresponding argument, + as specified below. +\item + Otherwise, the replacement preprocessing tokens are the + preprocessing tokens of corresponding argument after all + macros contained therein have been expanded. The argument's + preprocessing tokens are completely macro replaced before + being substituted as if they formed the rest of the preprocessing + file with no other preprocessing tokens being available. +\end{itemize} +\begin{example} +\begin{codeblock} +#define LPAREN() ( +#define G(Q) 42 +#define F(R, X, ...) __VA_OPT__(G R X) ) +int x = F(LPAREN(), 0, <:-); // replaced by \tcode{int x = 42;} +\end{codeblock} +\end{example} + +\pnum +\indextext{__va_args__@\mname{VA_ARGS}}% +An identifier \mname{VA_ARGS} that occurs in the replacement list +shall be treated as if it were a parameter, and the variable arguments shall form +the preprocessing tokens used to replace it. + +\pnum +\begin{example} +\begin{codeblock} +#define debug(...) fprintf(stderr, @\mname{VA_ARGS}@) +#define showlist(...) puts(#@\mname{VA_ARGS}@) +#define report(test, ...) ((test) ? puts(#test) : printf(@\mname{VA_ARGS}@)) +debug("Flag"); +debug("X = %d\n", x); +showlist(The first, second, and third items.); +report(x>y, "x is %d but y is %d", x, y); +\end{codeblock} +results in +\begin{codeblock} +fprintf(stderr, "Flag"); +fprintf(stderr, "X = %d\n", x); +puts("The first, second, and third items."); +((x>y) ? puts("x>y") : printf("x is %d but y is %d", x, y)); +\end{codeblock} +\end{example} + +\pnum +\indextext{__va_opt__@\mname{VA_OPT}}% +The identifier \mname{VA_OPT} +shall always occur as part of the preprocessing token sequence +\grammarterm{va-opt-replacement}; +its closing \tcode{)} is determined by skipping +intervening pairs of matching left and right parentheses +in its \grammarterm{pp-tokens}. +The \grammarterm{pp-tokens} of a \grammarterm{va-opt-replacement} +shall not contain \mname{VA_OPT}. +If the \grammarterm{pp-tokens} would be ill-formed +as the replacement list of the current function-like macro, +the program is ill-formed. +A \grammarterm{va-opt-replacement} is treated as if it were a parameter, +and the preprocessing token sequence for the corresponding +argument is defined as follows. +If the substitution of \mname{VA_ARGS} as neither an operand +of \tcode{\#} nor \tcode{\#\#} consists of no preprocessing tokens, +the argument consists of +a single placemarker preprocessing token\iref{cpp.concat,cpp.rescan}. +Otherwise, the argument consists of +the results of the expansion of the contained \grammarterm{pp-tokens} +as the replacement list of the current function-like macro +before removal of placemarker tokens, rescanning, and further replacement. +\begin{note} +The placemarker tokens are removed before stringization\iref{cpp.stringize}, +and can be removed by rescanning and further replacement\iref{cpp.rescan}. +\end{note} +\begin{example} +\begin{codeblock} +#define F(...) f(0 __VA_OPT__(,) __VA_ARGS__) +#define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__) +#define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ }) +#define EMP + +F(a, b, c) // replaced by \tcode{f(0, a, b, c)} +F() // replaced by \tcode{f(0)} +F(EMP) // replaced by \tcode{f(0)} + +G(a, b, c) // replaced by \tcode{f(0, a, b, c)} +G(a, ) // replaced by \tcode{f(0, a)} +G(a) // replaced by \tcode{f(0, a)} + +SDEF(foo); // replaced by \tcode{S foo;} +SDEF(bar, 1, 2); // replaced by \tcode{S bar = \{ 1, 2 \};} + +#define H1(X, ...) X __VA_OPT__(##) __VA_ARGS__ // error: \tcode{\#\#} may not appear at + // the beginning of a replacement list\iref{cpp.concat} + +#define H2(X, Y, ...) __VA_OPT__(X ## Y,) __VA_ARGS__ +H2(a, b, c, d) // replaced by \tcode{ab, c, d} + +#define H3(X, ...) #__VA_OPT__(X##X X##X) +H3(, 0) // replaced by \tcode{""} + +#define H4(X, ...) __VA_OPT__(a X ## X) ## b +H4(, 1) // replaced by \tcode{a b} + +#define H5A(...) __VA_OPT__()@\tcode{/**/}@__VA_OPT__() +#define H5B(X) a ## X ## b +#define H5C(X) H5B(X) +H5C(H5A()) // replaced by \tcode{ab} +\end{codeblock} +\end{example} + +\rSec3[cpp.stringize]{The \tcode{\#} operator}% +\indextext{\#\#0 operator@\tcode{\#} operator}% +\indextext{stringize|see{\tcode{\#} operator}} + +\pnum +Each +\tcode{\#} +preprocessing token in the replacement list for a function-like +macro shall be followed by a parameter as the next preprocessing +token in the replacement list. + +\pnum +A \defn{character string literal} is a \grammarterm{string-literal} with no prefix. +If, in the replacement list, a parameter is immediately +preceded by a +\tcode{\#} +preprocessing token, +both are replaced by a single character string literal preprocessing token that +contains the spelling of the preprocessing token sequence for the +corresponding argument (excluding placemarker tokens). +Let the \defn{stringizing argument} be the preprocessing token sequence +for the corresponding argument with placemarker tokens removed. +Each occurrence of whitespace between the stringizing argument's preprocessing +tokens becomes a single space character in the character string literal. +Whitespace before the first preprocessing token and after the last +preprocessing token comprising the stringizing argument is deleted. +Otherwise, the original spelling of each preprocessing token in the +stringizing argument is retained in the character string literal, +except for special handling for producing the spelling of +\grammarterm{string-literal}s and \grammarterm{character-literal}s: +a +\tcode{\textbackslash} +character is inserted before each +\tcode{"} +and +\tcode{\textbackslash} +character of a \grammarterm{character-literal} or \grammarterm{string-literal} +(including the delimiting +\tcode{"} +characters). +If the replacement that results is not a valid character string literal, +the behavior is undefined. The character string literal corresponding to +an empty stringizing argument is \tcode{""}. +The order of evaluation of +\tcode{\#} +and +\tcode{\#\#} +operators is unspecified. + +\rSec3[cpp.concat]{The \tcode{\#\#} operator}% +\indextext{\#\#1 operator@\tcode{\#\#} operator}% +\indextext{concatenation!macro argument|see{\tcode{\#\#} operator}} + +\pnum +A +\tcode{\#\#} +preprocessing token shall not occur at the beginning or +at the end of a replacement list for either form +of macro definition. + +\pnum +If, in the replacement list of a function-like macro, a parameter is +immediately preceded or followed by a +\tcode{\#\#} +preprocessing token, the parameter is replaced by the +corresponding argument's preprocessing token sequence; however, if an argument consists of no preprocessing tokens, the parameter is +replaced by a placemarker preprocessing token instead. +\begin{footnote} +Placemarker preprocessing tokens do not appear in the syntax +because they are temporary entities that exist only within translation phase 4. +\end{footnote} + +\pnum +For both object-like and function-like macro invocations, before the +replacement list is reexamined for more macro names to replace, +each instance of a +\tcode{\#\#} +preprocessing token in the replacement list +(not from an argument) is deleted and the +preceding preprocessing token is concatenated +with the following preprocessing token. +Placemarker preprocessing tokens are handled specially: concatenation +of two placemarkers results in a single placemarker preprocessing token, and +concatenation of a placemarker with a non-placemarker preprocessing token results +in the non-placemarker preprocessing token. +\begin{note} +Concatenation can form +a \grammarterm{universal-character-name}\iref{lex.charset}. +\end{note} +If the result is not a valid preprocessing token, +the behavior is undefined. +The resulting token is available for further macro replacement. +The order of evaluation of +\tcode{\#\#} +operators is unspecified. + +\pnum +\begin{example} +The sequence +\begin{codeblock} +#define str(s) # s +#define xstr(s) str(s) +#define debug(s, t) printf("x" # s "= %d, x" # t "= %s", @\textbackslash@ + x ## s, x ## t) +#define INCFILE(n) vers ## n +#define glue(a, b) a ## b +#define xglue(a, b) glue(a, b) +#define HIGHLOW "hello" +#define LOW LOW ", world" + +debug(1, 2); +fputs(str(strncmp("abc@\textbackslash@0d", "abc", '@\textbackslash@4') // this goes away + == 0) str(: @\atsign\textbackslash@n), s); +#include xstr(INCFILE(2).h) +glue(HIGH, LOW); +xglue(HIGH, LOW) +\end{codeblock} +results in +\begin{codeblock} +printf("x" "1" "= %d, x" "2" "= %s", x1, x2); +fputs("strncmp(@\textbackslash@"abc@\textbackslash\textbackslash@0d@\textbackslash@", @\textbackslash@"abc@\textbackslash@", '@\textbackslash\textbackslash@4') == 0" ": @\atsign\textbackslash@n", s); +#include "vers2.h" @\textrm{(\textit{after macro replacement, before file access})}@ +"hello"; +"hello" ", world" +\end{codeblock} +or, after concatenation of the character string literals, +\begin{codeblock} +printf("x1= %d, x2= %s", x1, x2); +fputs("strncmp(@\textbackslash@"abc@\textbackslash\textbackslash@0d@\textbackslash@", @\textbackslash@"abc@\textbackslash@", '@\textbackslash\textbackslash@4') == 0: @\atsign\textbackslash@n", s); +#include "vers2.h" @\textrm{(\textit{after macro replacement, before file access})}@ +"hello"; +"hello, world" +\end{codeblock} + +Space around the \tcode{\#} and \tcode{\#\#} tokens in the macro definition +is optional. +\end{example} + +\pnum +\begin{example} +In the following fragment: -\begin{multicolfloattable}{Identifiers with special meaning}{lex.name.special} -{llll} -\keyword{final} \\ -\columnbreak -\keyword{import} \\ -\columnbreak -\keyword{module} \\ -\columnbreak -\keyword{override} \\ -\end{multicolfloattable} +\begin{codeblock} +#define hash_hash # ## # +#define mkstr(a) # a +#define in_between(a) mkstr(a) +#define join(c, d) in_between(c hash_hash d) +char p[] = join(x, y); // equivalent to \tcode{char p[] = "x \#\# y";} +\end{codeblock} + +The expansion produces, at various stages: + +\begin{codeblock} +join(x, y) +in_between(x hash_hash y) +in_between(x ## y) +mkstr(x ## y) +"x ## y" +\end{codeblock} + +In other words, expanding \tcode{hash_hash} produces a new token, +consisting of two adjacent sharp signs, but this new token is not the +\tcode{\#\#} operator. +\end{example} \pnum -\indextext{\idxcode{_}|see{character, underscore}}% -\indextext{character!underscore!in identifier}% -\indextext{reserved identifier}% -In addition, some identifiers -appearing as a \grammarterm{token} or \grammarterm{preprocessing-token} -are reserved for use by \Cpp{} -implementations and shall -not be used otherwise; no diagnostic is required. -\begin{itemize} +\begin{example} +To illustrate the rules for placemarker preprocessing tokens, the sequence +\begin{codeblock} +#define t(x,y,z) x ## y ## z +int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), + t(10,,), t(,11,), t(,,12), t(,,) }; +\end{codeblock} +results in +\begin{codeblock} +int j[] = { 123, 45, 67, 89, + 10, 11, 12, }; +\end{codeblock} +\end{example} + +\rSec3[cpp.rescan]{Rescanning and further replacement}% +\indextext{macro!rescanning and replacement}% +\indextext{rescanning and replacement|see{macro, rescanning and replacement}} + +\pnum +After all parameters in the replacement list have been substituted and \tcode{\#} and \tcode{\#\#} processing has taken +place, all placemarker preprocessing tokens are removed. Then +the resulting preprocessing token sequence is rescanned, along with all +subsequent preprocessing tokens of the source file, for more macro names +to replace. + +\pnum +\begin{example} +The sequence +\begin{codeblock} +#define x 3 +#define f(a) f(x * (a)) +#undef x +#define x 2 +#define g f +#define z z[0] +#define h g(~ +#define m(a) a(w) +#define w 0,1 +#define t(a) a +#define p() int +#define q(x) x +#define r(x,y) x ## y +#define str(x) # x + +f(y+1) + f(f(z)) % t(t(g)(0) + t)(1); +g(x+(3,4)-w) | h 5) & m + (f)^m(m); +p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) }; +char c[2][6] = { str(hello), str() }; +\end{codeblock} +results in +\begin{codeblock} +f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); +f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); +int i[] = { 1, 23, 4, 5, }; +char c[2][6] = { "hello", "" }; +\end{codeblock} +\end{example} + +\pnum +If the name of the macro being replaced is found during this scan of +the replacement list +(not including the rest of the source file's preprocessing tokens), +it is not replaced. +Furthermore, +if any nested replacements encounter the name of the macro being replaced, +it is not replaced. +These nonreplaced macro name preprocessing tokens are no longer available +for further replacement even if they are later (re)examined in contexts +in which that macro name preprocessing token would otherwise have been +replaced. + +\pnum +The resulting completely macro-replaced preprocessing token sequence +is not processed as a preprocessing directive even if it resembles one, +but all pragma unary operator expressions within it are then processed as +specified in~\ref{cpp.pragma.op} below. + +\rSec3[cpp.scope]{Scope of macro definitions}% +\indextext{macro!scope of definition}% +\indextext{scope!macro definition|see{macro, scope of definition}} + +\pnum +A macro definition lasts +(independent of block structure) +until a corresponding +\tcode{\#undef} +directive is encountered or +(if none is encountered) +until the end of the translation unit. +Macro definitions have no significance after translation phase 4. + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# undef} identifier new-line +\indextext{\idxcode{\#undef}}% +\end{ncsimplebnf} +causes the specified identifier no longer to be defined as a macro name. +It is ignored if the specified identifier is not currently defined as +a macro name. + +\indextext{macro!replacement|)} + +\rSec2[cpp.predefined]{Predefined macro names} +\indextext{macro!predefined}% +\indextext{name!predefined macro|see{macro, predefined}} + +\pnum +The following macro names shall be defined by the implementation: + +\begin{description} + \item -Each identifier that contains a double underscore -\tcode{\unun} -\indextext{character!underscore}% -or begins with an underscore followed by -an uppercase letter, -other than those specified in this document -(for example, \xname{cplusplus}\iref{cpp.predefined}), -\indextext{uppercase}% -is reserved to the implementation for any use. +\indextext{\idxxname{cplusplus}}% +\xname{cplusplus}\\ +The integer literal \tcode{\cppver}. +\begin{note} +Future revisions of this document will +replace the value of this macro with a greater value. +\end{note} + +\item The names listed in \tref{cpp.predefined.ft}.\\ +The macros defined in \tref{cpp.predefined.ft} shall be defined to +the corresponding integer literal. +\begin{note} +Future revisions of this document might replace +the values of these macros with greater values. +\end{note} + \item -Each identifier that begins with an underscore is -\indextext{character!underscore}% -reserved to the implementation for use as a name in the global namespace.% -\indextext{namespace!global} -\end{itemize}% -\indextext{identifier|)} +\indextext{__date__@\mname{DATE}}% +\mname{DATE}\\ +The date of translation of the source file: +a character string literal of the form +\tcode{"Mmm~dd~yyyy"}, +where the names of the months are the same as those generated +by the +\tcode{asctime} +function, +and the first character of +\tcode{dd} +is a space character if the value is less than 10. +If the date of translation is not available, +an \impldef{text of \mname{DATE} when date of translation is not available} valid date +shall be supplied. + +\item +\indextext{__file__@\mname{FILE}}% +\mname{FILE}\\ +The presumed name of the current source file (a character string +literal). +\begin{footnote} +The presumed source file name can be changed by the \tcode{\#line} directive. +\end{footnote} + +\item +\indextext{__line__@\mname{LINE}}% +\mname{LINE}\\ +The presumed line number (within the current source file) of the current source line +(an integer literal). +\begin{footnote} +The presumed line number can be changed by the \tcode{\#line} directive. +\end{footnote} + +\item +\indextext{__stdc_hosted__@\mname{STDC_HOSTED}}% +\indextext{implementation!hosted}% +\indextext{implementation!freestanding}% +\mname{STDC_HOSTED}\\ +The integer literal \tcode{1} +if the implementation is a hosted implementation or +the integer literal \tcode{0} +if it is a freestanding implementation\iref{intro.compliance}. + +\item +\indextext{__stdcpp_default_new_alignment__@\mname{STDCPP_DEFAULT_NEW_ALIGNMENT}}% +\mname{STDCPP_DEFAULT_NEW_ALIGNMENT}\\ +An integer literal of type \tcode{std::size_t} +whose value is the alignment guaranteed +by a call to \tcode{operator new(std::size_t)} +or \tcode{operator new[](std::size_t)}. +\begin{note} +Larger alignments will be passed to +\tcode{operator new(std::size_t, std::align_val_t)}, etc.\iref{expr.new}. +\end{note} + +\item +\indextext{__stdcpp_float16_t__@\mname{STDCPP_FLOAT16_T}}% +\mname{STDCPP_FLOAT16_T}\\ +Defined as the integer literal \tcode{1} +if and only if the implementation supports +the \IsoFloatUndated{} floating-point interchange format binary16 +as an extended floating-point type\iref{basic.extended.fp}. + +\item +\indextext{__stdcpp_float32_t__@\mname{STDCPP_FLOAT32_T}}% +\mname{STDCPP_FLOAT32_T}\\ +Defined as the integer literal \tcode{1} +if and only if the implementation supports +the \IsoFloatUndated{} floating-point interchange format binary32 +as an extended floating-point type. + +\item +\indextext{__stdcpp_float64_t__@\mname{STDCPP_FLOAT64_T}}% +\mname{STDCPP_FLOAT64_T}\\ +Defined as the integer literal \tcode{1} +if and only if the implementation supports +the \IsoFloatUndated{} floating-point interchange format binary64 +as an extended floating-point type. + +\item +\indextext{__stdcpp_float128_t__@\mname{STDCPP_FLOAT128_T}}% +\mname{STDCPP_FLOAT128_T}\\ +Defined as the integer literal \tcode{1} +if and only if the implementation supports +the \IsoFloatUndated{} floating-point interchange format binary128 +as an extended floating-point type. + +\item +\indextext{__stdcpp_bfloat16_t__@\mname{STDCPP_BFLOAT16_T}}% +\mname{STDCPP_BFLOAT16_T}\\ +Defined as the integer literal \tcode{1} +if and only if the implementation supports an extended floating-point type +with the properties of the \grammarterm{typedef-name} \tcode{std::bfloat16_t} +as described in \ref{basic.extended.fp}. + +\item +\indextext{__time__@\mname{TIME}}% +\mname{TIME}\\ +The time of translation of the source file: +a character string literal of the form +\tcode{"hh:mm:ss"} +as in the time generated by the +\tcode{asctime} +function. +If the time of translation is not available, +an \impldef{text of \mname{TIME} when time of translation is not available} valid time shall be supplied. +\end{description} + +\indextext{macro!feature-test}% +\indextext{feature-test macro|see{macro, feature-test}}% +\begin{LongTable}{Feature-test macros}{cpp.predefined.ft}{ll} +\\ \topline +\lhdr{Macro name} & \rhdr{Value} \\ \capsep +\endfirsthead +\continuedcaption \\ +\hline +\lhdr{Name} & \rhdr{Value} \\ \capsep +\endhead +\defnxname{cpp_aggregate_bases} & \tcode{201603L} \\ \rowsep +\defnxname{cpp_aggregate_nsdmi} & \tcode{201304L} \\ \rowsep +\defnxname{cpp_aggregate_paren_init} & \tcode{201902L} \\ \rowsep +\defnxname{cpp_alias_templates} & \tcode{200704L} \\ \rowsep +\defnxname{cpp_aligned_new} & \tcode{201606L} \\ \rowsep +\defnxname{cpp_attributes} & \tcode{200809L} \\ \rowsep +\defnxname{cpp_auto_cast} & \tcode{202110L} \\ \rowsep +\defnxname{cpp_binary_literals} & \tcode{201304L} \\ \rowsep +\defnxname{cpp_capture_star_this} & \tcode{201603L} \\ \rowsep +\defnxname{cpp_char8_t} & \tcode{202207L} \\ \rowsep +\defnxname{cpp_concepts} & \tcode{202002L} \\ \rowsep +\defnxname{cpp_conditional_explicit} & \tcode{201806L} \\ \rowsep +\defnxname{cpp_constexpr} & \tcode{202406L} \\ \rowsep +\defnxname{cpp_constexpr_dynamic_alloc} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_constexpr_in_decltype} & \tcode{201711L} \\ \rowsep +\defnxname{cpp_consteval} & \tcode{202211L} \\ \rowsep +\defnxname{cpp_constinit} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_decltype} & \tcode{200707L} \\ \rowsep +\defnxname{cpp_decltype_auto} & \tcode{201304L} \\ \rowsep +\defnxname{cpp_deduction_guides} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_delegating_constructors} & \tcode{200604L} \\ \rowsep +\defnxname{cpp_deleted_function} & \tcode{202403L} \\ \rowsep +\defnxname{cpp_designated_initializers} & \tcode{201707L} \\ \rowsep +\defnxname{cpp_enumerator_attributes} & \tcode{201411L} \\ \rowsep +\defnxname{cpp_explicit_this_parameter} & \tcode{202110L} \\ \rowsep +\defnxname{cpp_fold_expressions} & \tcode{201603L} \\ \rowsep +\defnxname{cpp_generic_lambdas} & \tcode{201707L} \\ \rowsep +\defnxname{cpp_guaranteed_copy_elision} & \tcode{201606L} \\ \rowsep +\defnxname{cpp_hex_float} & \tcode{201603L} \\ \rowsep +\defnxname{cpp_if_consteval} & \tcode{202106L} \\ \rowsep +\defnxname{cpp_if_constexpr} & \tcode{201606L} \\ \rowsep +\defnxname{cpp_impl_coroutine} & \tcode{201902L} \\ \rowsep +\defnxname{cpp_impl_destroying_delete} & \tcode{201806L} \\ \rowsep +\defnxname{cpp_impl_three_way_comparison} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_implicit_move} & \tcode{202207L} \\ \rowsep +\defnxname{cpp_inheriting_constructors} & \tcode{201511L} \\ \rowsep +\defnxname{cpp_init_captures} & \tcode{201803L} \\ \rowsep +\defnxname{cpp_initializer_lists} & \tcode{200806L} \\ \rowsep +\defnxname{cpp_inline_variables} & \tcode{201606L} \\ \rowsep +\defnxname{cpp_lambdas} & \tcode{200907L} \\ \rowsep +\defnxname{cpp_modules} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_multidimensional_subscript} & \tcode{202211L} \\ \rowsep +\defnxname{cpp_named_character_escapes} & \tcode{202207L} \\ \rowsep +\defnxname{cpp_namespace_attributes} & \tcode{201411L} \\ \rowsep +\defnxname{cpp_noexcept_function_type} & \tcode{201510L} \\ \rowsep +\defnxname{cpp_nontype_template_args} & \tcode{201911L} \\ \rowsep +\defnxname{cpp_nontype_template_parameter_auto} & \tcode{201606L} \\ \rowsep +\defnxname{cpp_nsdmi} & \tcode{200809L} \\ \rowsep +\defnxname{cpp_pack_indexing} & \tcode{202311L} \\ \rowsep +\defnxname{cpp_placeholder_variables} & \tcode{202306L} \\ \rowsep +\defnxname{cpp_range_based_for} & \tcode{202211L} \\ \rowsep +\defnxname{cpp_raw_strings} & \tcode{200710L} \\ \rowsep +\defnxname{cpp_ref_qualifiers} & \tcode{200710L} \\ \rowsep +\defnxname{cpp_return_type_deduction} & \tcode{201304L} \\ \rowsep +\defnxname{cpp_rvalue_references} & \tcode{200610L} \\ \rowsep +\defnxname{cpp_size_t_suffix} & \tcode{202011L} \\ \rowsep +\defnxname{cpp_sized_deallocation} & \tcode{201309L} \\ \rowsep +\defnxname{cpp_static_assert} & \tcode{202306L} \\ \rowsep +\defnxname{cpp_static_call_operator} & \tcode{202207L} \\ \rowsep +\defnxname{cpp_structured_bindings} & \tcode{202403L} \\ \rowsep +\defnxname{cpp_template_template_args} & \tcode{201611L} \\ \rowsep +\defnxname{cpp_threadsafe_static_init} & \tcode{200806L} \\ \rowsep +\defnxname{cpp_unicode_characters} & \tcode{200704L} \\ \rowsep +\defnxname{cpp_unicode_literals} & \tcode{200710L} \\ \rowsep +\defnxname{cpp_user_defined_literals} & \tcode{200809L} \\ \rowsep +\defnxname{cpp_using_enum} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_variable_templates} & \tcode{201304L} \\ \rowsep +\defnxname{cpp_variadic_friend} & \tcode{202403L} \\ \rowsep +\defnxname{cpp_variadic_templates} & \tcode{200704L} \\ \rowsep +\defnxname{cpp_variadic_using} & \tcode{201611L} \\ +\end{LongTable} + +\pnum +The following macro names are conditionally defined by the implementation: + +\begin{description} +\item +\indextext{__stdc__@\mname{STDC}}% +\mname{STDC}\\ +Whether \mname{STDC} is predefined and if so, what its value is, +are \impldef{definition and meaning of \mname{STDC}}. + +\item +\indextext{__stdc_mb_might_neq_wc__@\mname{STDC_MB_MIGHT_NEQ_WC}}% +\mname{STDC_MB_MIGHT_NEQ_WC}\\ +The integer literal \tcode{1}, intended to indicate that, in the encoding for +\keyword{wchar_t}, a member of the basic character set need not have a code value equal to +its value when used as the lone character in an ordinary character literal. + +\item +\indextext{__stdc_version__@\mname{STDC_VERSION}}% +\mname{STDC_VERSION}\\ +Whether \mname{STDC_VERSION} is predefined and if so, what its value is, +are \impldef{definition and meaning of \mname{STDC_VERSION}}. + +\item +\indextext{__stdc_iso_10646__@\mname{STDC_ISO_10646}}% +\mname{STDC_ISO_10646}\\ +An integer literal of the form \tcode{yyyymmL} +(for example, \tcode{199712L}). +Whether \mname{STDC_ISO_10646} is predefined and +if so, what its value is, +are \impldef{presence and value of \mname{STDC_ISO_10646}}. + +\item +\indextext{__stdcpp_threads__@\mname{STDCPP_THREADS}}% +\mname{STDCPP_THREADS}\\ +Defined, and has the value integer literal 1, if and only if a program +can have more than one thread of execution\iref{intro.multithread}. + +\end{description} + +\pnum +The values of the predefined macros +(except for +\mname{FILE} +and +\mname{LINE}) +remain constant throughout the translation unit. + +\pnum +If any of the pre-defined macro names in this subclause, +or the identifier +\tcode{defined}, +is the subject of a +\tcode{\#define} +or a +\tcode{\#undef} +preprocessing directive, +the behavior is undefined. +Any other predefined macro names shall begin with a +leading underscore followed by an uppercase letter or a second +underscore. + +\rSec2[cpp.cond]{Conditional inclusion}% +\indextext{preprocessing directive!conditional inclusion}% +\indextext{inclusion!conditional|see{preprocessing directive, conditional inclusion}} + +\indextext{\idxcode{defined}}% +\begin{bnf} +\nontermdef{defined-macro-expression}\br + \terminal{defined} identifier\br + \terminal{defined (} identifier \terminal{)} +\end{bnf} +\begin{bnf} +\nontermdef{h-preprocessing-token}\br + \textnormal{any \grammarterm{preprocessing-token} other than \terminal{>}} +\end{bnf} + +\begin{bnf} +\nontermdef{h-pp-tokens}\br + h-preprocessing-token\br + h-pp-tokens h-preprocessing-token +\end{bnf} + +\begin{bnf} +\nontermdef{header-name-tokens}\br + string-literal\br + \terminal{<} h-pp-tokens \terminal{>} +\end{bnf} + +\indextext{\idxxname{has_include}}% +\begin{bnf} +\nontermdef{has-include-expression}\br + \terminal{\xname{has_include}} \terminal{(} header-name \terminal{)}\br + \terminal{\xname{has_include}} \terminal{(} header-name-tokens \terminal{)} +\end{bnf} + +\indextext{\idxxname{has_cpp_attribute}}% +\begin{bnf} +\nontermdef{has-attribute-expression}\br + \terminal{\xname{has_cpp_attribute} (} pp-tokens \terminal{)} +\end{bnf} + +\pnum +The expression that controls conditional inclusion +shall be an integral constant expression except that +identifiers +(including those lexically identical to keywords) +are interpreted as described below +\begin{footnote} +Because the controlling constant expression is evaluated +during translation phase 4, +all identifiers either are or are not macro names --- +there simply are no keywords, enumeration constants, etc. +\end{footnote} +and it may contain zero or more \grammarterm{defined-macro-expression}{s} and/or +\grammarterm{has-include-expression}{s} and/or +\grammarterm{has-attribute-expression}{s} as unary operator expressions. + +\pnum +A \grammarterm{defined-macro-expression} evaluates to \tcode{1} +if the identifier is currently defined +as a macro name +(that is, if it is predefined +or if it has one or more active macro definitions\iref{cpp.import}, +for example because +it has been the subject of a +\tcode{\#define} +preprocessing directive +without an intervening +\tcode{\#undef} +directive with the same subject identifier), \tcode{0} if it is not. + +\pnum +The second form of \grammarterm{has-include-expression} +is considered only if the first form does not match, +in which case the preprocessing tokens are processed just as in normal text. + +\pnum +The header or source file identified by +the parenthesized preprocessing token sequence +in each contained \grammarterm{has-include-expression} +is searched for as if that preprocessing token sequence +were the \grammarterm{pp-tokens} in a \tcode{\#include} directive, +except that no further macro expansion is performed. +If such a directive would not satisfy the syntactic requirements +of a \tcode{\#include} directive, the program is ill-formed. +The \grammarterm{has-include-expression} evaluates +to \tcode{1} if the search for the source file succeeds, and +to \tcode{0} if the search fails. + +\pnum +Each \grammarterm{has-attribute-expression} is replaced by +a non-zero \grammarterm{pp-number} +matching the form of an \grammarterm{integer-literal} +if the implementation supports an attribute +with the name specified by interpreting +the \grammarterm{pp-tokens}, after macro expansion, +as an \grammarterm{attribute-token}, +and by \tcode{0} otherwise. +The program is ill-formed if the \grammarterm{pp-tokens} +do not match the form of an \grammarterm{attribute-token}. + +\pnum +For an attribute specified in this document, +it is \impldef{value of \grammarterm{has-attribute-expression} +for standard attributes} +whether the value of the \grammarterm{has-attribute-expression} +is \tcode{0} or is given by \tref{cpp.cond.ha}. +For other attributes recognized by the implementation, +the value is +\impldef{value of \grammarterm{has-attribute-expression} +for non-standard attributes}. +\begin{note} +It is expected +that the availability of an attribute can be detected by any non-zero result. +\end{note} + +\begin{floattable}{\xname{has_cpp_attribute} values}{cpp.cond.ha} +{ll} +\topline +\lhdr{Attribute} & \rhdr{Value} \\ \rowsep +\tcode{assume} & \tcode{202207L} \\ +\tcode{carries_dependency} & \tcode{200809L} \\ +\tcode{deprecated} & \tcode{201309L} \\ +\tcode{fallthrough} & \tcode{201603L} \\ +\tcode{likely} & \tcode{201803L} \\ +\tcode{maybe_unused} & \tcode{201603L} \\ +\tcode{no_unique_address} & \tcode{201803L} \\ +\tcode{nodiscard} & \tcode{201907L} \\ +\tcode{noreturn} & \tcode{200809L} \\ +\tcode{unlikely} & \tcode{201803L} \\ +\end{floattable} + +\pnum +The +\tcode{\#ifdef}, \tcode{\#ifndef}, \tcode{\#elifdef}, and \tcode{\#elifndef} +directives, and +the \tcode{defined} conditional inclusion operator, +shall treat \xname{has_include} and \xname{has_cpp_attribute} +as if they were the names of defined macros. +The identifiers \xname{has_include} and \xname{has_cpp_attribute} +shall not appear in any context not mentioned in this subclause. + +\pnum +Each preprocessing token that remains (in the list of preprocessing tokens that +will become the controlling expression) +after all macro replacements have occurred +shall be in the lexical form of a token\iref{lex.token}. + +\pnum +Preprocessing directives of the forms +\begin{ncsimplebnf}\obeyspaces +\indextext{\idxcode{\#if}}% +\terminal{\# if } constant-expression new-line \opt{group}\br +\indextext{\idxcode{\#elif}}% +\terminal{\# elif } constant-expression new-line \opt{group} +\end{ncsimplebnf} +check whether the controlling constant expression evaluates to nonzero. + +\pnum +Prior to evaluation, +macro invocations in the list of preprocessing tokens +that will become the controlling constant expression +are replaced +(except for those macro names modified by the +\tcode{defined} +unary operator), +just as in normal text. +If the token +\tcode{defined} +is generated as a result of this replacement process +or use of the +\tcode{defined} +unary operator does not match one of the two specified forms +prior to macro replacement, +the behavior is undefined. + +\pnum +After all replacements due to macro expansion and +evaluations of +\grammarterm{defined-macro-expression}s, +\grammarterm{has-include-expression}s, and +\grammarterm{has-attribute-expression}s +have been performed, +all remaining identifiers and keywords, +except for +\tcode{true} +and +\tcode{false}, +are replaced with the \grammarterm{pp-number} +\tcode{0}, +and then each preprocessing token is converted into a token. +\begin{note} +An alternative +token\iref{lex.operators} is not an identifier, +even when its spelling consists entirely of letters and underscores. +Therefore it is not subject to this replacement. +\end{note} + +\pnum +The resulting tokens comprise the controlling constant expression +which is evaluated according to the rules of~\ref{expr.const} +using arithmetic that has at least the ranges specified +in~\ref{support.limits}. For the purposes of this token conversion and evaluation +all signed and unsigned integer types +act as if they have the same representation as, respectively, +\tcode{intmax_t} or \tcode{uintmax_t}\iref{cstdint.syn}. +\begin{note} +Thus on an +implementation where \tcode{std::numeric_limits::max()} is \tcode{0x7FFF} +and \tcode{std::numeric_limits::max()} is \tcode{0xFFFF}, +the integer literal \tcode{0x8000} is signed and positive within a \tcode{\#if} +expression even though it is unsigned in translation phase +7\iref{lex.phases}. +\end{note} +This includes interpreting \grammarterm{character-literal}s +according to the rules in \ref{lex.ccon}. +\begin{note} +The associated character encodings of literals are the same +in \tcode{\#if} and \tcode{\#elif} directives and in any expression. +\end{note} +Each subexpression with type +\tcode{bool} +is subjected to integral promotion before processing continues. + +\pnum +Preprocessing directives of the forms +\begin{ncsimplebnf}\obeyspaces +\terminal{\# ifdef } identifier new-line \opt{group}\br +\indextext{\idxcode{\#ifdef}}% +\terminal{\# ifndef } identifier new-line \opt{group}\br +\indextext{\idxcode{\#ifndef}}% +\terminal{\# elifdef } identifier new-line \opt{group}\br +\indextext{\idxcode{\#elifdef}}% +\terminal{\# elifndef} identifier new-line \opt{group} +\indextext{\idxcode{\#elifndef}}% +\end{ncsimplebnf} +check whether the identifier is or is not currently defined as a macro name. +Their conditions are equivalent to +\tcode{\#if} \tcode{defined} \grammarterm{identifier}, +\tcode{\#if} \tcode{!defined} \grammarterm{identifier}, +\tcode{\#elif} \tcode{defined} \grammarterm{identifier}, and +\tcode{\#elif} \tcode{!defined} \grammarterm{identifier}, +respectively. + +\pnum +Each directive's condition is checked in order. +If it evaluates to false (zero), +the group that it controls is skipped: +directives are processed only through the name that determines +the directive in order to keep track of the level +of nested conditionals; +the rest of the directives' preprocessing tokens are ignored, +as are the other preprocessing tokens in the group. +Only the first group +whose control condition evaluates to true (nonzero) is processed; +any following groups are skipped and their controlling directives +are processed as if they were in a group that is skipped. +If none of the conditions evaluates to true, +and there is a +\tcode{\#else} +\indextext{\idxcode{\#else}}% +directive, +the group controlled by the +\tcode{\#else} +is processed; lacking a +\tcode{\#else} +directive, all the groups until the +\tcode{\#endif} +\indextext{\idxcode{\#endif}}% +are skipped.% +\begin{footnote} +As indicated by the syntax, +a preprocessing token cannot follow a +\tcode{\#else} +or +\tcode{\#endif} +directive before the terminating new-line character. +However, +comments can appear anywhere in a source file, +including within a preprocessing directive. +\end{footnote} + +\pnum +\begin{example} +This demonstrates a way to include a library \tcode{optional} facility +only if it is available: + +\begin{codeblock} +#if __has_include() +# include +# if __cpp_lib_optional >= 201603 +# define have_optional 1 +# endif +#elif __has_include() +# include +# if __cpp_lib_experimental_optional >= 201411 +# define have_optional 1 +# define experimental_optional 1 +# endif +#endif +#ifndef have_optional +# define have_optional 0 +#endif +\end{codeblock} +\end{example} + +\pnum +\begin{example} +This demonstrates a way to use the attribute \tcode{[[acme::deprecated]]} +only if it is available. +\begin{codeblock} +#if __has_cpp_attribute(acme::deprecated) +# define ATTR_DEPRECATED(msg) [[acme::deprecated(msg)]] +#else +# define ATTR_DEPRECATED(msg) [[deprecated(msg)]] +#endif +ATTR_DEPRECATED("This function is deprecated") void anvil(); +\end{codeblock} +\end{example} + +\rSec2[cpp.include]{Source file inclusion} +\indextext{preprocessing directive!header inclusion} +\indextext{preprocessing directive!source-file inclusion} +\indextext{inclusion!source file|see{preprocessing directive, source-file inclusion}}% +\indextext{\idxcode{\#include}}% + +\pnum +A +\tcode{\#include} +directive shall identify a header or source file +that can be processed by the implementation. + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# include <} h-char-sequence \terminal{>} new-line +\end{ncsimplebnf} +searches a sequence of +\impldef{sequence of places searched for a header} +places +for a header identified uniquely by the specified sequence +between the +\tcode{<} +and +\tcode{>} +delimiters, +and causes the replacement of that +directive by the entire contents of the header. +How the places are specified +or the header identified +is \impldef{search locations for \tcode{<>} header}. + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# include "} q-char-sequence \terminal{"} new-line +\end{ncsimplebnf} +causes the replacement of that +directive by the entire contents of the +source file identified by the specified sequence between the +\tcode{"} +delimiters. +The named source file is searched for in an +\impldef{manner of search for included source file} +manner. +If this search is not supported, +or if the search fails, +the directive is reprocessed as if it read +\begin{ncsimplebnf} +\terminal{\# include <} h-char-sequence \terminal{>} new-line +\end{ncsimplebnf} +with the identical contained sequence (including +\tcode{>} +characters, if any) from the original directive. +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# include} pp-tokens new-line +\end{ncsimplebnf} +(that does not match one of the two previous forms) is permitted. +The preprocessing tokens after +\tcode{include} +in the directive are processed just as in normal text +(i.e., each identifier currently defined as a macro name is replaced by its +replacement list of preprocessing tokens). +If the directive resulting after all replacements does not match +one of the two previous forms, the behavior is +undefined. +\begin{footnote} +Note that adjacent \grammarterm{string-literal}s are not concatenated into +a single \grammarterm{string-literal} +(see the translation phases in~\ref{lex.phases}); +thus, an expansion that results in two \grammarterm{string-literal}s is an +invalid directive. +\end{footnote} +The method by which a sequence of preprocessing tokens between a +\tcode{<} +and a +\tcode{>} +preprocessing token pair or a pair of +\tcode{"} +characters is combined into a single header name +preprocessing token is \impldef{search locations for \tcode{""""} header}. + +\pnum +The implementation shall provide unique mappings for +sequences consisting of one or more +\grammarterm{nondigit}{s} or \grammarterm{digit}{s}\iref{lex.name} +followed by a period +(\tcode{.}) +and a single +\grammarterm{nondigit}. +The first character shall not be a \grammarterm{digit}. +The implementation may ignore distinctions of alphabetical case. + +\pnum +A +\tcode{\#include} +preprocessing directive may appear +in a source file that has been read because of a +\tcode{\#include} +directive in another file, +up to an \impldef{nesting limit for \tcode{\#include} directives} nesting limit. + +\pnum +If the header identified by the \grammarterm{header-name} +denotes an importable header\iref{module.import}, +it is +\impldef{whether source file inclusion of importable header +is replaced with \tcode{import} directive} +whether the \tcode{\#include} preprocessing directive +is instead replaced by an \tcode{import} directive\iref{cpp.import} of the form +\begin{ncbnf} +\terminal{import} header-name \terminal{;} new-line +\end{ncbnf} +\pnum +\begin{note} +An implementation can provide a mechanism for making arbitrary +source files available to the \tcode{< >} search. +However, using the \tcode{< >} form for headers provided +with the implementation and the \tcode{" "} form for sources +outside the control of the implementation +achieves wider portability. For instance: -\rSec1[lex.ppexec]{Preprocessor execution} +\begin{codeblock} +#include +#include +#include "usefullib.h" +#include "myprog.h" +\end{codeblock} +\end{note} +\pnum +\begin{example} +This illustrates macro-replaced +\tcode{\#include} +directives: +\begin{codeblock} +#if VERSION == 1 + #define INCFILE "vers1.h" +#elif VERSION == 2 + #define INCFILE "vers2.h" // and so on +#else + #define INCFILE "versN.h" +#endif +#include INCFILE +\end{codeblock} +\end{example} -\rSec1[lex.tokenize]{Tokenization} +\rSec1[lex.tutokenize]{Translation unit tokenization} \rSec2[lex.token]{Tokens} \indextext{token|(}% @@ -1509,7 +3488,7 @@ operators, and other separators. \indextext{whitespace}% Blanks, horizontal and vertical tabs, newlines, formfeeds, and comments -(collectively, ``whitespace''), as described below, are ignored except +(collectively, ``whitespace''), are ignored except as they serve to separate tokens. \begin{note} Whitespace can separate otherwise adjacent identifiers, keywords, numeric @@ -1626,6 +3605,39 @@ \keyword{while} \\ \end{multicolfloattable} +\pnum +\indextext{\idxcode{import}}% +\indextext{\idxcode{final}}% +\indextext{\idxcode{module}}% +\indextext{\idxcode{override}}% +The identifiers in \tref{lex.name.special} have a special meaning when +appearing in a certain context. When referred to in the grammar, these identifiers +are used explicitly rather than using the \grammarterm{identifier} grammar production. +Unless otherwise specified, any ambiguity as to whether a given +\grammarterm{identifier} has a special meaning is resolved to interpret the +token as a regular \grammarterm{identifier}. + +\begin{multicolfloattable}{Identifiers with special meaning}{lex.name.special} +{llll} +\keyword{final} \\ +\columnbreak +\keyword{import} \\ +\columnbreak +\keyword{module} \\ +\columnbreak +\keyword{override} \\ +\end{multicolfloattable} + +\pnum +\indextext{unit!translation}% +A translation unit shall not \tcode{\#define} or \tcode{\#undef} +names lexically identical +to keywords, +to the identifiers listed in \tref{lex.name.special}, or +to the \grammarterm{attribute-token}{s} described in~\ref{dcl.attr}, +except that the names \tcode{likely} and \tcode{unlikely} may be +defined as function-like macros~\iref{cpp.replace}. + \pnum Furthermore, the alternative representations shown in \tref{lex.key.digraph} for certain operators and @@ -1640,7 +3652,6 @@ \end{floattable}% \indextext{keyword|)}% - \rSec2[lex.literal]{Literals}% \indextext{literal|(} diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 86ab73dda5..8ca834f9d4 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -3188,16 +3188,6 @@ \tcode{\#define} or \tcode{\#undef} names declared in any standard library header. -\pnum -\indextext{unit!translation}% -A translation unit shall not \tcode{\#define} or \tcode{\#undef} -names lexically identical -to keywords, -to the identifiers listed in \tref{lex.name.special}, or -to the \grammarterm{attribute-token}{s} described in~\ref{dcl.attr}, -except that the names \tcode{likely} and \tcode{unlikely} may be -defined as function-like macros~\iref{cpp.replace}. - \rSec4[extern.names]{External linkage} \pnum diff --git a/source/modules.tex b/source/modules.tex index 9298ba4dee..a1d5b003a0 100644 --- a/source/modules.tex +++ b/source/modules.tex @@ -32,7 +32,7 @@ \pnum \indextext{translation unit}% -A translation unit consists of a sequence of declarations. +A translation unit\iref{lex.phases} consists of a sequence of declarations. \pnum A \defn{module unit} is a translation unit that contains diff --git a/source/preprocessor.tex b/source/preprocessor.tex deleted file mode 100644 index d0a80dadaf..0000000000 --- a/source/preprocessor.tex +++ /dev/null @@ -1,2009 +0,0 @@ -%!TEX root = std.tex -\rSec0[cpp]{Preprocessing directives}% -\indextext{preprocessing directive|(} - -\indextext{compiler control line|see{preprocessing directive}}% -\indextext{control line|see{preprocessing directive}}% -\indextext{directive, preprocessing|see{preprocessing directive}} - -\gramSec[gram.cpp]{Preprocessing directives} - -\rSec1[cpp.pre]{Preamble} - -\begin{bnf} -\nontermdef{preprocessing-file}\br - \opt{group}\br - module-file -\end{bnf} - -\begin{bnf} -\nontermdef{module-file}\br - \opt{pp-global-module-fragment} pp-module \opt{group} \opt{pp-private-module-fragment} -\end{bnf} - -\begin{bnf} -\nontermdef{pp-global-module-fragment}\br - \keyword{module} \terminal{;} new-line \opt{group} -\end{bnf} - -\begin{bnf} -\nontermdef{pp-private-module-fragment}\br - \keyword{module} \terminal{:} \keyword{private} \terminal{;} new-line \opt{group} -\end{bnf} - -\begin{bnf} -\nontermdef{group}\br - group-part\br - group group-part -\end{bnf} - -\begin{bnf} -\nontermdef{group-part}\br - control-line\br - if-section\br - text-line\br - \terminal{\#} conditionally-supported-directive -\end{bnf} - -\begin{bnf}\obeyspaces -\nontermdef{control-line}\br - \terminal{\# include} pp-tokens new-line\br - pp-import\br - \terminal{\# define } identifier replacement-list new-line\br - \terminal{\# define } identifier lparen \opt{identifier-list} \terminal{)} replacement-list new-line\br - \terminal{\# define } identifier lparen \terminal{... )} replacement-list new-line\br - \terminal{\# define } identifier lparen identifier-list \terminal{, ... )} replacement-list new-line\br - \terminal{\# undef } identifier new-line\br - \terminal{\# line } pp-tokens new-line\br - \terminal{\# error } \opt{pp-tokens} new-line\br - \terminal{\# warning} \opt{pp-tokens} new-line\br - \terminal{\# pragma } \opt{pp-tokens} new-line\br - \terminal{\# }new-line -\end{bnf} - -\begin{bnf} -\nontermdef{if-section}\br - if-group \opt{elif-groups} \opt{else-group} endif-line -\end{bnf} - -\begin{bnf}\obeyspaces -\nontermdef{if-group}\br - \terminal{\# if } constant-expression new-line \opt{group}\br - \terminal{\# ifdef } identifier new-line \opt{group}\br - \terminal{\# ifndef } identifier new-line \opt{group} -\end{bnf} - -\begin{bnf} -\nontermdef{elif-groups}\br - elif-group\br - elif-groups elif-group -\end{bnf} - -\begin{bnf}\obeyspaces -\nontermdef{elif-group}\br - \terminal{\# elif } constant-expression new-line \opt{group}\br - \terminal{\# elifdef } identifier new-line \opt{group}\br - \terminal{\# elifndef} identifier new-line \opt{group} -\end{bnf} - -\begin{bnf}\obeyspaces -\nontermdef{else-group}\br - \terminal{\# else } new-line \opt{group} -\end{bnf} - -\begin{bnf}\obeyspaces -\nontermdef{endif-line}\br - \terminal{\# endif } new-line -\end{bnf} - -\begin{bnf} -\nontermdef{text-line}\br - \opt{pp-tokens} new-line -\end{bnf} - -\begin{bnf} -\nontermdef{conditionally-supported-directive}\br - pp-tokens new-line -\end{bnf} - -\begin{bnf} -\nontermdef{lparen}\br - \descr{a \terminal{(} character not immediately preceded by whitespace} -\end{bnf} - -\begin{bnf} -\nontermdef{identifier-list}\br - identifier\br - identifier-list \terminal{,} identifier -\end{bnf} - -\begin{bnf} -\nontermdef{replacement-list}\br - \opt{pp-tokens} -\end{bnf} - -\begin{bnf} -\nontermdef{pp-tokens}\br - preprocessing-token\br - pp-tokens preprocessing-token -\end{bnf} - -\begin{bnf} -\nontermdef{new-line}\br - \descr{the new-line character} -\end{bnf} - -\pnum -A \defn{preprocessing directive} consists of a sequence of preprocessing tokens -that satisfies the following constraints: -At the start of translation phase 4, -the first token in the sequence, -referred to as a \defnadj{directive-introducing}{token}, -begins with the first character in the source file -(optionally after whitespace containing no new-line characters) or -follows whitespace containing at least one new-line character, -and is - -\begin{itemize} -\item -a \tcode{\#} preprocessing token, or - -\item -an \keyword{import} preprocessing token -immediately followed on the same logical source line by a -\grammarterm{header-name}, -\tcode{<}, -\grammarterm{identifier}, -\grammarterm{string-literal}, or -\tcode{:} -preprocessing token, or - -\item -a \keyword{module} preprocessing token -immediately followed on the same logical source line by an -\grammarterm{identifier}, -\tcode{:}, or -\tcode{;} -preprocessing token, or - -\item -an \keyword{export} preprocessing token -immediately followed on the same logical source line by -one of the two preceding forms. -\end{itemize} - -The last token in the sequence is the first token within the sequence that -is immediately followed by whitespace containing a new-line character. -\begin{footnote} -Thus, -preprocessing directives are commonly called ``lines''. -These ``lines'' have no other syntactic significance, -as all whitespace is equivalent except in certain situations -during preprocessing (see the -\tcode{\#} -character string literal creation operator in~\ref{cpp.stringize}, for example). -\end{footnote} -\begin{note} -A new-line character ends the preprocessing directive even if it occurs -within what would otherwise be an invocation of a function-like macro. -\end{note} - -\begin{example} -\begin{codeblock} -# // preprocessing directive -module ; // preprocessing directive -export module leftpad; // preprocessing directive -import ; // preprocessing directive -export import "squee"; // preprocessing directive -import rightpad; // preprocessing directive -import :part; // preprocessing directive - -module // not a preprocessing directive -; // not a preprocessing directive - -export // not a preprocessing directive -import // not a preprocessing directive -foo; // not a preprocessing directive - -export // not a preprocessing directive -import foo; // preprocessing directive (ill-formed at phase 7) - -import :: // not a preprocessing directive -import -> // not a preprocessing directive -\end{codeblock} -\end{example} - -\pnum -A sequence of preprocessing tokens is only a \grammarterm{text-line} -if it does not begin with a directive-introducing token. -A sequence of preprocessing tokens is only a \grammarterm{conditionally-supported-directive} -if it does not begin with any of the directive names -appearing after a \tcode{\#} in the syntax. -A \grammarterm{conditionally-supported-directive} is -conditionally-supported with -\impldef{additional supported forms of preprocessing directive} -semantics. - -\pnum -At the start of phase 4 of translation, -the \grammarterm{group} of a \grammarterm{pp-global-module-fragment} shall -contain neither a \grammarterm{text-line} nor a \grammarterm{pp-import}. - -\pnum -When in a group that is skipped\iref{cpp.cond}, the directive -syntax is relaxed to allow any sequence of preprocessing tokens to occur between -the directive name and the following new-line character. - -\pnum -The only whitespace characters that shall appear -between preprocessing tokens -within a preprocessing directive -(from just after the directive-introducing token -through just before the terminating new-line character) -are space and horizontal-tab -(including spaces that have replaced comments -or possibly other whitespace characters -in translation phase 3). - -\pnum -The implementation can -process and skip sections of source files conditionally, -include other source files, -import macros from header units, -and replace macros. -These capabilities are called -\defn{preprocessing}, -because conceptually they occur -before translation of the resulting translation unit. - -\pnum -The preprocessing tokens within a preprocessing directive -are not subject to macro expansion unless otherwise stated. - -\begin{example} -In: -\begin{codeblock} -#define EMPTY -EMPTY # include -\end{codeblock} -the sequence of preprocessing tokens on the second line is \textit{not} -a preprocessing directive, because it does not begin with a \tcode{\#} at the start of -translation phase 4, even though it will do so after the macro \tcode{EMPTY} -has been replaced. -\end{example} - -\rSec1[cpp.cond]{Conditional inclusion}% -\indextext{preprocessing directive!conditional inclusion}% -\indextext{inclusion!conditional|see{preprocessing directive, conditional inclusion}} - -\indextext{\idxcode{defined}}% -\begin{bnf} -\nontermdef{defined-macro-expression}\br - \terminal{defined} identifier\br - \terminal{defined (} identifier \terminal{)} -\end{bnf} - -\begin{bnf} -\nontermdef{h-preprocessing-token}\br - \textnormal{any \grammarterm{preprocessing-token} other than \terminal{>}} -\end{bnf} - -\begin{bnf} -\nontermdef{h-pp-tokens}\br - h-preprocessing-token\br - h-pp-tokens h-preprocessing-token -\end{bnf} - -\begin{bnf} -\nontermdef{header-name-tokens}\br - string-literal\br - \terminal{<} h-pp-tokens \terminal{>} -\end{bnf} - -\indextext{\idxxname{has_include}}% -\begin{bnf} -\nontermdef{has-include-expression}\br - \terminal{\xname{has_include}} \terminal{(} header-name \terminal{)}\br - \terminal{\xname{has_include}} \terminal{(} header-name-tokens \terminal{)} -\end{bnf} - -\indextext{\idxxname{has_cpp_attribute}}% -\begin{bnf} -\nontermdef{has-attribute-expression}\br - \terminal{\xname{has_cpp_attribute} (} pp-tokens \terminal{)} -\end{bnf} - -\pnum -The expression that controls conditional inclusion -shall be an integral constant expression except that -identifiers -(including those lexically identical to keywords) -are interpreted as described below -\begin{footnote} -Because the controlling constant expression is evaluated -during translation phase 4, -all identifiers either are or are not macro names --- -there simply are no keywords, enumeration constants, etc. -\end{footnote} -and it may contain zero or more \grammarterm{defined-macro-expression}{s} and/or -\grammarterm{has-include-expression}{s} and/or -\grammarterm{has-attribute-expression}{s} as unary operator expressions. - -\pnum -A \grammarterm{defined-macro-expression} evaluates to \tcode{1} -if the identifier is currently defined -as a macro name -(that is, if it is predefined -or if it has one or more active macro definitions\iref{cpp.import}, -for example because -it has been the subject of a -\tcode{\#define} -preprocessing directive -without an intervening -\tcode{\#undef} -directive with the same subject identifier), \tcode{0} if it is not. - -\pnum -The second form of \grammarterm{has-include-expression} -is considered only if the first form does not match, -in which case the preprocessing tokens are processed just as in normal text. - -\pnum -The header or source file identified by -the parenthesized preprocessing token sequence -in each contained \grammarterm{has-include-expression} -is searched for as if that preprocessing token sequence -were the \grammarterm{pp-tokens} in a \tcode{\#include} directive, -except that no further macro expansion is performed. -If such a directive would not satisfy the syntactic requirements -of a \tcode{\#include} directive, the program is ill-formed. -The \grammarterm{has-include-expression} evaluates -to \tcode{1} if the search for the source file succeeds, and -to \tcode{0} if the search fails. - -\pnum -Each \grammarterm{has-attribute-expression} is replaced by -a non-zero \grammarterm{pp-number} -matching the form of an \grammarterm{integer-literal} -if the implementation supports an attribute -with the name specified by interpreting -the \grammarterm{pp-tokens}, after macro expansion, -as an \grammarterm{attribute-token}, -and by \tcode{0} otherwise. -The program is ill-formed if the \grammarterm{pp-tokens} -do not match the form of an \grammarterm{attribute-token}. - -\pnum -For an attribute specified in this document, -it is \impldef{value of \grammarterm{has-attribute-expression} -for standard attributes} -whether the value of the \grammarterm{has-attribute-expression} -is \tcode{0} or is given by \tref{cpp.cond.ha}. -For other attributes recognized by the implementation, -the value is -\impldef{value of \grammarterm{has-attribute-expression} -for non-standard attributes}. -\begin{note} -It is expected -that the availability of an attribute can be detected by any non-zero result. -\end{note} - -\begin{floattable}{\xname{has_cpp_attribute} values}{cpp.cond.ha} -{ll} -\topline -\lhdr{Attribute} & \rhdr{Value} \\ \rowsep -\tcode{assume} & \tcode{202207L} \\ -\tcode{carries_dependency} & \tcode{200809L} \\ -\tcode{deprecated} & \tcode{201309L} \\ -\tcode{fallthrough} & \tcode{201603L} \\ -\tcode{likely} & \tcode{201803L} \\ -\tcode{maybe_unused} & \tcode{201603L} \\ -\tcode{no_unique_address} & \tcode{201803L} \\ -\tcode{nodiscard} & \tcode{201907L} \\ -\tcode{noreturn} & \tcode{200809L} \\ -\tcode{unlikely} & \tcode{201803L} \\ -\end{floattable} - -\pnum -The -\tcode{\#ifdef}, \tcode{\#ifndef}, \tcode{\#elifdef}, and \tcode{\#elifndef} -directives, and -the \tcode{defined} conditional inclusion operator, -shall treat \xname{has_include} and \xname{has_cpp_attribute} -as if they were the names of defined macros. -The identifiers \xname{has_include} and \xname{has_cpp_attribute} -shall not appear in any context not mentioned in this subclause. - -\pnum -Each preprocessing token that remains (in the list of preprocessing tokens that -will become the controlling expression) -after all macro replacements have occurred -shall be in the lexical form of a token\iref{lex.token}. - -\pnum -Preprocessing directives of the forms -\begin{ncsimplebnf}\obeyspaces -\indextext{\idxcode{\#if}}% -\terminal{\# if } constant-expression new-line \opt{group}\br -\indextext{\idxcode{\#elif}}% -\terminal{\# elif } constant-expression new-line \opt{group} -\end{ncsimplebnf} -check whether the controlling constant expression evaluates to nonzero. - -\pnum -Prior to evaluation, -macro invocations in the list of preprocessing tokens -that will become the controlling constant expression -are replaced -(except for those macro names modified by the -\tcode{defined} -unary operator), -just as in normal text. -If the token -\tcode{defined} -is generated as a result of this replacement process -or use of the -\tcode{defined} -unary operator does not match one of the two specified forms -prior to macro replacement, -the behavior is undefined. - -\pnum -After all replacements due to macro expansion and -evaluations of -\grammarterm{defined-macro-expression}s, -\grammarterm{has-include-expression}s, and -\grammarterm{has-attribute-expression}s -have been performed, -all remaining identifiers and keywords, -except for -\tcode{true} -and -\tcode{false}, -are replaced with the \grammarterm{pp-number} -\tcode{0}, -and then each preprocessing token is converted into a token. -\begin{note} -An alternative -token\iref{lex.operators} is not an identifier, -even when its spelling consists entirely of letters and underscores. -Therefore it is not subject to this replacement. -\end{note} - -\pnum -The resulting tokens comprise the controlling constant expression -which is evaluated according to the rules of~\ref{expr.const} -using arithmetic that has at least the ranges specified -in~\ref{support.limits}. For the purposes of this token conversion and evaluation -all signed and unsigned integer types -act as if they have the same representation as, respectively, -\tcode{intmax_t} or \tcode{uintmax_t}\iref{cstdint.syn}. -\begin{note} -Thus on an -implementation where \tcode{std::numeric_limits::max()} is \tcode{0x7FFF} -and \tcode{std::numeric_limits::max()} is \tcode{0xFFFF}, -the integer literal \tcode{0x8000} is signed and positive within a \tcode{\#if} -expression even though it is unsigned in translation phase -7\iref{lex.phases}. -\end{note} -This includes interpreting \grammarterm{character-literal}s -according to the rules in \ref{lex.ccon}. -\begin{note} -The associated character encodings of literals are the same -in \tcode{\#if} and \tcode{\#elif} directives and in any expression. -\end{note} -Each subexpression with type -\tcode{bool} -is subjected to integral promotion before processing continues. - -\pnum -Preprocessing directives of the forms -\begin{ncsimplebnf}\obeyspaces -\terminal{\# ifdef } identifier new-line \opt{group}\br -\indextext{\idxcode{\#ifdef}}% -\terminal{\# ifndef } identifier new-line \opt{group}\br -\indextext{\idxcode{\#ifndef}}% -\terminal{\# elifdef } identifier new-line \opt{group}\br -\indextext{\idxcode{\#elifdef}}% -\terminal{\# elifndef} identifier new-line \opt{group} -\indextext{\idxcode{\#elifndef}}% -\end{ncsimplebnf} -check whether the identifier is or is not currently defined as a macro name. -Their conditions are equivalent to -\tcode{\#if} \tcode{defined} \grammarterm{identifier}, -\tcode{\#if} \tcode{!defined} \grammarterm{identifier}, -\tcode{\#elif} \tcode{defined} \grammarterm{identifier}, and -\tcode{\#elif} \tcode{!defined} \grammarterm{identifier}, -respectively. - -\pnum -Each directive's condition is checked in order. -If it evaluates to false (zero), -the group that it controls is skipped: -directives are processed only through the name that determines -the directive in order to keep track of the level -of nested conditionals; -the rest of the directives' preprocessing tokens are ignored, -as are the other preprocessing tokens in the group. -Only the first group -whose control condition evaluates to true (nonzero) is processed; -any following groups are skipped and their controlling directives -are processed as if they were in a group that is skipped. -If none of the conditions evaluates to true, -and there is a -\tcode{\#else} -\indextext{\idxcode{\#else}}% -directive, -the group controlled by the -\tcode{\#else} -is processed; lacking a -\tcode{\#else} -directive, all the groups until the -\tcode{\#endif} -\indextext{\idxcode{\#endif}}% -are skipped.% -\begin{footnote} -As indicated by the syntax, -a preprocessing token cannot follow a -\tcode{\#else} -or -\tcode{\#endif} -directive before the terminating new-line character. -However, -comments can appear anywhere in a source file, -including within a preprocessing directive. -\end{footnote} - -\pnum -\begin{example} -This demonstrates a way to include a library \tcode{optional} facility -only if it is available: - -\begin{codeblock} -#if __has_include() -# include -# if __cpp_lib_optional >= 201603 -# define have_optional 1 -# endif -#elif __has_include() -# include -# if __cpp_lib_experimental_optional >= 201411 -# define have_optional 1 -# define experimental_optional 1 -# endif -#endif -#ifndef have_optional -# define have_optional 0 -#endif -\end{codeblock} -\end{example} - -\pnum -\begin{example} -This demonstrates a way to use the attribute \tcode{[[acme::deprecated]]} -only if it is available. -\begin{codeblock} -#if __has_cpp_attribute(acme::deprecated) -# define ATTR_DEPRECATED(msg) [[acme::deprecated(msg)]] -#else -# define ATTR_DEPRECATED(msg) [[deprecated(msg)]] -#endif -ATTR_DEPRECATED("This function is deprecated") void anvil(); -\end{codeblock} -\end{example} - -\rSec1[cpp.include]{Source file inclusion} -\indextext{preprocessing directive!header inclusion} -\indextext{preprocessing directive!source-file inclusion} -\indextext{inclusion!source file|see{preprocessing directive, source-file inclusion}}% -\indextext{\idxcode{\#include}}% - -\pnum -A -\tcode{\#include} -directive shall identify a header or source file -that can be processed by the implementation. - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# include <} h-char-sequence \terminal{>} new-line -\end{ncsimplebnf} -searches a sequence of -\impldef{sequence of places searched for a header} -places -for a header identified uniquely by the specified sequence -between the -\tcode{<} -and -\tcode{>} -delimiters, -and causes the replacement of that -directive by the entire contents of the header. -How the places are specified -or the header identified -is \impldef{search locations for \tcode{<>} header}. - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# include "} q-char-sequence \terminal{"} new-line -\end{ncsimplebnf} -causes the replacement of that -directive by the entire contents of the -source file identified by the specified sequence between the -\tcode{"} -delimiters. -The named source file is searched for in an -\impldef{manner of search for included source file} -manner. -If this search is not supported, -or if the search fails, -the directive is reprocessed as if it read -\begin{ncsimplebnf} -\terminal{\# include <} h-char-sequence \terminal{>} new-line -\end{ncsimplebnf} -with the identical contained sequence (including -\tcode{>} -characters, if any) from the original directive. - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# include} pp-tokens new-line -\end{ncsimplebnf} -(that does not match one of the two previous forms) is permitted. -The preprocessing tokens after -\tcode{include} -in the directive are processed just as in normal text -(i.e., each identifier currently defined as a macro name is replaced by its -replacement list of preprocessing tokens). -If the directive resulting after all replacements does not match -one of the two previous forms, the behavior is -undefined. -\begin{footnote} -Note that adjacent \grammarterm{string-literal}s are not concatenated into -a single \grammarterm{string-literal} -(see the translation phases in~\ref{lex.phases}); -thus, an expansion that results in two \grammarterm{string-literal}s is an -invalid directive. -\end{footnote} -The method by which a sequence of preprocessing tokens between a -\tcode{<} -and a -\tcode{>} -preprocessing token pair or a pair of -\tcode{"} -characters is combined into a single header name -preprocessing token is \impldef{search locations for \tcode{""""} header}. - -\pnum -The implementation shall provide unique mappings for -sequences consisting of one or more -\grammarterm{nondigit}{s} or \grammarterm{digit}{s}\iref{lex.name} -followed by a period -(\tcode{.}) -and a single -\grammarterm{nondigit}. -The first character shall not be a \grammarterm{digit}. -The implementation may ignore distinctions of alphabetical case. - -\pnum -A -\tcode{\#include} -preprocessing directive may appear -in a source file that has been read because of a -\tcode{\#include} -directive in another file, -up to an \impldef{nesting limit for \tcode{\#include} directives} nesting limit. - -\pnum -If the header identified by the \grammarterm{header-name} -denotes an importable header\iref{module.import}, -it is -\impldef{whether source file inclusion of importable header -is replaced with \tcode{import} directive} -whether the \tcode{\#include} preprocessing directive -is instead replaced by an \tcode{import} directive\iref{cpp.import} of the form -\begin{ncbnf} -\terminal{import} header-name \terminal{;} new-line -\end{ncbnf} - -\pnum -\begin{note} -An implementation can provide a mechanism for making arbitrary -source files available to the \tcode{< >} search. -However, using the \tcode{< >} form for headers provided -with the implementation and the \tcode{" "} form for sources -outside the control of the implementation -achieves wider portability. For instance: - -\begin{codeblock} -#include -#include -#include "usefullib.h" -#include "myprog.h" -\end{codeblock} - -\end{note} - -\pnum -\begin{example} -This illustrates macro-replaced -\tcode{\#include} -directives: - -\begin{codeblock} -#if VERSION == 1 - #define INCFILE "vers1.h" -#elif VERSION == 2 - #define INCFILE "vers2.h" // and so on -#else - #define INCFILE "versN.h" -#endif -#include INCFILE -\end{codeblock} -\end{example} - -\rSec1[cpp.module]{Module directive} -\indextext{preprocessing directive!module}% - -\begin{bnf} -\nontermdef{pp-module}\br - \opt{\keyword{export}} \keyword{module} \opt{pp-tokens} \terminal{;} new-line -\end{bnf} - -\pnum -A \grammarterm{pp-module} shall not -appear in a context where \tcode{module} -or (if it is the first token of the \grammarterm{pp-module}) \tcode{export} -is an identifier defined as an object-like macro. - -\pnum -The \grammarterm{pp-tokens}, if any, of a \grammarterm{pp-module} -shall be of the form: -\begin{ncsimplebnf} -pp-module-name \opt{pp-module-partition} \opt{pp-tokens} -\end{ncsimplebnf} -where the \grammarterm{pp-tokens} (if any) shall not begin with -a \tcode{(} preprocessing token and -the grammar non-terminals are defined as: -\begin{ncbnf} -\nontermdef{pp-module-name}\br - \opt{pp-module-name-qualifier} identifier -\end{ncbnf} -\begin{ncbnf} -\nontermdef{pp-module-partition}\br - \terminal{:} \opt{pp-module-name-qualifier} identifier -\end{ncbnf} -\begin{ncbnf} -\nontermdef{pp-module-name-qualifier}\br - identifier \terminal{.}\br - pp-module-name-qualifier identifier \terminal{.} -\end{ncbnf} -No \grammarterm{identifier} in -the \grammarterm{pp-module-name} or \grammarterm{pp-module-partition} -shall currently be defined as an object-like macro. - -\pnum -Any preprocessing tokens after the \tcode{module} preprocessing token -in the \tcode{module} directive are processed just as in normal text. -\begin{note} -Each identifier currently defined as a macro name -is replaced by its replacement list of preprocessing tokens. -\end{note} - -\pnum -The \tcode{module} and \tcode{export} (if it exists) preprocessing tokens -are replaced by the \grammarterm{module-keyword} and -\grammarterm{export-keyword} preprocessing tokens respectively. -\begin{note} -This makes the line no longer a directive -so it is not removed at the end of phase 4. -\end{note} - -\rSec1[cpp.import]{Header unit importation} -\indextext{header unit!preprocessing}% -\indextext{preprocessing directive!import}% -\indextext{macro!import|(}% - -\begin{bnf} -\nontermdef{pp-import}\br - \opt{\keyword{export}} \keyword{import} header-name \opt{pp-tokens} \terminal{;} new-line\br - \opt{\keyword{export}} \keyword{import} header-name-tokens \opt{pp-tokens} \terminal{;} new-line\br - \opt{\keyword{export}} \keyword{import} pp-tokens \terminal{;} new-line -\end{bnf} - -\pnum -A \grammarterm{pp-import} shall not -appear in a context where \tcode{import} -or (if it is the first token of the \grammarterm{pp-import}) \tcode{export} -is an identifier defined as an object-like macro. - -\pnum -The preprocessing tokens after the \tcode{import} preprocessing token -in the \tcode{import} \grammarterm{control-line} -are processed just as in normal text -(i.e., each identifier currently defined as a macro name -is replaced by its replacement list of preprocessing tokens). -\begin{note} -An \tcode{import} directive -matching the first two forms of a \grammarterm{pp-import} -instructs the preprocessor to import macros -from the header unit\iref{module.import} -denoted by the \grammarterm{header-name}, -as described below. -\end{note} -\indextext{point of!macro import|see{macro, point of import}}% -The \defnx{point of macro import}{macro!point of import} for the -first two forms of \grammarterm{pp-import} is -immediately after the \grammarterm{new-line} terminating -the \grammarterm{pp-import}. -The last form of \grammarterm{pp-import} is only considered -if the first two forms did not match, and -does not have a point of macro import. - -\pnum -If a \grammarterm{pp-import} is produced by source file inclusion -(including by the rewrite produced -when a \tcode{\#include} directive names an importable header) -while processing the \grammarterm{group} of a \grammarterm{module-file}, -the program is ill-formed. - -\pnum -In all three forms of \grammarterm{pp-import}, -the \tcode{import} and \tcode{export} (if it exists) preprocessing tokens -are replaced by the \grammarterm{import-keyword} and -\grammarterm{export-keyword} preprocessing tokens respectively. -\begin{note} -This makes the line no longer a directive -so it is not removed at the end of phase 4. -\end{note} -Additionally, in the second form of \grammarterm{pp-import}, -a \grammarterm{header-name} token is formed as if -the \grammarterm{header-name-tokens} -were the \grammarterm{pp-tokens} of a \tcode{\#include} directive. -The \grammarterm{header-name-tokens} are replaced by -the \grammarterm{header-name} token. -\begin{note} -This ensures that imports are treated consistently by -the preprocessor and later phases of translation. -\end{note} - -\pnum -Each \tcode{\#define} directive encountered when preprocessing -each translation unit in a program results in a distinct -\defnx{macro definition}{macro!definition}. -\begin{note} -A predefined macro name\iref{cpp.predefined} -is not introduced by a \tcode{\#define} directive. -Implementations providing mechanisms to predefine additional macros -are encouraged to not treat them -as being introduced by a \tcode{\#define} directive. -\end{note} -Each macro definition has at most one point of definition in -each translation unit and at most one point of undefinition, as follows: -\begin{itemize} -\item -\indextext{point of!macro definition|see{macro, point of definition}}% -The \defnx{point of definition}{macro!point of definition} -of a macro definition within a translation unit $T$ is -\begin{itemize} -\item -if the \tcode{\#define} directive of the macro definition occurs within $T$, -the point at which that directive occurs, or otherwise, -\item -if the macro name is not lexically identical to a keyword\iref{lex.key} -or to the \grammarterm{identifier}{s} \tcode{module} or \tcode{import}, -the first point of macro import in $T$ of a header unit -containing a point of definition for the macro definition, if any. -\end{itemize} -In the latter case, the macro is said -to be \defnx{imported}{macro!import} from the header unit. - -\item -\indextext{point of!macro undefinition|see{macro, point of undefinition}}% -The \defnx{point of undefinition}{macro!point of undefinition} -of a macro definition within a translation unit -is the first point at which a \tcode{\#undef} directive naming the macro occurs -after its point of definition, or the first point -of macro import of a header unit containing a point of undefinition for the -macro definition, whichever (if any) occurs first. -\end{itemize} - -\pnum -\indextext{active macro directive|see{macro, active}}% -A macro directive is \defnx{active}{macro!active} at a source location -if it has a point of definition in that translation unit preceding the location, -and does not have a point of undefinition in that translation unit preceding -the location. - -\pnum -If a macro would be replaced or redefined, and multiple macro definitions -are active for that macro name, the active macro definitions shall all be -valid redefinitions of the same macro\iref{cpp.replace}. -\begin{note} -The relative order of \grammarterm{pp-import}{s} has no bearing on whether a -particular macro definition is active. -\end{note} - -\pnum -\begin{example} -\begin{codeblocktu}{Importable header \tcode{"a.h"}} -#define X 123 // \#1 -#define Y 45 // \#2 -#define Z a // \#3 -#undef X // point of undefinition of \#1 in \tcode{"a.h"} -\end{codeblocktu} - -\begin{codeblocktu}{Importable header \tcode{"b.h"}} -import "a.h"; // point of definition of \#1, \#2, and \#3, point of undefinition of \#1 in \tcode{"b.h"} -#define X 456 // OK, \#1 is not active -#define Y 6 // error: \#2 is active -\end{codeblocktu} - -\begin{codeblocktu}{Importable header \tcode{"c.h"}} -#define Y 45 // \#4 -#define Z c // \#5 -\end{codeblocktu} - -\begin{codeblocktu}{Importable header \tcode{"d.h"}} -import "c.h"; // point of definition of \#4 and \#5 in \tcode{"d.h"} -\end{codeblocktu} - -\begin{codeblocktu}{Importable header \tcode{"e.h"}} -import "a.h"; // point of definition of \#1, \#2, and \#3, point of undefinition of \#1 in \tcode{"e.h"} -import "d.h"; // point of definition of \#4 and \#5 in \tcode{"e.h"} -int a = Y; // OK, active macro definitions \#2 and \#4 are valid redefinitions -int c = Z; // error: active macro definitions \#3 and \#5 are not valid redefinitions of \tcode{Z} -\end{codeblocktu} - -\begin{codeblocktu}{Module unit \tcode{f}} -export module f; -export import "a.h"; - -int a = Y; // OK -\end{codeblocktu} - -\begin{codeblocktu}{Translation unit \tcode{\#1}} -import f; -int x = Y; // error: \tcode{Y} is neither a defined macro nor a declared name -\end{codeblocktu} -\end{example} -\indextext{macro!import|)} - -\rSec1[cpp.replace]{Macro replacement}% - -\rSec2[cpp.replace.general]{General}% -\indextext{macro!replacement|(}% -\indextext{replacement!macro|see{macro, replacement}}% -\indextext{preprocessing directive!macro replacement|see{macro, replacement}} - -\pnum -\indextext{macro!replacement list}% -Two replacement lists are identical if and only if -the preprocessing tokens in both have -the same number, ordering, spelling, and whitespace separation, -where all whitespace separations are considered identical. - -\pnum -An identifier currently defined as an -\indextext{macro!object-like}% -object-like macro (see below) may be redefined by another -\tcode{\#define} -preprocessing directive provided that the second definition is an -object-like macro definition and the two replacement lists -are identical, otherwise the program is ill-formed. -Likewise, an identifier currently defined as a -\indextext{macro!function-like}% -function-like macro (see below) may be redefined by another -\tcode{\#define} -preprocessing directive provided that the second definition is a -function-like macro definition that has the same number and spelling -of parameters, -and the two replacement lists are identical, -otherwise the program is ill-formed. - -\pnum -\begin{example} -The following sequence is valid: -\begin{codeblock} -#define OBJ_LIKE (1-1) -#define OBJ_LIKE @\tcode{/* whitespace */ (1-1) /* other */}@ -#define FUNC_LIKE(a) ( a ) -#define FUNC_LIKE( a )( @\tcode{/* note the whitespace */ \textbackslash}@ - a @\tcode{/* other stuff on this line}@ - @\tcode{*/}@ ) -\end{codeblock} -But the following redefinitions are invalid: -\begin{codeblock} -#define OBJ_LIKE (0) // different token sequence -#define OBJ_LIKE (1 - 1) // different whitespace -#define FUNC_LIKE(b) ( a ) // different parameter usage -#define FUNC_LIKE(b) ( b ) // different parameter spelling -\end{codeblock} -\end{example} - -\pnum -\indextext{macro!replacement list}% -There shall be whitespace between the identifier and the replacement list -in the definition of an object-like macro. - -\pnum -If the \grammarterm{identifier-list} in the macro definition does not end with -an ellipsis, the number of arguments (including those arguments consisting -of no preprocessing tokens) -in an invocation of a function-like macro shall -equal the number of parameters in the macro definition. -Otherwise, there shall be at least as many arguments in the invocation as there are -parameters in the macro definition (excluding the \tcode{...}). There -shall exist a -\tcode{)} -preprocessing token that terminates the invocation. - -\pnum -\indextext{__va_args__@\mname{VA_ARGS}}% -\indextext{__va_opt__@\mname{VA_OPT}}% -The identifiers \mname{VA_ARGS} and \mname{VA_OPT} -shall occur only in the \grammarterm{replacement-list} -of a function-like macro that uses the ellipsis notation in the parameters. - -\pnum -A parameter identifier in a function-like macro -shall be uniquely declared within its scope. - -\pnum -The identifier immediately following the -\tcode{define} -is called the -\indextext{name!macro|see{macro, name}}% -\defnx{macro name}{macro!name}. -There is one name space for macro names. -Any whitespace characters preceding or following the -replacement list of preprocessing tokens are not considered -part of the replacement list for either form of macro. - -\pnum -If a -\indextext{\#\#0 operator@\tcode{\#} operator} -\tcode{\#} -preprocessing token, -followed by an identifier, -occurs lexically -at the point at which a preprocessing directive can begin, -the identifier is not subject to macro replacement. - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# define} identifier replacement-list new-line -\indextext{\idxcode{\#define}}% -\end{ncsimplebnf} -defines an -\defnadj{object-like}{macro} that -causes each subsequent instance of the macro name -\begin{footnote} -Since, by macro-replacement time, -all \grammarterm{character-literal}s and \grammarterm{string-literal}s are preprocessing tokens, -not sequences possibly containing identifier-like subsequences -(see \ref{lex.phases}, translation phases), -they are never scanned for macro names or parameters. -\end{footnote} -to be replaced by the replacement list of preprocessing tokens -that constitute the remainder of the directive. -\begin{footnote} -An alternative token\iref{lex.operators} is not an identifier, -even when its spelling consists entirely of letters and underscores. -Therefore it is not possible to define a macro -whose name is the same as that of an alternative token. -\end{footnote} -The replacement list is then rescanned for more macro names as -specified below. - -\pnum -\begin{example} -The simplest use of this facility is to define a ``manifest constant'', -as in -\begin{codeblock} -#define TABSIZE 100 -int table[TABSIZE]; -\end{codeblock} -\end{example} - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# define} identifier lparen \opt{identifier-list} \terminal{)} replacement-list new-line\br -\terminal{\# define} identifier lparen \terminal{...} \terminal{)} replacement-list new-line\br -\terminal{\# define} identifier lparen identifier-list \terminal{, ...} \terminal{)} replacement-list new-line -\end{ncsimplebnf} -defines a \defnadj{function-like}{macro} -with parameters, whose use is -similar syntactically to a function call. -The parameters -\indextext{parameter!macro}% -are specified by the optional list of identifiers. -Each subsequent instance of the function-like macro name followed by a -\tcode{(} -as the next preprocessing token -introduces the sequence of preprocessing tokens that is replaced -by the replacement list in the definition -(an invocation of the macro). -\indextext{invocation!macro}% -The replaced sequence of preprocessing tokens is terminated by the matching -\tcode{)} -preprocessing token, skipping intervening matched pairs of left and -right parenthesis preprocessing tokens. -Within the sequence of preprocessing tokens making up an invocation -of a function-like macro, -new-line is considered a normal whitespace character. - -\pnum -\indextext{macro!function-like!arguments}% -The sequence of preprocessing tokens -bounded by the outside-most matching parentheses -forms the list of arguments for the function-like macro. -The individual arguments within the list -are separated by comma preprocessing tokens, -but comma preprocessing tokens between matching -inner parentheses do not separate arguments. -If there are sequences of preprocessing tokens within the list of -arguments that would otherwise act as preprocessing directives, -\begin{footnote} -A \grammarterm{conditionally-supported-directive} is a preprocessing directive regardless of whether the implementation supports it. -\end{footnote} -the behavior is undefined. - -\pnum -\begin{example} -The following defines a function-like -macro whose value is the maximum of its arguments. -It has the disadvantages of evaluating one or the other of its arguments -a second time -(including -\indextext{side effects}% -side effects) -and generating more code than a function if invoked several times. -It also cannot have its address taken, -as it has none. - -\begin{codeblock} -#define max(a, b) ((a) > (b) ? (a) : (b)) -\end{codeblock} - -The parentheses ensure that the arguments and -the resulting expression are bound properly. -\end{example} - -\pnum -\indextext{macro!function-like!arguments}% -If there is a \tcode{...} immediately preceding the \tcode{)} in the -function-like macro -definition, then the trailing arguments (if any), including any separating comma preprocessing -tokens, are merged to form a single item: the \defn{variable arguments}. The number of -arguments so combined is such that, following merger, the number of arguments is -either equal to or -one more than the number of parameters in the macro definition (excluding the -\tcode{...}). - -\rSec2[cpp.subst]{Argument substitution}% -\indextext{macro!argument substitution}% -\indextext{argument substitution|see{macro, argument substitution}}% - -\indextext{__va_opt__@\mname{VA_OPT}}% -\begin{bnf} -\nontermdef{va-opt-replacement}\br - \terminal{\mname{VA_OPT} (} \opt{pp-tokens} \terminal{)} -\end{bnf} - -\pnum -After the arguments for the invocation of a function-like macro have -been identified, argument substitution takes place. -For each parameter in the replacement list that is neither -preceded by a \tcode{\#} or \tcode{\#\#} preprocessing token nor -followed by a \tcode{\#\#} preprocessing token, the preprocessing tokens -naming the parameter are replaced by a token sequence determined as follows: -\begin{itemize} -\item - If the parameter is of the form \grammarterm{va-opt-replacement}, - the replacement preprocessing tokens are the - preprocessing token sequence for the corresponding argument, - as specified below. -\item - Otherwise, the replacement preprocessing tokens are the - preprocessing tokens of corresponding argument after all - macros contained therein have been expanded. The argument's - preprocessing tokens are completely macro replaced before - being substituted as if they formed the rest of the preprocessing - file with no other preprocessing tokens being available. -\end{itemize} -\begin{example} -\begin{codeblock} -#define LPAREN() ( -#define G(Q) 42 -#define F(R, X, ...) __VA_OPT__(G R X) ) -int x = F(LPAREN(), 0, <:-); // replaced by \tcode{int x = 42;} -\end{codeblock} -\end{example} - -\pnum -\indextext{__va_args__@\mname{VA_ARGS}}% -An identifier \mname{VA_ARGS} that occurs in the replacement list -shall be treated as if it were a parameter, and the variable arguments shall form -the preprocessing tokens used to replace it. - -\pnum -\begin{example} -\begin{codeblock} -#define debug(...) fprintf(stderr, @\mname{VA_ARGS}@) -#define showlist(...) puts(#@\mname{VA_ARGS}@) -#define report(test, ...) ((test) ? puts(#test) : printf(@\mname{VA_ARGS}@)) -debug("Flag"); -debug("X = %d\n", x); -showlist(The first, second, and third items.); -report(x>y, "x is %d but y is %d", x, y); -\end{codeblock} -results in -\begin{codeblock} -fprintf(stderr, "Flag"); -fprintf(stderr, "X = %d\n", x); -puts("The first, second, and third items."); -((x>y) ? puts("x>y") : printf("x is %d but y is %d", x, y)); -\end{codeblock} -\end{example} - -\pnum -\indextext{__va_opt__@\mname{VA_OPT}}% -The identifier \mname{VA_OPT} -shall always occur as part of the preprocessing token sequence -\grammarterm{va-opt-replacement}; -its closing \tcode{)} is determined by skipping -intervening pairs of matching left and right parentheses -in its \grammarterm{pp-tokens}. -The \grammarterm{pp-tokens} of a \grammarterm{va-opt-replacement} -shall not contain \mname{VA_OPT}. -If the \grammarterm{pp-tokens} would be ill-formed -as the replacement list of the current function-like macro, -the program is ill-formed. -A \grammarterm{va-opt-replacement} is treated as if it were a parameter, -and the preprocessing token sequence for the corresponding -argument is defined as follows. -If the substitution of \mname{VA_ARGS} as neither an operand -of \tcode{\#} nor \tcode{\#\#} consists of no preprocessing tokens, -the argument consists of -a single placemarker preprocessing token\iref{cpp.concat,cpp.rescan}. -Otherwise, the argument consists of -the results of the expansion of the contained \grammarterm{pp-tokens} -as the replacement list of the current function-like macro -before removal of placemarker tokens, rescanning, and further replacement. -\begin{note} -The placemarker tokens are removed before stringization\iref{cpp.stringize}, -and can be removed by rescanning and further replacement\iref{cpp.rescan}. -\end{note} -\begin{example} -\begin{codeblock} -#define F(...) f(0 __VA_OPT__(,) __VA_ARGS__) -#define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__) -#define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ }) -#define EMP - -F(a, b, c) // replaced by \tcode{f(0, a, b, c)} -F() // replaced by \tcode{f(0)} -F(EMP) // replaced by \tcode{f(0)} - -G(a, b, c) // replaced by \tcode{f(0, a, b, c)} -G(a, ) // replaced by \tcode{f(0, a)} -G(a) // replaced by \tcode{f(0, a)} - -SDEF(foo); // replaced by \tcode{S foo;} -SDEF(bar, 1, 2); // replaced by \tcode{S bar = \{ 1, 2 \};} - -#define H1(X, ...) X __VA_OPT__(##) __VA_ARGS__ // error: \tcode{\#\#} may not appear at - // the beginning of a replacement list\iref{cpp.concat} - -#define H2(X, Y, ...) __VA_OPT__(X ## Y,) __VA_ARGS__ -H2(a, b, c, d) // replaced by \tcode{ab, c, d} - -#define H3(X, ...) #__VA_OPT__(X##X X##X) -H3(, 0) // replaced by \tcode{""} - -#define H4(X, ...) __VA_OPT__(a X ## X) ## b -H4(, 1) // replaced by \tcode{a b} - -#define H5A(...) __VA_OPT__()@\tcode{/**/}@__VA_OPT__() -#define H5B(X) a ## X ## b -#define H5C(X) H5B(X) -H5C(H5A()) // replaced by \tcode{ab} -\end{codeblock} -\end{example} - -\rSec2[cpp.stringize]{The \tcode{\#} operator}% -\indextext{\#\#0 operator@\tcode{\#} operator}% -\indextext{stringize|see{\tcode{\#} operator}} - -\pnum -Each -\tcode{\#} -preprocessing token in the replacement list for a function-like -macro shall be followed by a parameter as the next preprocessing -token in the replacement list. - -\pnum -A \defn{character string literal} is a \grammarterm{string-literal} with no prefix. -If, in the replacement list, a parameter is immediately -preceded by a -\tcode{\#} -preprocessing token, -both are replaced by a single character string literal preprocessing token that -contains the spelling of the preprocessing token sequence for the -corresponding argument (excluding placemarker tokens). -Let the \defn{stringizing argument} be the preprocessing token sequence -for the corresponding argument with placemarker tokens removed. -Each occurrence of whitespace between the stringizing argument's preprocessing -tokens becomes a single space character in the character string literal. -Whitespace before the first preprocessing token and after the last -preprocessing token comprising the stringizing argument is deleted. -Otherwise, the original spelling of each preprocessing token in the -stringizing argument is retained in the character string literal, -except for special handling for producing the spelling of -\grammarterm{string-literal}s and \grammarterm{character-literal}s: -a -\tcode{\textbackslash} -character is inserted before each -\tcode{"} -and -\tcode{\textbackslash} -character of a \grammarterm{character-literal} or \grammarterm{string-literal} -(including the delimiting -\tcode{"} -characters). -If the replacement that results is not a valid character string literal, -the behavior is undefined. The character string literal corresponding to -an empty stringizing argument is \tcode{""}. -The order of evaluation of -\tcode{\#} -and -\tcode{\#\#} -operators is unspecified. - -\rSec2[cpp.concat]{The \tcode{\#\#} operator}% -\indextext{\#\#1 operator@\tcode{\#\#} operator}% -\indextext{concatenation!macro argument|see{\tcode{\#\#} operator}} - -\pnum -A -\tcode{\#\#} -preprocessing token shall not occur at the beginning or -at the end of a replacement list for either form -of macro definition. - -\pnum -If, in the replacement list of a function-like macro, a parameter is -immediately preceded or followed by a -\tcode{\#\#} -preprocessing token, the parameter is replaced by the -corresponding argument's preprocessing token sequence; however, if an argument consists of no preprocessing tokens, the parameter is -replaced by a placemarker preprocessing token instead. -\begin{footnote} -Placemarker preprocessing tokens do not appear in the syntax -because they are temporary entities that exist only within translation phase 4. -\end{footnote} - -\pnum -For both object-like and function-like macro invocations, before the -replacement list is reexamined for more macro names to replace, -each instance of a -\tcode{\#\#} -preprocessing token in the replacement list -(not from an argument) is deleted and the -preceding preprocessing token is concatenated -with the following preprocessing token. -Placemarker preprocessing tokens are handled specially: concatenation -of two placemarkers results in a single placemarker preprocessing token, and -concatenation of a placemarker with a non-placemarker preprocessing token results -in the non-placemarker preprocessing token. -\begin{note} -Concatenation can form -a \grammarterm{universal-character-name}\iref{lex.charset}. -\end{note} -If the result is not a valid preprocessing token, -the behavior is undefined. -The resulting token is available for further macro replacement. -The order of evaluation of -\tcode{\#\#} -operators is unspecified. - -\pnum -\begin{example} -The sequence -\begin{codeblock} -#define str(s) # s -#define xstr(s) str(s) -#define debug(s, t) printf("x" # s "= %d, x" # t "= %s", @\textbackslash@ - x ## s, x ## t) -#define INCFILE(n) vers ## n -#define glue(a, b) a ## b -#define xglue(a, b) glue(a, b) -#define HIGHLOW "hello" -#define LOW LOW ", world" - -debug(1, 2); -fputs(str(strncmp("abc@\textbackslash@0d", "abc", '@\textbackslash@4') // this goes away - == 0) str(: @\atsign\textbackslash@n), s); -#include xstr(INCFILE(2).h) -glue(HIGH, LOW); -xglue(HIGH, LOW) -\end{codeblock} -results in -\begin{codeblock} -printf("x" "1" "= %d, x" "2" "= %s", x1, x2); -fputs("strncmp(@\textbackslash@"abc@\textbackslash\textbackslash@0d@\textbackslash@", @\textbackslash@"abc@\textbackslash@", '@\textbackslash\textbackslash@4') == 0" ": @\atsign\textbackslash@n", s); -#include "vers2.h" @\textrm{(\textit{after macro replacement, before file access})}@ -"hello"; -"hello" ", world" -\end{codeblock} -or, after concatenation of the character string literals, -\begin{codeblock} -printf("x1= %d, x2= %s", x1, x2); -fputs("strncmp(@\textbackslash@"abc@\textbackslash\textbackslash@0d@\textbackslash@", @\textbackslash@"abc@\textbackslash@", '@\textbackslash\textbackslash@4') == 0: @\atsign\textbackslash@n", s); -#include "vers2.h" @\textrm{(\textit{after macro replacement, before file access})}@ -"hello"; -"hello, world" -\end{codeblock} - -Space around the \tcode{\#} and \tcode{\#\#} tokens in the macro definition -is optional. -\end{example} - -\pnum -\begin{example} -In the following fragment: - -\begin{codeblock} -#define hash_hash # ## # -#define mkstr(a) # a -#define in_between(a) mkstr(a) -#define join(c, d) in_between(c hash_hash d) -char p[] = join(x, y); // equivalent to \tcode{char p[] = "x \#\# y";} -\end{codeblock} - -The expansion produces, at various stages: - -\begin{codeblock} -join(x, y) -in_between(x hash_hash y) -in_between(x ## y) -mkstr(x ## y) -"x ## y" -\end{codeblock} - -In other words, expanding \tcode{hash_hash} produces a new token, -consisting of two adjacent sharp signs, but this new token is not the -\tcode{\#\#} operator. -\end{example} - -\pnum -\begin{example} -To illustrate the rules for placemarker preprocessing tokens, the sequence -\begin{codeblock} -#define t(x,y,z) x ## y ## z -int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), - t(10,,), t(,11,), t(,,12), t(,,) }; -\end{codeblock} -results in -\begin{codeblock} -int j[] = { 123, 45, 67, 89, - 10, 11, 12, }; -\end{codeblock} -\end{example} - -\rSec2[cpp.rescan]{Rescanning and further replacement}% -\indextext{macro!rescanning and replacement}% -\indextext{rescanning and replacement|see{macro, rescanning and replacement}} - -\pnum -After all parameters in the replacement list have been substituted and \tcode{\#} and \tcode{\#\#} processing has taken -place, all placemarker preprocessing tokens are removed. Then -the resulting preprocessing token sequence is rescanned, along with all -subsequent preprocessing tokens of the source file, for more macro names -to replace. - -\pnum -\begin{example} -The sequence -\begin{codeblock} -#define x 3 -#define f(a) f(x * (a)) -#undef x -#define x 2 -#define g f -#define z z[0] -#define h g(~ -#define m(a) a(w) -#define w 0,1 -#define t(a) a -#define p() int -#define q(x) x -#define r(x,y) x ## y -#define str(x) # x - -f(y+1) + f(f(z)) % t(t(g)(0) + t)(1); -g(x+(3,4)-w) | h 5) & m - (f)^m(m); -p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) }; -char c[2][6] = { str(hello), str() }; -\end{codeblock} -results in -\begin{codeblock} -f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); -f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); -int i[] = { 1, 23, 4, 5, }; -char c[2][6] = { "hello", "" }; -\end{codeblock} -\end{example} - -\pnum -If the name of the macro being replaced is found during this scan of -the replacement list -(not including the rest of the source file's preprocessing tokens), -it is not replaced. -Furthermore, -if any nested replacements encounter the name of the macro being replaced, -it is not replaced. -These nonreplaced macro name preprocessing tokens are no longer available -for further replacement even if they are later (re)examined in contexts -in which that macro name preprocessing token would otherwise have been -replaced. - -\pnum -The resulting completely macro-replaced preprocessing token sequence -is not processed as a preprocessing directive even if it resembles one, -but all pragma unary operator expressions within it are then processed as -specified in~\ref{cpp.pragma.op} below. - -\rSec2[cpp.scope]{Scope of macro definitions}% -\indextext{macro!scope of definition}% -\indextext{scope!macro definition|see{macro, scope of definition}} - -\pnum -A macro definition lasts -(independent of block structure) -until a corresponding -\tcode{\#undef} -directive is encountered or -(if none is encountered) -until the end of the translation unit. -Macro definitions have no significance after translation phase 4. - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# undef} identifier new-line -\indextext{\idxcode{\#undef}}% -\end{ncsimplebnf} -causes the specified identifier no longer to be defined as a macro name. -It is ignored if the specified identifier is not currently defined as -a macro name. - -\indextext{macro!replacement|)} - -\rSec1[cpp.line]{Line control}% -\indextext{preprocessing directive!line control}% -\indextext{\idxcode{\#line}|see{preprocessing directive, line control}} - -\pnum -The \grammarterm{string-literal} of a -\tcode{\#line} -directive, if present, -shall be a character string literal. - -\pnum -The -\defn{line number} -of the current source line is one greater than -the number of new-line characters read or introduced -in translation phase 1\iref{lex.phases} -while processing the source file to the current token. - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# line} digit-sequence new-line -\end{ncsimplebnf} -causes the implementation to behave as if -the following sequence of source lines begins with a -source line that has a line number as specified -by the digit sequence (interpreted as a decimal integer). -If the digit sequence specifies zero -or a number greater than 2147483647, -the behavior is undefined. - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# line} digit-sequence \terminal{"} \opt{s-char-sequence} \terminal{"} new-line -\end{ncsimplebnf} -sets the presumed line number similarly and changes the -presumed name of the source file to be the contents -of the character string literal. - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# line} pp-tokens new-line -\end{ncsimplebnf} -(that does not match one of the two previous forms) -is permitted. -The preprocessing tokens after -\tcode{line} -on the directive are processed just as in normal text -(each identifier currently defined as a macro name is replaced by its -replacement list of preprocessing tokens). -If the directive resulting after all replacements does not match -one of the two previous forms, the behavior is undefined; -otherwise, the result is processed as appropriate. - -\rSec1[cpp.error]{Diagnostic directives}% -\indextext{preprocessing directive!error}% -\indextext{preprocessing directive!diagnostic}% -\indextext{preprocessing directive!warning}% -\indextext{\idxcode{\#error}|see{preprocessing directive, error}} - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# error} \opt{pp-tokens} new-line -\end{ncsimplebnf} -renders the program ill-formed. -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# warning} \opt{pp-tokens} new-line -\end{ncsimplebnf} -requires the implementation to produce at least one diagnostic message -for the preprocessing translation unit\iref{intro.compliance.general}. -\recommended -Any diagnostic message caused by either of these directives -should include the specified sequence of preprocessing tokens. - -\rSec1[cpp.pragma]{Pragma directive}% -\indextext{preprocessing directive!pragma}% -\indextext{\idxcode{\#pragma}|see{preprocessing directive, pragma}} - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# pragma} \opt{pp-tokens} new-line -\end{ncsimplebnf} -causes the implementation to behave -in an \impldef{\tcode{\#pragma}} manner. -The behavior may cause translation to fail or cause the translator or -the resulting program to behave in a non-conforming manner. -Any pragma that is not recognized by the implementation is ignored. - -\rSec1[cpp.null]{Null directive}% -\indextext{preprocessing directive!null} - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\#} new-line -\end{ncsimplebnf} -has no effect. - -\rSec1[cpp.predefined]{Predefined macro names} -\indextext{macro!predefined}% -\indextext{name!predefined macro|see{macro, predefined}} - -\pnum -The following macro names shall be defined by the implementation: - -\begin{description} - -\item -\indextext{\idxxname{cplusplus}}% -\xname{cplusplus}\\ -The integer literal \tcode{\cppver}. -\begin{note} -Future revisions of this document will -replace the value of this macro with a greater value. -\end{note} - -\item The names listed in \tref{cpp.predefined.ft}.\\ -The macros defined in \tref{cpp.predefined.ft} shall be defined to -the corresponding integer literal. -\begin{note} -Future revisions of this document might replace -the values of these macros with greater values. -\end{note} - -\item -\indextext{__date__@\mname{DATE}}% -\mname{DATE}\\ -The date of translation of the source file: -a character string literal of the form -\tcode{"Mmm~dd~yyyy"}, -where the names of the months are the same as those generated -by the -\tcode{asctime} -function, -and the first character of -\tcode{dd} -is a space character if the value is less than 10. -If the date of translation is not available, -an \impldef{text of \mname{DATE} when date of translation is not available} valid date -shall be supplied. - -\item -\indextext{__file__@\mname{FILE}}% -\mname{FILE}\\ -The presumed name of the current source file (a character string -literal). -\begin{footnote} -The presumed source file name can be changed by the \tcode{\#line} directive. -\end{footnote} - -\item -\indextext{__line__@\mname{LINE}}% -\mname{LINE}\\ -The presumed line number (within the current source file) of the current source line -(an integer literal). -\begin{footnote} -The presumed line number can be changed by the \tcode{\#line} directive. -\end{footnote} - -\item -\indextext{__stdc_hosted__@\mname{STDC_HOSTED}}% -\indextext{implementation!hosted}% -\indextext{implementation!freestanding}% -\mname{STDC_HOSTED}\\ -The integer literal \tcode{1} -if the implementation is a hosted implementation or -the integer literal \tcode{0} -if it is a freestanding implementation\iref{intro.compliance}. - -\item -\indextext{__stdcpp_default_new_alignment__@\mname{STDCPP_DEFAULT_NEW_ALIGNMENT}}% -\mname{STDCPP_DEFAULT_NEW_ALIGNMENT}\\ -An integer literal of type \tcode{std::size_t} -whose value is the alignment guaranteed -by a call to \tcode{operator new(std::size_t)} -or \tcode{operator new[](std::size_t)}. -\begin{note} -Larger alignments will be passed to -\tcode{operator new(std::size_t, std::align_val_t)}, etc.\iref{expr.new}. -\end{note} - -\item -\indextext{__stdcpp_float16_t__@\mname{STDCPP_FLOAT16_T}}% -\mname{STDCPP_FLOAT16_T}\\ -Defined as the integer literal \tcode{1} -if and only if the implementation supports -the \IsoFloatUndated{} floating-point interchange format binary16 -as an extended floating-point type\iref{basic.extended.fp}. - -\item -\indextext{__stdcpp_float32_t__@\mname{STDCPP_FLOAT32_T}}% -\mname{STDCPP_FLOAT32_T}\\ -Defined as the integer literal \tcode{1} -if and only if the implementation supports -the \IsoFloatUndated{} floating-point interchange format binary32 -as an extended floating-point type. - -\item -\indextext{__stdcpp_float64_t__@\mname{STDCPP_FLOAT64_T}}% -\mname{STDCPP_FLOAT64_T}\\ -Defined as the integer literal \tcode{1} -if and only if the implementation supports -the \IsoFloatUndated{} floating-point interchange format binary64 -as an extended floating-point type. - -\item -\indextext{__stdcpp_float128_t__@\mname{STDCPP_FLOAT128_T}}% -\mname{STDCPP_FLOAT128_T}\\ -Defined as the integer literal \tcode{1} -if and only if the implementation supports -the \IsoFloatUndated{} floating-point interchange format binary128 -as an extended floating-point type. - -\item -\indextext{__stdcpp_bfloat16_t__@\mname{STDCPP_BFLOAT16_T}}% -\mname{STDCPP_BFLOAT16_T}\\ -Defined as the integer literal \tcode{1} -if and only if the implementation supports an extended floating-point type -with the properties of the \grammarterm{typedef-name} \tcode{std::bfloat16_t} -as described in \ref{basic.extended.fp}. - -\item -\indextext{__time__@\mname{TIME}}% -\mname{TIME}\\ -The time of translation of the source file: -a character string literal of the form -\tcode{"hh:mm:ss"} -as in the time generated by the -\tcode{asctime} -function. -If the time of translation is not available, -an \impldef{text of \mname{TIME} when time of translation is not available} valid time shall be supplied. -\end{description} - -\indextext{macro!feature-test}% -\indextext{feature-test macro|see{macro, feature-test}}% -\begin{LongTable}{Feature-test macros}{cpp.predefined.ft}{ll} -\\ \topline -\lhdr{Macro name} & \rhdr{Value} \\ \capsep -\endfirsthead -\continuedcaption \\ -\hline -\lhdr{Name} & \rhdr{Value} \\ \capsep -\endhead -\defnxname{cpp_aggregate_bases} & \tcode{201603L} \\ \rowsep -\defnxname{cpp_aggregate_nsdmi} & \tcode{201304L} \\ \rowsep -\defnxname{cpp_aggregate_paren_init} & \tcode{201902L} \\ \rowsep -\defnxname{cpp_alias_templates} & \tcode{200704L} \\ \rowsep -\defnxname{cpp_aligned_new} & \tcode{201606L} \\ \rowsep -\defnxname{cpp_attributes} & \tcode{200809L} \\ \rowsep -\defnxname{cpp_auto_cast} & \tcode{202110L} \\ \rowsep -\defnxname{cpp_binary_literals} & \tcode{201304L} \\ \rowsep -\defnxname{cpp_capture_star_this} & \tcode{201603L} \\ \rowsep -\defnxname{cpp_char8_t} & \tcode{202207L} \\ \rowsep -\defnxname{cpp_concepts} & \tcode{202002L} \\ \rowsep -\defnxname{cpp_conditional_explicit} & \tcode{201806L} \\ \rowsep -\defnxname{cpp_constexpr} & \tcode{202406L} \\ \rowsep -\defnxname{cpp_constexpr_dynamic_alloc} & \tcode{201907L} \\ \rowsep -\defnxname{cpp_constexpr_in_decltype} & \tcode{201711L} \\ \rowsep -\defnxname{cpp_consteval} & \tcode{202211L} \\ \rowsep -\defnxname{cpp_constinit} & \tcode{201907L} \\ \rowsep -\defnxname{cpp_decltype} & \tcode{200707L} \\ \rowsep -\defnxname{cpp_decltype_auto} & \tcode{201304L} \\ \rowsep -\defnxname{cpp_deduction_guides} & \tcode{201907L} \\ \rowsep -\defnxname{cpp_delegating_constructors} & \tcode{200604L} \\ \rowsep -\defnxname{cpp_deleted_function} & \tcode{202403L} \\ \rowsep -\defnxname{cpp_designated_initializers} & \tcode{201707L} \\ \rowsep -\defnxname{cpp_enumerator_attributes} & \tcode{201411L} \\ \rowsep -\defnxname{cpp_explicit_this_parameter} & \tcode{202110L} \\ \rowsep -\defnxname{cpp_fold_expressions} & \tcode{201603L} \\ \rowsep -\defnxname{cpp_generic_lambdas} & \tcode{201707L} \\ \rowsep -\defnxname{cpp_guaranteed_copy_elision} & \tcode{201606L} \\ \rowsep -\defnxname{cpp_hex_float} & \tcode{201603L} \\ \rowsep -\defnxname{cpp_if_consteval} & \tcode{202106L} \\ \rowsep -\defnxname{cpp_if_constexpr} & \tcode{201606L} \\ \rowsep -\defnxname{cpp_impl_coroutine} & \tcode{201902L} \\ \rowsep -\defnxname{cpp_impl_destroying_delete} & \tcode{201806L} \\ \rowsep -\defnxname{cpp_impl_three_way_comparison} & \tcode{201907L} \\ \rowsep -\defnxname{cpp_implicit_move} & \tcode{202207L} \\ \rowsep -\defnxname{cpp_inheriting_constructors} & \tcode{201511L} \\ \rowsep -\defnxname{cpp_init_captures} & \tcode{201803L} \\ \rowsep -\defnxname{cpp_initializer_lists} & \tcode{200806L} \\ \rowsep -\defnxname{cpp_inline_variables} & \tcode{201606L} \\ \rowsep -\defnxname{cpp_lambdas} & \tcode{200907L} \\ \rowsep -\defnxname{cpp_modules} & \tcode{201907L} \\ \rowsep -\defnxname{cpp_multidimensional_subscript} & \tcode{202211L} \\ \rowsep -\defnxname{cpp_named_character_escapes} & \tcode{202207L} \\ \rowsep -\defnxname{cpp_namespace_attributes} & \tcode{201411L} \\ \rowsep -\defnxname{cpp_noexcept_function_type} & \tcode{201510L} \\ \rowsep -\defnxname{cpp_nontype_template_args} & \tcode{201911L} \\ \rowsep -\defnxname{cpp_nontype_template_parameter_auto} & \tcode{201606L} \\ \rowsep -\defnxname{cpp_nsdmi} & \tcode{200809L} \\ \rowsep -\defnxname{cpp_pack_indexing} & \tcode{202311L} \\ \rowsep -\defnxname{cpp_placeholder_variables} & \tcode{202306L} \\ \rowsep -\defnxname{cpp_range_based_for} & \tcode{202211L} \\ \rowsep -\defnxname{cpp_raw_strings} & \tcode{200710L} \\ \rowsep -\defnxname{cpp_ref_qualifiers} & \tcode{200710L} \\ \rowsep -\defnxname{cpp_return_type_deduction} & \tcode{201304L} \\ \rowsep -\defnxname{cpp_rvalue_references} & \tcode{200610L} \\ \rowsep -\defnxname{cpp_size_t_suffix} & \tcode{202011L} \\ \rowsep -\defnxname{cpp_sized_deallocation} & \tcode{201309L} \\ \rowsep -\defnxname{cpp_static_assert} & \tcode{202306L} \\ \rowsep -\defnxname{cpp_static_call_operator} & \tcode{202207L} \\ \rowsep -\defnxname{cpp_structured_bindings} & \tcode{202403L} \\ \rowsep -\defnxname{cpp_template_template_args} & \tcode{201611L} \\ \rowsep -\defnxname{cpp_threadsafe_static_init} & \tcode{200806L} \\ \rowsep -\defnxname{cpp_unicode_characters} & \tcode{200704L} \\ \rowsep -\defnxname{cpp_unicode_literals} & \tcode{200710L} \\ \rowsep -\defnxname{cpp_user_defined_literals} & \tcode{200809L} \\ \rowsep -\defnxname{cpp_using_enum} & \tcode{201907L} \\ \rowsep -\defnxname{cpp_variable_templates} & \tcode{201304L} \\ \rowsep -\defnxname{cpp_variadic_friend} & \tcode{202403L} \\ \rowsep -\defnxname{cpp_variadic_templates} & \tcode{200704L} \\ \rowsep -\defnxname{cpp_variadic_using} & \tcode{201611L} \\ -\end{LongTable} - -\pnum -The following macro names are conditionally defined by the implementation: - -\begin{description} -\item -\indextext{__stdc__@\mname{STDC}}% -\mname{STDC}\\ -Whether \mname{STDC} is predefined and if so, what its value is, -are \impldef{definition and meaning of \mname{STDC}}. - -\item -\indextext{__stdc_mb_might_neq_wc__@\mname{STDC_MB_MIGHT_NEQ_WC}}% -\mname{STDC_MB_MIGHT_NEQ_WC}\\ -The integer literal \tcode{1}, intended to indicate that, in the encoding for -\keyword{wchar_t}, a member of the basic character set need not have a code value equal to -its value when used as the lone character in an ordinary character literal. - -\item -\indextext{__stdc_version__@\mname{STDC_VERSION}}% -\mname{STDC_VERSION}\\ -Whether \mname{STDC_VERSION} is predefined and if so, what its value is, -are \impldef{definition and meaning of \mname{STDC_VERSION}}. - -\item -\indextext{__stdc_iso_10646__@\mname{STDC_ISO_10646}}% -\mname{STDC_ISO_10646}\\ -An integer literal of the form \tcode{yyyymmL} -(for example, \tcode{199712L}). -Whether \mname{STDC_ISO_10646} is predefined and -if so, what its value is, -are \impldef{presence and value of \mname{STDC_ISO_10646}}. - -\item -\indextext{__stdcpp_threads__@\mname{STDCPP_THREADS}}% -\mname{STDCPP_THREADS}\\ -Defined, and has the value integer literal 1, if and only if a program -can have more than one thread of execution\iref{intro.multithread}. - -\end{description} - -\pnum -The values of the predefined macros -(except for -\mname{FILE} -and -\mname{LINE}) -remain constant throughout the translation unit. - -\pnum -If any of the pre-defined macro names in this subclause, -or the identifier -\tcode{defined}, -is the subject of a -\tcode{\#define} -or a -\tcode{\#undef} -preprocessing directive, -the behavior is undefined. -Any other predefined macro names shall begin with a -leading underscore followed by an uppercase letter or a second -underscore. - -\rSec1[cpp.pragma.op]{Pragma operator}% -\indextext{macro!pragma operator}% -\indextext{operator!pragma|see{macro, pragma operator}} - -\pnum -A unary operator expression of the form: -\begin{ncbnf} -\terminal{_Pragma} \terminal{(} string-literal \terminal{)} -\end{ncbnf} -is processed as follows: The \grammarterm{string-literal} is \defnx{destringized}{destringization} -by deleting the \tcode{L} prefix, if present, deleting the leading and trailing -double-quotes, replacing each escape sequence \tcode{\textbackslash"} by a double-quote, and -replacing each escape sequence \tcode{\textbackslash\textbackslash} by a single -backslash. The resulting sequence of characters is processed through translation phase 3 -to produce preprocessing tokens that are executed as if they were the -\grammarterm{pp-tokens} in a pragma directive. The original four preprocessing -tokens in the unary operator expression are removed. - -\pnum -\begin{example} -\begin{codeblock} -#pragma listing on "..\listing.dir" -\end{codeblock} -can also be expressed as: -\begin{codeblock} -_Pragma ( "listing on \"..\\listing.dir\"" ) -\end{codeblock} -The latter form is processed in the same way whether it appears literally -as shown, or results from macro replacement, as in: -\begin{codeblock} -#define LISTING(x) PRAGMA(listing on #x) -#define PRAGMA(x) _Pragma(#x) - -LISTING( ..\listing.dir ) -\end{codeblock} -\end{example} -\indextext{preprocessing directive|)} diff --git a/source/std.tex b/source/std.tex index 373c487476..7b5f3358b5 100644 --- a/source/std.tex +++ b/source/std.tex @@ -112,7 +112,6 @@ \include{intro} \include{lex} -\include{preprocessor} \include{modules} \include{basic} \include{expressions} diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index 2fe56a4680..1aba8e649d 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -101,6 +101,7 @@ % Lexing reorganization \movedxref{lex.digraph}{lex.operators} +\movedxref{gram.basic}{gram.module} %%% Deprecated features. %%% Example: From 6b4fb148830d28972f9c0b83c4b2477eebf2302f Mon Sep 17 00:00:00 2001 From: Alisdair Meredith Date: Mon, 30 Sep 2024 13:57:47 -0400 Subject: [PATCH 13/18] Move names, linkage, and program execution into [lex] This completes the large-scale reorganization to move the text corresponding to the phases of translation for constructing programs into the same clause. Names and linkage correspond closely to phase 8, while program execution is the essence of phase 9. The [basic] clause has been rearranged to reflect the new structure. --- source/basic.tex | 10681 ++++++++++++++++----------------------- source/expressions.tex | 4 +- source/lex.tex | 1893 +++++++ source/xrefdelta.tex | 4 +- 4 files changed, 6292 insertions(+), 6290 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 20aff54707..bd97d83581 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -24,7156 +24,5263 @@ Clauses. \end{note} -\pnum -\indextext{type}% -\indextext{object}% -\indextext{storage class}% -\indextext{scope}% -\indextext{linkage}% -A \defn{name} is an \grammarterm{identifier}\iref{lex.name}, -\grammarterm{operator-function-id}\iref{over.oper}, -\grammarterm{literal-operator-id}\iref{over.literal}, or -\grammarterm{conversion-function-id}\iref{class.conv.fct}. +\rSec1[basic.memobj]{Memory and objects} + +\rSec2[intro.memory]{Memory model} \pnum -Two names are \defnx{the same}{name!same} if -\begin{itemize} -\item they are \grammarterm{identifier}{s} composed of the same character sequence, or -\item they are \grammarterm{operator-function-id}{s} formed with the same operator, or -\item they are \grammarterm{literal-operator-id}{s} formed with the same -literal suffix identifier, or -\item they are \grammarterm{conversion-function-id}{s} formed with -equivalent\iref{temp.over.link} types. -\end{itemize} +\indextext{memory model|(}% +The fundamental storage unit in the \Cpp{} memory model is the +\defn{byte}. +A byte is at least large enough to contain +the ordinary literal encoding of any element of the basic +\indextext{character set!basic literal}% +literal character set\iref{lex.charset} +and the eight-bit code units of the Unicode +\indextext{UTF-8}% +UTF-8 encoding form +and is composed of a contiguous sequence of +bits, +\begin{footnote} +The number of bits in a byte is reported by the macro +\tcode{CHAR_BIT} in the header \libheaderref{climits}. +\end{footnote} +the number of which is \impldef{bits in a byte}. The least +significant bit is called the \defn{low-order bit}; the most +significant bit is called the \defn{high-order bit}. The memory +available to a \Cpp{} program consists of one or more sequences of +contiguous bytes. Every byte has a unique address. \pnum -Every name is introduced by a \defn{declaration}, which is a -\begin{itemize} -\item -\grammarterm{name-declaration}, -\grammarterm{block-declaration}, or -\grammarterm{member-declaration}\iref{dcl.pre,class.mem}, -\item -\grammarterm{init-declarator}\iref{dcl.decl}, -\item -\grammarterm{identifier} -in a structured binding declaration\iref{dcl.struct.bind}, -\item -\grammarterm{init-capture}\iref{expr.prim.lambda.capture}, -\item -\grammarterm{condition} with a \grammarterm{declarator}\iref{stmt.pre}, -\item -\grammarterm{member-declarator}\iref{class.mem}, -\item -\grammarterm{using-declarator}\iref{namespace.udecl}, -\item -\grammarterm{parameter-declaration}\iref{dcl.fct}, -\item -\grammarterm{type-parameter}\iref{temp.param}, -\item -\grammarterm{elaborated-type-specifier} -that introduces a name\iref{dcl.type.elab}, -\item -\grammarterm{class-specifier}\iref{class.pre}, -\item -\grammarterm{enum-specifier} or -\grammarterm{enumerator-definition}\iref{dcl.enum}, -\item -\grammarterm{exception-declaration}\iref{except.pre}, or -\item -implicit declaration of an injected-class-name\iref{class.pre}. -\end{itemize} \begin{note} -The interpretation of a \grammarterm{for-range-declaration} produces -one or more of the above\iref{stmt.ranged}. +The representation of types is described +in~\ref{basic.types.general}. \end{note} \pnum -Some names denote types or templates. In general, whenever a name is -encountered it is necessary to determine whether that name denotes one of these -entities before continuing to parse the program that contains it. The process -that determines this is called -\defnx{name lookup}{lookup!name}\iref{basic.lookup}. +A \defn{memory location} is either an object of scalar type that is not a bit-field +or a maximal sequence of adjacent bit-fields all having nonzero width. +\begin{note} +Various +features of the language, such as references and virtual functions, might +involve additional memory locations that are not accessible to programs but are +managed by the implementation. +\end{note} +Two or more threads of +execution\iref{intro.multithread} can access separate memory +locations without interfering with each other. \pnum -A \defn{variable} is introduced by the -declaration of -a reference other than a non-static data member or of -an object. The variable's name, if any, denotes the reference or object. +\begin{note} +Thus a bit-field and an adjacent non-bit-field are in separate memory +locations, and therefore can be concurrently updated by two threads of execution +without interference. The same applies to two bit-fields, if one is declared +inside a nested struct declaration and the other is not, or if the two are +separated by a zero-length bit-field declaration, or if they are separated by a +non-bit-field declaration. It is not safe to concurrently update two bit-fields +in the same struct if all fields between them are also bit-fields of nonzero +width. +\end{note} \pnum -An \defn{entity} is a value, object, reference, structured binding, function, -enumerator, type, class member, bit-field, template, template specialization, -namespace, or pack. An entity $E$ is denoted by the name (if any) that is -introduced by a declaration of $E$ or by a \grammarterm{typedef-name} -introduced by a declaration specifying $E$. +\begin{example} +A class declared as +\begin{codeblock} +struct { + char a; + int b:5, + c:11, + :0, + d:8; + struct {int ee:8;} e; +}; +\end{codeblock} +contains four separate memory locations: The member \tcode{a} and bit-fields +\tcode{d} and \tcode{e.ee} are each separate memory locations, and can be +modified concurrently without interfering with each other. The bit-fields +\tcode{b} and \tcode{c} together constitute the fourth memory location. The +bit-fields \tcode{b} and \tcode{c} cannot be concurrently modified, but +\tcode{b} and \tcode{a}, for example, can be. +\end{example} +\indextext{memory model|)} -\pnum -A \defnadj{local}{entity} is a variable with -automatic storage duration\iref{basic.stc.auto}, -a structured binding\iref{dcl.struct.bind} -whose corresponding variable is such an entity, -or the \tcode{*\keyword{this}} object\iref{expr.prim.this}. +\rSec2[intro.object]{Object model} \pnum -\indextext{translation unit!name and}% -\indextext{linkage}% -A name used in more than one translation unit can potentially -refer to the same entity in these translation units depending on the -linkage\iref{basic.link} of the name specified in each -translation unit. - -\rSec1[basic.def]{Declarations and definitions} +\indextext{object model|(}% +The constructs in a \Cpp{} program create, destroy, refer to, access, and +manipulate objects. +An \defn{object} is created +by a definition\iref{basic.def}, +by a \grammarterm{new-expression}\iref{expr.new}, +by an operation that implicitly creates objects (see below), +when implicitly changing the active member of a union\iref{class.union}, +or +when a temporary object is created\iref{conv.rval,class.temporary}. +An object occupies a region of storage +in its period of construction\iref{class.cdtor}, +throughout its lifetime\iref{basic.life}, +and +in its period of destruction\iref{class.cdtor}. +\begin{note} +A function is not an object, regardless of whether or not it +occupies storage in the way that objects do. +\end{note} +The properties of an +object are determined when the object is created. An object can have a +name\iref{basic.link}. An object has a storage +duration\iref{basic.stc} which influences its +lifetime\iref{basic.life}. An object has a +type\iref{basic.types}. +\begin{note} +Some objects are +polymorphic\iref{class.virtual}; the implementation +generates information associated with each such object that makes it +possible to determine that object's type during program execution. +\end{note} \pnum -\indextext{declaration!definition versus}% -\indextext{declaration}% -\indextext{declaration!name}% -A declaration\iref{dcl} may (re)introduce -one or more names and/or entities into a translation -unit. -If so, the -declaration specifies the interpretation and semantic properties of these names. -A declaration of an entity or \grammarterm{typedef-name} $X$ is -a redeclaration of $X$ -if another declaration of $X$ is reachable from it\iref{module.reach}. -A declaration may also have effects including: +\indextext{subobject}% +Objects can contain other objects, called \defnx{subobjects}{subobject}. +A subobject can be +a \defn{member subobject}\iref{class.mem}, a \defn{base class subobject}\iref{class.derived}, +or an array element. +\indextext{object!complete}% +An object that is not a subobject of any other object is called a \defn{complete +object}. +If an object is created +in storage associated with a member subobject or array element \placeholder{e} +(which may or may not be within its lifetime), +the created object +is a subobject of \placeholder{e}'s containing object if \begin{itemize} -\item a static assertion\iref{dcl.pre}, -\item controlling template instantiation\iref{temp.explicit}, -\item guiding template argument deduction for constructors\iref{temp.deduct.guide}, -\item use of attributes\iref{dcl.attr}, and -\item nothing (in the case of an \grammarterm{empty-declaration}). +\item +the lifetime of \placeholder{e}'s containing object has begun and not ended, and +\item +the storage for the new object exactly overlays the storage location associated with \placeholder{e}, and +\item +the new object is of the same type as \placeholder{e} (ignoring cv-qualification). \end{itemize} \pnum -\indextext{declaration!function}% -\indextext{definition}% -Each entity declared by a \grammarterm{declaration} is -also \defnx{defined}{define} by that declaration unless: +\indextext{object!providing storage for}% +If a complete object is created\iref{expr.new} +in storage associated with another object \placeholder{e} +of type ``array of $N$ \tcode{\keyword{unsigned} \keyword{char}}'' or +of type ``array of $N$ \tcode{std::byte}''\iref{cstddef.syn}, +that array \defn{provides storage} +for the created object if \begin{itemize} \item -it declares a function -without specifying the function's body\iref{dcl.fct.def}, +the lifetime of \placeholder{e} has begun and not ended, and \item -it contains -the -\indextext{declaration!\idxcode{extern}}% -\keyword{extern} specifier\iref{dcl.stc} or a -\grammarterm{linkage-specification} -\begin{footnote} -Appearing inside the brace-enclosed -\grammarterm{declaration-seq} in a \grammarterm{linkage-specification} does -not affect whether a declaration is a definition. -\end{footnote} -\iref{dcl.link} -and neither an \grammarterm{initializer} nor a -\grammarterm{function-body}, +the storage for the new object fits entirely within \placeholder{e}, and \item -\indextext{declaration!static member@\tcode{static} member}% -it declares a non-inline static data member in a class -definition\iref{class.mem,class.static}, +there is no array object that satisfies these constraints nested within \placeholder{e}. +\end{itemize} +\begin{note} +If that portion of the array +previously provided storage for another object, +the lifetime of that object ends +because its storage was reused\iref{basic.life}. +\end{note} +\begin{example} +\begin{codeblock} +// assumes that \tcode{sizeof(int)} is equal to 4 + +template +struct AlignedUnion { + alignas(T...) unsigned char data[max(sizeof(T)...)]; +}; +int f() { + AlignedUnion au; + int *p = new (au.data) int; // OK, \tcode{au.data} provides storage + char *c = new (au.data) char(); // OK, ends lifetime of \tcode{*p} + char *d = new (au.data + 1) char(); + return *c + *d; // OK +} + +struct A { unsigned char a[32]; }; +struct B { unsigned char b[16]; }; +alignas(int) A a; +B *b = new (a.a + 8) B; // \tcode{a.a} provides storage for \tcode{*b} +int *p = new (b->b + 4) int; // \tcode{b->b} provides storage for \tcode{*p} + // \tcode{a.a} does not provide storage for \tcode{*p} (directly), + // but \tcode{*p} is nested within \tcode{a} (see below) +\end{codeblock} +\end{example} + +\pnum +\indextext{object!nested within}% +An object \placeholder{a} is \defn{nested within} another object \placeholder{b} if +\begin{itemize} \item -it declares a static data member outside a class definition -and the variable was defined within the class with the \keyword{constexpr} -specifier\iref{class.static.data} (this usage is deprecated; see \ref{depr.static.constexpr}), +\placeholder{a} is a subobject of \placeholder{b}, or \item -\indextext{declaration!class name}% -it is an \grammarterm{elaborated-type-specifier}\iref{class.name}, +\placeholder{b} provides storage for \placeholder{a}, or \item -it is an -\indextext{declaration!opaque enum}% -\grammarterm{opaque-enum-declaration}\iref{dcl.enum}, +there exists an object \placeholder{c} +where \placeholder{a} is nested within \placeholder{c}, +and \placeholder{c} is nested within \placeholder{b}. +\end{itemize} + +\pnum +For every object \tcode{x}, there is some object called the +\defn{complete object of} \tcode{x}, determined as follows: +\begin{itemize} \item -it is a -\indextext{parameter!template}\indextext{template parameter}% -\grammarterm{template-parameter}\iref{temp.param}, +If \tcode{x} is a complete object, then the complete object +of \tcode{x} is itself. + \item -it is a -\indextext{declaration!parameter}\indextext{parameter declaration}% -\grammarterm{parameter-declaration}\iref{dcl.fct} in a function -\indextext{declarator}% -declarator that is not the \grammarterm{declarator} of a -\grammarterm{function-definition}, -\item -it is a -\indextext{declaration!\idxcode{typedef}}% -\keyword{typedef} declaration\iref{dcl.typedef}, -\item it is -an \grammarterm{alias-declaration}\iref{dcl.typedef}, -\item it is -a -\grammarterm{using-declaration}\iref{namespace.udecl}, -\item it is -a \grammarterm{deduction-guide}\iref{temp.deduct.guide}, -\item it is -a \grammarterm{static_assert-declaration}\iref{dcl.pre}, -\item -it is an -\grammarterm{attribute-declaration}\iref{dcl.pre}, -\item -it is an -\grammarterm{empty-declaration}\iref{dcl.pre}, -\item it is -a \grammarterm{using-directive}\iref{namespace.udir}, -\item it is -a \grammarterm{using-enum-declaration}\iref{enum.udecl}, -\item it is -a \grammarterm{template-declaration}\iref{temp.pre} -whose \grammarterm{template-head} is not followed by -either a \grammarterm{concept-definition} or a \grammarterm{declaration} -that defines a function, a class, a variable, or a static data member, -\item it is -an explicit instantiation declaration\iref{temp.explicit}, or -\item it is -an explicit specialization\iref{temp.expl.spec} whose -\grammarterm{declaration} is not a definition. +Otherwise, the complete object of \tcode{x} is the complete object +of the (unique) object that contains \tcode{x}. \end{itemize} -A declaration is said to be a \defn{definition} of each entity that it defines. -\begin{example} -All but one of the following are definitions: -\begin{codeblock} -int a; // defines \tcode{a} -extern const int c = 1; // defines \tcode{c} -int f(int x) { return x+a; } // defines \tcode{f} and defines \tcode{x} -struct S { int a; int b; }; // defines \tcode{S}, \tcode{S::a}, and \tcode{S::b} -struct X { // defines \tcode{X} - int x; // defines non-static data member \tcode{x} - static int y; // declares static data member \tcode{y} - X(): x(0) { } // defines a constructor of \tcode{X} -}; -int X::y = 1; // defines \tcode{X::y} -enum { up, down }; // defines \tcode{up} and \tcode{down} -namespace N { int d; } // defines \tcode{N} and \tcode{N::d} -namespace N1 = N; // defines \tcode{N1} -X anX; // defines \tcode{anX} - -\end{codeblock} -whereas these are just declarations: -\begin{codeblock} -extern int a; // declares \tcode{a} -extern const int c; // declares \tcode{c} -int f(int); // declares \tcode{f} -struct S; // declares \tcode{S} -typedef int Int; // declares \tcode{Int} -extern X anotherX; // declares \tcode{anotherX} -using N::d; // declares \tcode{d} -\end{codeblock} -\end{example} - -\pnum -\begin{note} -\indextext{implementation-generated}% -In some circumstances, \Cpp{} implementations implicitly define the -default constructor\iref{class.default.ctor}, -copy constructor, move constructor\iref{class.copy.ctor}, -copy assignment operator, move assignment operator\iref{class.copy.assign}, -or destructor\iref{class.dtor} member functions. -\end{note} -\begin{example} -Given -\begin{codeblock} -#include - -struct C { - std::string s; // \tcode{std::string} is the standard library class\iref{string.classes} -}; - -int main() { - C a; - C b = a; - b = a; -} -\end{codeblock} -the implementation will implicitly define functions to make the -definition of \tcode{C} equivalent to -\begin{codeblock} -struct C { - std::string s; - C() : s() { } - C(const C& x): s(x.s) { } - C(C&& x): s(static_cast(x.s)) { } - @\rlap{\textnormal{\textit{//}}}@ : s(std::move(x.s)) { } - C& operator=(const C& x) { s = x.s; return *this; } - C& operator=(C&& x) { s = static_cast(x.s); return *this; } - @\rlap{\textnormal{\textit{//}}}@ { s = std::move(x.s); return *this; } - ~C() { } -}; -\end{codeblock} -\end{example} \pnum -\begin{note} -A class name can also be implicitly declared by an -\grammarterm{elaborated-type-specifier}\iref{dcl.type.elab}. -\end{note} +If a complete object, a member subobject, or an array element is of +class type, its type is considered the \defn{most derived +class}, to distinguish it from the class type of any base class subobject; +an object of a most derived class type or of a non-class type is called a +\defn{most derived object}. \pnum -\indextext{type!incomplete}% -In the definition of an object, -the type of that object shall not be -an incomplete type\iref{term.incomplete.type}, -an abstract class type\iref{class.abstract}, or -a (possibly multidimensional) array thereof. - -\rSec1[basic.def.odr]{One-definition rule}% -\indextext{object!definition}% -\indextext{function!definition}% -\indextext{class!definition}% -\indextext{enumerator!definition}% -\indextext{one-definition rule|(}% +A \defn{potentially-overlapping subobject} is either: +\begin{itemize} +\item a base class subobject, or +\item a non-static data member +declared with the \tcode{no_unique_address} attribute\iref{dcl.attr.nouniqueaddr}. +\end{itemize} \pnum -Each of the following is termed a \defnadj{definable}{item}: +\indextext{object!zero size}% +\indextext{object!nonzero size}% +An object has nonzero size if it \begin{itemize} -\item a class type\iref{class}, -\item an enumeration type\iref{dcl.enum}, -\item a function\iref{dcl.fct}, -\item a variable\iref{basic.pre}, -\item a templated entity\iref{temp.pre}, -\item a default argument for a parameter -(for a function in a given scope)\iref{dcl.fct.default}, or -\item a default template argument\iref{temp.param}. +\item is not a potentially-overlapping subobject, or +\item is not of class type, or +\item is of a class type with virtual member functions or virtual base classes, or +\item has subobjects of nonzero size or unnamed bit-fields of nonzero length. \end{itemize} +Otherwise, if the object is a base class subobject +of a standard-layout class type +with no non-static data members, +it has zero size. +Otherwise, the circumstances under which the object has zero size +are \impldef{which non-standard-layout objects +containing no data are considered empty}. +\indextext{most derived object!bit-field}% +Unless it is a bit-field\iref{class.bit}, +an object with nonzero size +shall occupy one or more bytes of storage, +including every byte that is occupied in full or in part +by any of its subobjects. +An object of trivially copyable or +standard-layout type\iref{basic.types.general} shall occupy contiguous bytes of +storage. \pnum -No translation unit shall contain more than one definition of any -definable item. +An object is a \defnadj{potentially non-unique}{object} if it is +a string literal object\iref{lex.string}, +the backing array of an initializer list\iref{dcl.init.ref}, or +a subobject thereof. \pnum -\indextext{expression!potentially evaluated}% -An expression or conversion is \defn{potentially evaluated} unless it is -an unevaluated operand\iref{expr.context}, -a subexpression thereof, or -a conversion in an initialization or conversion sequence in such a context. -The set of \defn{potential results} of an expression $E$ is -defined as follows: +\indextext{most derived object!bit-field}% +\indextext{most derived object!zero size subobject}% +Unless an object is a bit-field or a subobject of zero size, the +address of that object is the address of the first byte it occupies. +Two objects +with overlapping lifetimes +that are not bit-fields +may have the same address if \begin{itemize} -\item If $E$ is an -\grammarterm{id-expression}\iref{expr.prim.id}, the set -contains only $E$. -\item If $E$ is a subscripting operation\iref{expr.sub} with -an array operand, the set contains the potential results of that operand. -\item If $E$ is a class member access -expression\iref{expr.ref} of the form -$E_1$ \tcode{.} \opt{\keyword{template}} $E_2$ -naming a non-static data member, -the set contains the potential results of $E_1$. -\item If $E$ is a class member access expression -naming a static data member, -the set contains the \grammarterm{id-expression} designating the data member. -\item If $E$ is a pointer-to-member -expression\iref{expr.mptr.oper} of the form -$E_1$ \tcode{.*} $E_2$, -the set contains the potential results of $E_1$. -\item If $E$ has the form \tcode{($E_1$)}, the set contains the -potential results of $E_1$. -\item If $E$ is a glvalue conditional -expression\iref{expr.cond}, the set is the union of the sets of -potential results of the second and third operands. -\item If $E$ is a comma expression\iref{expr.comma}, the set -contains the potential results of the right operand. -\item Otherwise, the set is empty. +\item one is nested within the other, +\item at least one is a subobject of zero size and they are not of similar types\iref{conv.qual}, +or +\item they are both potentially non-unique objects; \end{itemize} -\begin{note} -This set is a (possibly-empty) set of \grammarterm{id-expression}{s}, -each of which is either $E$ or a subexpression of $E$. +otherwise, they have distinct addresses +and occupy disjoint bytes of storage. +\begin{footnote} +Under the ``as-if'' rule an +implementation is allowed to store two objects at the same machine address or +not store an object at all if the program cannot observe the +difference\iref{intro.execution}. +\end{footnote} \begin{example} -In the following example, the set of potential results of the initializer -of \tcode{n} contains the first \tcode{S::x} subexpression, but not the second -\tcode{S::x} subexpression. \begin{codeblock} -struct S { static const int x = 0; }; -const int &f(const int &r); -int n = b ? (1, S::x) // \tcode{S::x} is not odr-used here - : f(S::x); // \tcode{S::x} is odr-used here, so a definition is required +static const char test1 = 'x'; +static const char test2 = 'x'; +const bool b = &test1 != &test2; // always \tcode{true} + +static const char (&r) [] = "x"; +static const char *s = "x"; +static std::initializer_list il = { 'x' }; +const bool b2 = r != il.begin(); // unspecified result +const bool b3 = r != s; // unspecified result +const bool b4 = il.begin() != &test1; // always \tcode{true} +const bool b5 = r != &test1; // always \tcode{true} \end{codeblock} \end{example} -\end{note} +The address of a non-bit-field subobject of zero size is +the address of an unspecified byte of storage +occupied by the complete object of that subobject. \pnum -A function is \defnx{named by}{function!named by expression or conversion} -an expression or conversion as follows: -\begin{itemize} -\item - A function is named by an expression or conversion - if it is the selected member - of an overload set\iref{basic.lookup,over.match,over.over} - in an overload resolution performed - as part of forming that expression or conversion, - unless it is a pure virtual function and either - the expression is not an \grammarterm{id-expression} naming the function with - an explicitly qualified name or - the expression forms a pointer to member\iref{expr.unary.op}. - \begin{note} -This covers - taking the address of functions\iref{conv.func,expr.unary.op}, - calls to named functions\iref{expr.call}, - operator overloading\iref{over}, - user-defined conversions\iref{class.conv.fct}, - allocation functions for \grammarterm{new-expression}{s}\iref{expr.new}, as well as - non-default initialization\iref{dcl.init}. - A constructor selected to copy or move an object of class type - is considered to be named by an expression or conversion - even if the call is actually elided by the implementation\iref{class.copy.elision}. +Some operations are described as +\defnx{implicitly creating objects}{object!implicit creation} +within a specified region of storage. +For each operation that is specified as implicitly creating objects, +that operation implicitly creates and starts the lifetime of +zero or more objects of implicit-lifetime types\iref{term.implicit.lifetime.type} +in its specified region of storage +if doing so would result in the program having defined behavior. +If no such set of objects would give the program defined behavior, +the behavior of the program is undefined. +If multiple such sets of objects would give the program defined behavior, +it is unspecified which such set of objects is created. +\begin{note} +Such operations do not start the lifetimes of subobjects of such objects +that are not themselves of implicit-lifetime types. \end{note} -\item - A deallocation function for a class - is named by a \grammarterm{new-expression} - if it is the single matching deallocation function - for the allocation function selected by overload resolution, - as specified in~\ref{expr.new}. -\item - A deallocation function for a class - is named by a \grammarterm{delete-expression} - if it is the selected usual deallocation function - as specified in~\ref{expr.delete} and~\ref{class.free}. -\end{itemize} \pnum -\label{term.odr.use}% -A variable is named by an expression -if the expression is an \grammarterm{id-expression} that denotes it. -A variable \tcode{x} that is named by a -potentially-evaluated expression $E$ -is \defnx{odr-used}{odr-use} by $E$ unless -\begin{itemize} -\item - \tcode{x} is a reference that is - usable in constant expressions\iref{expr.const}, or -\item - \tcode{x} is a variable of non-reference type that is - usable in constant expressions and has no mutable subobjects, and - $E$ is an element of the set of potential results of an expression - of non-volatile-qualified non-class type - to which the lvalue-to-rvalue conversion\iref{conv.lval} is applied, or -\item - \tcode{x} is a variable of non-reference type, and - $E$ is an element of the set of potential results - of a discarded-value expression\iref{expr.context} - to which the lvalue-to-rvalue conversion is not applied. -\end{itemize} +Further, after implicitly creating objects within a specified region of storage, +some operations are described as producing a pointer to a +\defnadj{suitable created}{object}. +These operations select one of the implicitly-created objects +whose address is the address of the start of the region of storage, +and produce a pointer value that points to that object, +if that value would result in the program having defined behavior. +If no such pointer value would give the program defined behavior, +the behavior of the program is undefined. +If multiple such pointer values would give the program defined behavior, +it is unspecified which such pointer value is produced. \pnum -A structured binding is odr-used if it appears as a potentially-evaluated expression. +\begin{example} +\begin{codeblock} +#include +struct X { int a, b; }; +X *make_x() { + // The call to \tcode{std::malloc} implicitly creates an object of type \tcode{X} + // and its subobjects \tcode{a} and \tcode{b}, and returns a pointer to that \tcode{X} object + // (or an object that is pointer-interconvertible\iref{basic.compound} with it), + // in order to give the subsequent class member access operations + // defined behavior. + X *p = (X*)std::malloc(sizeof(struct X)); + p->a = 1; + p->b = 2; + return p; +} +\end{codeblock} +\end{example} \pnum -\tcode{*\keyword{this}} is odr-used if \keyword{this} appears as a potentially-evaluated expression -(including as the result of any implicit transformation to -a class member access expression\iref{expr.prim.id.general}). +Except during constant evaluation, +an operation that begins the lifetime of +an array of \tcode{unsigned char} or \tcode{std::byte} +implicitly creates objects within the region of storage occupied by the array. +\begin{note} +The array object provides storage for these objects. +\end{note} +Except during constant evaluation, +any implicit or explicit invocation of a function +named \tcode{\keyword{operator} \keyword{new}} or \tcode{\keyword{operator} \keyword{new}[]} +implicitly creates objects in the returned region of storage and +returns a pointer to a suitable created object. +\begin{note} +Some functions in the \Cpp{} standard library implicitly create objects% +\iref{obj.lifetime,c.malloc,mem.res.public,bit.cast,cstring.syn}. +\end{note} +\indextext{object model|)} -\pnum -A virtual member -function is odr-used if it is not pure. -A function is odr-used if it is named by -a potentially-evaluated expression or conversion. -A non-placement allocation or deallocation -function for a class is odr-used by the definition of a constructor of that -class. A non-placement deallocation function for a class is odr-used by the -definition of the destructor of that class, or by being selected by the -lookup at the point of definition of a virtual -destructor\iref{class.dtor}. -\begin{footnote} -An implementation is not required -to call allocation and -deallocation functions from constructors or destructors; however, this -is a permissible implementation technique. -\end{footnote} +\rSec2[basic.life]{Lifetime} \pnum -An assignment operator function in a class is odr-used by an -implicitly-defined -copy assignment or move assignment function for another class as specified -in~\ref{class.copy.assign}. -A constructor for a class is odr-used as specified -in~\ref{dcl.init}. A destructor for a class is odr-used if it is potentially -invoked\iref{class.dtor}. +In this subclause, ``before'' and ``after'' refer to the ``happens before'' +relation\iref{intro.multithread}. +\begin{note} +Therefore, undefined behavior results +if an object that is being constructed in one thread is referenced from another +thread without adequate synchronization. +\end{note} \pnum -A local entity\iref{basic.pre} -is \defn{odr-usable} in a scope\iref{basic.scope.scope} if -\begin{itemize} -\item either the local entity is not \tcode{*\keyword{this}}, or -an enclosing class or non-lambda function parameter scope exists and, -if the innermost such scope is a function parameter scope, -it corresponds to a non-static member function, and -\item -for each intervening scope\iref{basic.scope.scope} -between the point at which the entity is introduced and the scope -(where \tcode{*\keyword{this}} is considered to be introduced -within the innermost enclosing class or non-lambda function definition scope), -either: +\indextext{object lifetime|(}% +The \defn{lifetime} of an object or reference is a runtime property of the +object or reference. +A variable is said to have \defnadj{vacuous}{initialization} +if it is default-initialized, no other initialization is performed, and, +if it is of class type or a (possibly multidimensional) array thereof, +a trivial constructor of that class type is selected for +the default-initialization. +The lifetime of an object of type \tcode{T} begins when: \begin{itemize} -\item the intervening scope is a block scope, or -\item the intervening scope is the function parameter scope of a \grammarterm{lambda-expression}, or -\item the intervening scope is the lambda scope of -a \grammarterm{lambda-expression} -that has a \grammarterm{simple-capture} -naming the entity or has a \grammarterm{capture-default}, and -the block scope of the \grammarterm{lambda-expression} -is also an intervening scope. +\item storage with the proper alignment and size + for type \tcode{T} is obtained, and +\item its initialization (if any) is complete + (including vacuous initialization)\iref{dcl.init}, \end{itemize} +except that if the object is a union member or subobject thereof, +its lifetime only begins if that union member is the +initialized member in the union\iref{dcl.init.aggr,class.base.init}, +or as described in +\ref{class.union}, \ref{class.copy.ctor}, and \ref{class.copy.assign}, +and except as described in \ref{allocator.members}. +The lifetime of an object \placeholder{o} of type \tcode{T} ends when: +\begin{itemize} +\item if \tcode{T} is a non-class type, the object is destroyed, or +\item if \tcode{T} is a class type, the destructor call starts, or +\item the storage which the object occupies is released, +or is reused by an object that is not nested within \placeholder{o}\iref{intro.object}. \end{itemize} - -If a local entity is odr-used -in a scope in which it is not odr-usable, -the program is ill-formed. +When evaluating a \grammarterm{new-expression}, +storage is considered reused after it is returned from the allocation function, +but before the evaluation of the \grammarterm{new-initializer}\iref{expr.new}. \begin{example} \begin{codeblock} -void f(int n) { - [] { n = 1; }; // error: \tcode{n} is not odr-usable due to intervening lambda-expression - struct A { - void f() { n = 2; } // error: \tcode{n} is not odr-usable due to intervening function definition scope - }; - void g(int = n); // error: \tcode{n} is not odr-usable due to intervening function parameter scope - [=](int k = n) {}; // error: \tcode{n} is not odr-usable due to being - // outside the block scope of the \grammarterm{lambda-expression} - [&] { [n]{ return n; }; }; // OK +struct S { + int m; +}; + +void f() { + S x{1}; + new(&x) S(x.m); // undefined behavior } \end{codeblock} \end{example} \pnum -\begin{example} -\begin{codeblock} -void g() { - constexpr int x = 1; - auto lambda = [] {}; // OK - lambda.operator()(); // OK, does not consider \tcode{x} at all - lambda.operator()(); // OK, does not odr-use \tcode{x} - lambda.operator()(); // error: odr-uses \tcode{x} from a context where \tcode{x} is not odr-usable -} +\indextext{reference lifetime}% +The lifetime of a reference begins when its initialization is complete. +The lifetime of a reference ends as if it were a scalar object requiring storage. -void h() { - constexpr int x = 1; - auto lambda = [] { (T)x; }; // OK - lambda.operator()(); // OK, does not odr-use \tcode{x} - lambda.operator()(); // OK, does not odr-use \tcode{x} - lambda.operator()(); // error: odr-uses \tcode{x} from a context where \tcode{x} is not odr-usable -} -\end{codeblock} -\end{example} +\pnum +\begin{note} +\ref{class.base.init} +describes the lifetime of base and member subobjects. +\end{note} \pnum -Every program shall contain at least one definition of every -function or variable that is odr-used in that program -outside of a discarded statement\iref{stmt.if}; no diagnostic required. -The definition can appear explicitly in the program, it can be found in -the standard or a user-defined library, or (when appropriate) it is -implicitly defined (see~\ref{class.default.ctor}, \ref{class.copy.ctor}, -\ref{class.dtor}, and \ref{class.copy.assign}). -\begin{example} -\begin{codeblock} -auto f() { - struct A {}; - return A{}; -} -decltype(f()) g(); -auto x = g(); -\end{codeblock} -A program containing this translation unit is ill-formed -because \tcode{g} is odr-used but not defined, -and cannot be defined in any other translation unit -because the local class \tcode{A} cannot be named outside this -translation unit. -\end{example} - -\pnum -A \defn{definition domain} is -a \grammarterm{private-module-fragment} or -the portion of a translation unit -excluding its \grammarterm{private-module-fragment} (if any). -A definition of an inline function or variable shall be reachable -from the end of every definition domain -in which it is odr-used outside of a discarded statement. +The properties ascribed to objects and references throughout this document +apply for a given object or reference only during its lifetime. +\begin{note} +In particular, before the lifetime of an object starts and after its +lifetime ends there are significant restrictions on the use of the +object, as described below, in~\ref{class.base.init}, and +in~\ref{class.cdtor}. Also, the behavior of an object under construction +and destruction can differ from the behavior of an object whose +lifetime has started and not ended. \ref{class.base.init} +and~\ref{class.cdtor} describe the behavior of an object during its periods +of construction and destruction. +\end{note} \pnum -\indextext{type!incomplete}% -A definition of a class shall be reachable in every context in which -the class is used in a way that requires the class type to be complete. -\begin{example} -The following complete translation unit is well-formed, -even though it never defines \tcode{X}: -\begin{codeblock} -struct X; // declare \tcode{X} as a struct type -struct X* x1; // use \tcode{X} in pointer formation -X* x2; // use \tcode{X} in pointer formation -\end{codeblock} -\end{example} +A program may end the lifetime of an object of class type without invoking the +destructor, by reusing or releasing the storage as described above. \begin{note} -The rules for declarations and expressions -describe in which contexts complete class types are required. A class -type \tcode{T} must be complete if -\begin{itemize} -\item an object of type \tcode{T} is defined\iref{basic.def}, or -\item a non-static class data member of type \tcode{T} is -declared\iref{class.mem}, or -\item \tcode{T} is used as the allocated type or array element type in a -\grammarterm{new-expression}\iref{expr.new}, or -\item an lvalue-to-rvalue conversion is applied to -a glvalue referring -to an object of type \tcode{T}\iref{conv.lval}, or -\item an expression is converted (either implicitly or explicitly) to -type \tcode{T}\iref{conv,expr.type.conv, -expr.dynamic.cast,expr.static.cast,expr.cast}, or -\item an expression that is not a null pointer constant, and has type -other than \cv{}~\tcode{\keyword{void}*}, is converted to the type pointer to \tcode{T} -or reference to \tcode{T} using a standard conversion\iref{conv}, -a \keyword{dynamic_cast}\iref{expr.dynamic.cast} or -a \keyword{static_cast}\iref{expr.static.cast}, or -\item a class member access operator is applied to an expression of type -\tcode{T}\iref{expr.ref}, or -\item the \keyword{typeid} operator\iref{expr.typeid} or the -\keyword{sizeof} operator\iref{expr.sizeof} is applied to an operand of -type \tcode{T}, or -\item a function with a return type or argument type of type \tcode{T} -is defined\iref{basic.def} or called\iref{expr.call}, or -\item a class with a base class of type \tcode{T} is -defined\iref{class.derived}, or -\item an lvalue of type \tcode{T} is assigned to\iref{expr.ass}, or -\item the type \tcode{T} is the subject of an -\keyword{alignof} expression\iref{expr.alignof}, or -\item an \grammarterm{exception-declaration} has type \tcode{T}, reference to -\tcode{T}, or pointer to \tcode{T}\iref{except.handle}. -\end{itemize} +A \grammarterm{delete-expression}\iref{expr.delete} invokes the destructor +prior to releasing the storage. +\end{note} +In this case, the destructor is not implicitly invoked. +\begin{note} +The correct behavior of a program often depends on +the destructor being invoked for each object of class type. \end{note} \pnum -For any definable item \tcode{D} with definitions in multiple translation units, +Before the lifetime of an object has started but after the storage which +the object will occupy has been allocated +\begin{footnote} +For example, before the dynamic initialization of +an object with static storage duration\iref{basic.start.dynamic}. + +\end{footnote} +or, after the lifetime of an object has ended and before the storage +which the object occupied is reused or released, any pointer that represents the address of +the storage location where the object will be or was located may be +used but only in limited ways. +For an object under construction or destruction, see~\ref{class.cdtor}. +Otherwise, such +a pointer refers to allocated +storage\iref{basic.stc.dynamic.allocation}, and using the pointer as +if the pointer were of type \tcode{\keyword{void}*} is +well-defined. Indirection through such a pointer is permitted but the resulting lvalue may only be used in +limited ways, as described below. The +program has undefined behavior if \begin{itemize} \item -if \tcode{D} is a non-inline non-templated function or variable, or + the pointer is used as the operand of a \grammarterm{delete-expression}, \item -if the definitions in different translation units -do not satisfy the following requirements, -\end{itemize} -the program is ill-formed; -a diagnostic is required only -if the definable item is attached to a named module and -a prior definition is reachable at the point where a later definition occurs. -Given such an item, -for all definitions of \tcode{D}, or, -if \tcode{D} is an unnamed enumeration, -for all definitions of \tcode{D} that are reachable at any given program point, -the following requirements shall be satisfied. -\begin{itemize} -\item Each such definition -shall not be attached to a named module\iref{module.unit}. -\item Each such definition shall consist of -the same sequence of tokens, -where the definition of a closure type -is considered to consist of the sequence of tokens of -the corresponding \grammarterm{lambda-expression}. -\item In each such definition, corresponding names, looked up -according to~\ref{basic.lookup}, shall refer to the same entity, after -overload resolution\iref{over.match} and after matching of partial -template specialization\iref{temp.over}, except that a name can refer to -\begin{itemize} + the pointer is used to access a non-static data member or call a + non-static member function of the object, or \item -a non-volatile const object with internal or no linkage if the object -\begin{itemize} -\item has the same literal type in all definitions of \tcode{D}, -\item is initialized with a constant expression\iref{expr.const}, -\item is not odr-used in any definition of \tcode{D}, and -\item has the same value in all definitions of \tcode{D}, -\end{itemize} -or + the pointer is implicitly converted\iref{conv.ptr} to a pointer + to a virtual base class, or \item -a reference with internal or no linkage -initialized with a constant expression such that -the reference refers to the same entity in all definitions of \tcode{D}. + the pointer is used as the operand of a + \keyword{static_cast}\iref{expr.static.cast}, except when the conversion + is to pointer to \cv{}~\keyword{void}, or to pointer to \cv{}~\keyword{void} + and subsequently to pointer to + \cv{}~\keyword{char}, + \cv{}~\tcode{\keyword{unsigned} \keyword{char}}, or + \cv{}~\tcode{std::byte}\iref{cstddef.syn}, or +\item + the pointer is used as the operand of a + \keyword{dynamic_cast}\iref{expr.dynamic.cast}. \end{itemize} +\begin{example} +\begin{codeblock} +#include -\item In each such definition, except within -the default arguments and default template arguments of \tcode{D}, -corresponding \grammarterm{lambda-expression}{s} shall have -the same closure type (see below). - -\item In each such definition, corresponding entities shall have the -same language linkage. +struct B { + virtual void f(); + void mutate(); + virtual ~B(); +}; -\item In each such definition, -const objects with static or thread storage duration -shall be constant-initialized if -the object is constant-initialized in any such definition. +struct D1 : B { void f(); }; +struct D2 : B { void f(); }; -\item In each such definition, -corresponding manifestly constant-evaluated expressions -that are not value-dependent -shall have the same value\iref{expr.const,temp.dep.constexpr}. +void B::mutate() { + new (this) D2; // reuses storage --- ends the lifetime of \tcode{*this} + f(); // undefined behavior + ... = this; // OK, \keyword{this} points to valid memory +} -\item In each such definition, the overloaded operators referred -to, the implicit calls to conversion functions, constructors, operator -new functions and operator delete functions, shall refer to the same -function. +void g() { + void* p = std::malloc(sizeof(D1) + sizeof(D2)); + B* pb = new (p) D1; + pb->mutate(); + *pb; // OK, \tcode{pb} points to valid memory + void* q = pb; // OK, \tcode{pb} points to valid memory + pb->f(); // undefined behavior: lifetime of \tcode{*pb} has ended +} +\end{codeblock} +\end{example} -\item In each such definition, -a default argument used by an (implicit or explicit) function call or -a default template argument used by an (implicit or explicit) -\grammarterm{template-id} or \grammarterm{simple-template-id} -is treated as if its token sequence -were present in the definition of \tcode{D}; -that is, the default argument or default template argument -is subject to the requirements described in this paragraph (recursively). +\pnum +Similarly, before the lifetime of an object has started but after the +storage which the object will occupy has been allocated or, after the +lifetime of an object has ended and before the storage which the object +occupied is reused or released, any glvalue that refers to the original +object may be used but only in limited ways. +For an object under construction or destruction, see~\ref{class.cdtor}. +Otherwise, such +a glvalue refers to +allocated storage\iref{basic.stc.dynamic.allocation}, and using the +properties of the glvalue that do not depend on its value is +well-defined. The program has undefined behavior if +\begin{itemize} +\item the glvalue is used to access the object, or +\item the glvalue is used to call a non-static member function of the object, or +\item the glvalue is bound to a reference to a virtual base class\iref{dcl.init.ref}, or +\item the glvalue is used as the operand of a +\keyword{dynamic_cast}\iref{expr.dynamic.cast} or as the operand of +\keyword{typeid}. \end{itemize} \pnum -For the purposes of the preceding requirements: - +An object $o_1$ is \defn{transparently replaceable} by an object $o_2$ if \begin{itemize} -\item If \tcode{D} is a class with an implicitly-declared -constructor\iref{class.default.ctor,class.copy.ctor}, -it is as if the constructor was -implicitly defined in every translation unit where it is odr-used, and the -implicit definition in every translation unit shall call the same -constructor for a subobject of \tcode{D}. -\begin{example} -\begin{codeblock} -// translation unit 1: -struct X { - X(int, int); - X(int, int, int); -}; -X::X(int, int = 0) { } -class D { - X x = 0; -}; -D d1; // \tcode{X(int, int)} called by \tcode{D()} +\item the storage that $o_2$ occupies exactly overlays +the storage that $o_1$ occupied, and -// translation unit 2: -struct X { - X(int, int); - X(int, int, int); -}; -X::X(int, int = 0, int = 0) { } -class D { - X x = 0; -}; -D d2; // \tcode{X(int, int, int)} called by \tcode{D()}; - // \tcode{D()}'s implicit definition violates the ODR -\end{codeblock} -\end{example} +\item $o_1$ and $o_2$ are of the same type +(ignoring the top-level cv-qualifiers), and -\item If \tcode{D} is a class with -a defaulted three-way comparison operator function\iref{class.spaceship}, -it is as if the operator was -implicitly defined in every translation unit where it is odr-used, and the -implicit definition in every translation unit shall call the same -comparison operators for each subobject of \tcode{D}. +\item $o_1$ is not a const, complete object, and -\item -If \tcode{D} is a template and is defined in more than one -translation unit, the requirements -apply both to names from the template's enclosing scope used in the -template definition, and also to dependent names at -the point of instantiation\iref{temp.dep}. +\item neither $o_1$ nor $o_2$ +is a potentially-overlapping subobject\iref{intro.object}, and + +\item either $o_1$ and $o_2$ are both complete objects, or +$o_1$ and $o_2$ are direct subobjects of objects $p_1$ and $p_2$, respectively, +and $p_1$ is transparently replaceable by $p_2$. \end{itemize} \pnum -These requirements also apply to corresponding entities -defined within each definition of \tcode{D} -(including the closure types of \grammarterm{lambda-expression}{s}, -but excluding entities defined within default arguments or -default template arguments of either \tcode{D} or -an entity not defined within \tcode{D}). -For each such entity and for \tcode{D} itself, -the behavior is as if there is a single entity with a single definition, -including in the application of these requirements to other entities. +After the lifetime of an object has ended and before the storage which the +object occupied is reused or released, if a new object is created at the +storage location which the original object occupied and the original object was +transparently replaceable by the new object, a pointer that pointed to the +original object, a reference that referred to the original object, or the name +of the original object will automatically refer to the new object and, once the +lifetime of the new object has started, can be used to manipulate the new +object. + +\begin{example} +\begin{codeblock} +struct C { + int i; + void f(); + const C& operator=( const C& ); +}; + +const C& C::operator=( const C& other) { + if ( this != &other ) { + this->~C(); // lifetime of \tcode{*this} ends + new (this) C(other); // new object of type \tcode{C} created + f(); // well-defined + } + return *this; +} + +C c1; +C c2; +c1 = c2; // well-defined +c1.f(); // well-defined; \tcode{c1} refers to a new object of type \tcode{C} +\end{codeblock} +\end{example} \begin{note} -The entity is still declared in multiple translation units, and \ref{basic.link} -still applies to these declarations. In particular, -\grammarterm{lambda-expression}{s}\iref{expr.prim.lambda} -appearing in the type of \tcode{D} can result -in the different declarations having distinct types, and -\grammarterm{lambda-expression}{s} appearing in a default argument of \tcode{D} -might still denote different types in different translation units. +If these conditions are not met, +a pointer to the new object can be obtained from +a pointer that represents the address of its storage +by calling \tcode{std::launder}\iref{ptr.launder}. \end{note} \pnum +If a program ends the lifetime of an object of type \tcode{T} with +static\iref{basic.stc.static}, thread\iref{basic.stc.thread}, +or automatic\iref{basic.stc.auto} +storage duration and if \tcode{T} has a non-trivial destructor, +\begin{footnote} +That +is, an object for which a destructor will be called +implicitly---upon exit from the block for an object with +automatic storage duration, upon exit from the thread for an object with +thread storage duration, or upon exit from the program for an object +with static storage duration. +\end{footnote} +and another object of the original type does not occupy +that same storage location when the implicit destructor call takes +place, the behavior of the program is undefined. This is true +even if the block is exited with an exception. \begin{example} \begin{codeblock} -inline void f(bool cond, void (*p)()) { - if (cond) f(false, []{}); -} -inline void g(bool cond, void (*p)() = []{}) { - if (cond) g(false); -} -struct X { - void h(bool cond, void (*p)() = []{}) { - if (cond) h(false); - } +class T { }; +struct B { + ~B(); }; -\end{codeblock} -If the definition of \tcode{f} appears in multiple translation units, -the behavior of the program is as if -there is only one definition of \tcode{f}. -If the definition of \tcode{g} appears in multiple translation units, -the program is ill-formed (no diagnostic required) because -each such definition uses a default argument that -refers to a distinct \grammarterm{lambda-expression} closure type. -The definition of \tcode{X} can appear -in multiple translation units of a valid program; -the \grammarterm{lambda-expression}{s} defined within -the default argument of \tcode{X::h} within the definition of \tcode{X} -denote the same closure type in each translation unit. +void h() { + B b; + new (&b) T; +} // undefined behavior at block exit +\end{codeblock} \end{example} \pnum -If, at any point in the program, -there is more than one -reachable unnamed enumeration definition in the same scope -that have the same first enumerator name and -do not have typedef names for linkage purposes\iref{dcl.enum}, -those unnamed enumeration types shall be the same; no diagnostic required. -\indextext{one-definition rule|)} +Creating a new object within the storage that a const, complete +object with static, thread, or automatic storage duration occupies, +or within the storage that such a const object used to occupy before +its lifetime ended, results in undefined behavior. +\begin{example} +\begin{codeblock} +struct B { + B(); + ~B(); +}; -\rSec1[basic.scope]{Scope}% -\indextext{scope|(} +const B b; -\rSec2[basic.scope.scope]{General} +void h() { + b.~B(); + new (const_cast(&b)) const B; // undefined behavior +} +\end{codeblock} +\end{example} +\indextext{object lifetime|)} -\pnum -The declarations in a program appear in a number of \defnx{scopes}{scope} -that are in general discontiguous. -The \defnadj{global}{scope} contains the entire program; -every other scope $S$ is introduced by a -declaration, -\grammarterm{parameter-declaration-clause}, -\grammarterm{statement}, or \grammarterm{handler} -(as described in the following subclauses of \ref{basic.scope}) -appearing in another scope which thereby contains $S$. -An \defnadj{enclosing}{scope} at a program point is any scope that contains it; -the smallest such scope is said to be the \defnadj{immediate}{scope} -at that point. -A scope \defnx{intervenes}{scope!intervene} -between a program point $P$ and a scope $S$ -(that does not contain $P$) if it is or contains $S$ but does not contain $P$. +\rSec2[basic.indet]{Indeterminate and erroneous values} \pnum -Unless otherwise specified: +When storage for an object with automatic or dynamic storage duration +is obtained, +the bytes comprising the storage for the object +have the following initial value: \begin{itemize} \item -The smallest scope that contains a scope $S$ is -the \defnadj{parent}{scope} of $S$. -\item -No two declarations (re)introduce the same entity. -\item -A declaration \defnx{inhabits}{scope!inhabit} -the immediate scope at its locus\iref{basic.scope.pdecl}. -\item -A declaration's \defnadj{target}{scope} is the scope it inhabits. +If the object has dynamic storage duration, or +is the object associated with a variable or function parameter +whose first declaration is marked with +the \tcode{[[indeterminate]]} attribute\iref{dcl.attr.indet}, +the bytes have \defnadjx{indeterminate}{values}{value}; \item -Any names (re)introduced by a declaration are \defnx{bound}{name!bound} to it -in its target scope. +otherwise, the bytes have \defnadjx{erroneous}{values}{value}, +where each value is determined by the implementation +independently of the state of the program. \end{itemize} -An entity \defnx{belongs}{entity!belong} to a scope $S$ -if $S$ is the target scope of a declaration of the entity. +If no initialization is performed for an object (including subobjects), +such a byte retains its initial value +until that value is replaced\iref{dcl.init.general,expr.ass}. +If any bit in the value representation has an indeterminate value, +the object has an indeterminate value; +otherwise, if any bit in the value representation has an erroneous value, +the object has an erroneous value\iref{conv.lval}. \begin{note} -Special cases include that: -\begin{itemize} -\item -Template parameter scopes are parents -only to other template parameter scopes\iref{basic.scope.temp}. -\item -Corresponding declarations with appropriate linkage -declare the same entity\iref{basic.link}. -\item -The declaration in a \grammarterm{template-declaration} -inhabits the same scope as the \grammarterm{template-declaration}. -\item -Friend declarations and -declarations of template specializations do not bind names\iref{dcl.meaning}; -those with qualified names target a specified scope, and -other friend declarations and -certain \grammarterm{elaborated-type-specifier}s\iref{dcl.type.elab} -target a larger enclosing scope. -\item -Block-scope extern declarations target a larger enclosing scope -but bind a name in their immediate scope. -\item -The names of unscoped enumerators are bound -in the two innermost enclosing scopes\iref{dcl.enum}. -\item -A class's name is also bound in its own scope\iref{class.pre}. -\item -The names of the members of an anonymous union are bound in -the union's parent scope\iref{class.union.anon}. -\end{itemize} +Objects with static or thread storage duration are zero-initialized, +see~\ref{basic.start.static}. \end{note} \pnum -Two non-static member functions have -\defnadjx{corresponding}{object parameters}{object parameter} if +Except in the following cases, +if an indeterminate value is produced by an evaluation, +the behavior is undefined, and +if an erroneous value is produced by an evaluation, +the behavior is erroneous and +the result of the evaluation is the value so produced but is not erroneous: \begin{itemize} \item -exactly one is an implicit object member function -with no \grammarterm{ref-qualifier} and -the types of their object parameters\iref{dcl.fct}, -after removing references, -are the same, or + If an indeterminate or erroneous value of + unsigned ordinary character type\iref{basic.fundamental} + or \tcode{std::byte} type\iref{cstddef.syn} + is produced by the evaluation of: + \begin{itemize} + \item + the second or third operand of a conditional expression\iref{expr.cond}, + \item + the right operand of a comma expression\iref{expr.comma}, + \item + the operand of a cast or conversion\iref{conv.integral, + expr.type.conv,expr.static.cast,expr.cast} + to an unsigned ordinary character type + or \tcode{std::byte} type\iref{cstddef.syn}, or + \item + a discarded-value expression\iref{expr.context}, + \end{itemize} + then the result of the operation is an indeterminate value or + that erroneous value, respectively. \item -their object parameters have the same type. -\end{itemize} -\indextext{template!function!corresponding object parameter}% -Two non-static member function templates have -\defnadjx{corresponding}{object parameters}{object parameter} if -\begin{itemize} + If an indeterminate or erroneous value of + unsigned ordinary character type or \tcode{std::byte} type + is produced by the evaluation of + the right operand of a simple assignment operator\iref{expr.ass} + whose first operand is an lvalue of + unsigned ordinary character type or \tcode{std::byte} type, + an indeterminate value or that erroneous value, respectively, replaces + the value of the object referred to by the left operand. \item -exactly one is an implicit object member function -with no \grammarterm{ref-qualifier} and -the types of their object parameters, -after removing any references, -are equivalent, or + If an indeterminate or erroneous value of unsigned ordinary character type + is produced by the evaluation of the initialization expression + when initializing an object of unsigned ordinary character type, + that object is initialized to an indeterminate + value or that erroneous value, respectively. \item -the types of their object parameters are equivalent. + If an indeterminate value of + unsigned ordinary character type or \tcode{std::byte} type + is produced by the evaluation of the initialization expression + when initializing an object of \tcode{std::byte} type, + that object is initialized to an indeterminate value or + that erroneous value, respectively. \end{itemize} -\indextext{template!function!corresponding signature}% -Two function templates have -\defnadjx{corresponding}{signatures}{signature} if -their \grammarterm{template-parameter-list}{s} -have the same length, -their corresponding \grammarterm{template-parameter}{s} are equivalent, -they have equivalent non-object-parameter-type-lists and return types (if any), and, -if both are non-static members, they have corresponding object parameters. +Converting an indeterminate or erroneous value of +unsigned ordinary character type or \tcode{std::byte} type +produces an indeterminate or erroneous value, respectively. +In the latter case, +the result of the conversion is the value of the converted operand. +\begin{example} +\begin{codeblock} +int f(bool b) { + unsigned char *c = new unsigned char; + unsigned char d = *c; // OK, \tcode{d} has an indeterminate value + int e = d; // undefined behavior + return b ? d : 0; // undefined behavior if \tcode{b} is \tcode{true} +} + +int g(bool b) { + unsigned char c; + unsigned char d = c; // no erroneous behavior, but \tcode{d} has an erroneous value + + assert(c == d); // holds, both integral promotions have erroneous behavior + + int e = d; // erroneous behavior + return b ? d : 0; // erroneous behavior if \tcode{b} is \tcode{true} +} + +void h() { + int d1, d2; + + int e1 = d1; // erroneous behavior + int e2 = d1; // erroneous behavior + + assert(e1 == e2); // holds + assert(e1 == d1); // holds, erroneous behavior + assert(e2 == d1); // holds, erroneous behavior + + std::memcpy(&d2, &d1, sizeof(int)); // no erroneous behavior, but \tcode{d2} has an erroneous value + assert(e1 == d2); // holds, erroneous behavior + assert(e2 == d2); // holds, erroneous behavior +} +\end{codeblock} +\end{example} + +\rSec2[basic.stc]{Storage duration} + +\rSec3[basic.stc.general]{General} \pnum -Two declarations \defn{correspond} -if they (re)introduce the same name, -both declare constructors, or -both declare destructors, -unless -\begin{itemize} -\item -either is a \grammarterm{using-declarator}, or -\item -one declares a type (not a \grammarterm{typedef-name}) and the other declares a -variable, -non-static data member other than of an anonymous union\iref{class.union.anon}, -enumerator, -function, or -function template, or -\item -each declares a function or function template -and they do not declare corresponding overloads. -\end{itemize} -Two function or function template declarations declare -\defn{corresponding overloads} if +\indextext{storage duration|(}% +The \defn{storage duration} is the property of an object that defines the minimum +potential lifetime of the storage containing the object. The storage +duration is determined by the construct used to create the object and is +one of the following: \begin{itemize} -\item -both declare functions with the same non-object-parameter-type-list, -\begin{footnote} -An implicit object parameter\iref{over.match.funcs} -is not part of the parameter-type-list. -\end{footnote} -equivalent\iref{temp.over.link} trailing \grammarterm{requires-clause}s -(if any, except as specified in \ref{temp.friend}), and, -if both are non-static members, -they have corresponding object parameters, or -\item -both declare function templates with corresponding signatures and equivalent -\grammarterm{template-head}s and -trailing \grammarterm{requires-clause}s (if any). +\item static storage duration +\item thread storage duration +\item automatic storage duration +\item dynamic storage duration \end{itemize} \begin{note} -Declarations can correspond even if neither binds a name. -\begin{example} -\begin{codeblock} -struct A { - friend void f(); // \#1 -}; -struct B { - friend void f() {} // corresponds to, and defines, \#1 -}; -\end{codeblock} -\end{example} +After the duration of a region of storage has ended, +the use of pointers to that region of storage is limited\iref{basic.compound}. \end{note} -\begin{example} -\begin{codeblock} -typedef int Int; -enum E : int { a }; -void f(int); // \#1 -void f(Int) {} // defines \#1 -void f(E) {} // OK, another overload -struct X { - static void f(); - void f() const; // error: redeclaration - void g(); - void g() const; // OK - void g() &; // error: redeclaration +\pnum +\indextext{storage duration!static}% +\indextext{storage duration!thread}% +\indextext{storage duration!automatic}% +\indextext{storage duration!dynamic}% +Static, thread, and automatic storage durations are associated with objects +introduced by declarations\iref{basic.def} and +with temporary objects\iref{class.temporary}. +The dynamic storage duration +is associated with objects created by a +\grammarterm{new-expression}\iref{expr.new} or +with implicitly created objects\iref{intro.object}. - void h(this X&, int); - void h(int) &&; // OK, another overload - void j(this const X&); - void j() const &; // error: redeclaration - void k(); - void k(this X&); // error: redeclaration -}; -\end{codeblock} -\end{example} +\pnum +The storage duration categories apply to references as well. + +\rSec3[basic.stc.inherit]{Duration of subobjects} \pnum -A declaration is \defnx{name-independent}{declaration!name-independent} -if its name is \tcode{_} (\unicode{005f}{low line}) and it declares +\indextext{storage duration!class member}% +The storage duration of subobjects and reference members +is that of their complete object\iref{intro.object}. +\indextext{storage duration|)}% + +\rSec3[basic.stc.static]{Static storage duration} + +\pnum +All variables which \begin{itemize} \item -a variable with automatic storage duration, -\item -a structured binding -%FIXME: "and" is strange below; maybe reword to something like: -%FIXME: "that has no \grammarterm{storage-class-specifier} and -%FIXME: that is not inhabiting a namespace scope," -with no \grammarterm{storage-class-specifier} and -not inhabiting a namespace scope, -\item -the variable introduced by an \grammarterm{init-capture}, or +do not have thread storage duration and \item -%FIXME: "of" is strange below; remove it? -a non-static data member of other than an anonymous union. +belong to a namespace scope\iref{basic.scope.namespace} or +are first declared with +the \keyword{static} or \keyword{extern} keywords\iref{dcl.stc} \end{itemize} +have \defnadj{static}{storage duration}. +The storage for these entities lasts for the duration of the +program\iref{basic.start.static,basic.start.term}. -\recommended -Implementations should not emit a warning -that a name-independent declaration is used or unused. +\pnum +If a variable with static storage duration has initialization or a +destructor with side effects, it shall not be eliminated even if it +appears to be unused, except that a class object or its copy/move may be +eliminated as specified in~\ref{class.copy.elision}. \pnum -\indextext{declaration!potentially conflict}% -Two declarations \defn{potentially conflict} -if they correspond and -cause their shared name to denote different entities\iref{basic.link}. -The program is ill-formed -if, in any scope, a name is bound to two declarations $A$ and $B$ -that potentially conflict and $A$ precedes $B$\iref{basic.lookup}, -unless $B$ is name-independent. \begin{note} -An \grammarterm{id-expression} that names a unique name-independent declaration -is usable until an additional declaration of the same name -is introduced in the same scope\iref{basic.lookup.general}. +\indextext{object!local static@local \tcode{static}}% +The keyword \keyword{static} can be used to declare +a block variable\iref{basic.scope.block} with static storage duration; +\ref{stmt.dcl} and \ref{basic.start.term} describe the +initialization and destruction of such variables. +\indextext{member!class static@class \tcode{static}}% +The keyword \keyword{static} applied to +a class data member in a class definition +gives the data member static storage duration\iref{class.static.data}. \end{note} -\begin{note} -Overload resolution can consider potentially conflicting declarations -found in multiple scopes -(e.g., via \grammarterm{using-directive}s or for operator functions), -in which case it is often ambiguous. -\end{note} -\begin{example} -\begin{codeblock} -void f() { - int x,y; - void x(); // error: different entity for \tcode{x} - int y; // error: redefinition -} -enum { f }; // error: different entity for \tcode{::f} -namespace A {} -namespace B = A; -namespace B = A; // OK, no effect -namespace B = B; // OK, no effect -namespace A = B; // OK, no effect -namespace B {} // error: different entity for \tcode{B} -void g() { - int _; - _ = 0; // OK - int _; // OK, name-independent declaration - _ = 0; // error: two non-function declarations in the lookup set -} -void h () { - int _; // \#1 - _ ++; // OK - static int _; // error: conflicts with \#1 because static variables are not name-independent -} -\end{codeblock} -\end{example} +\rSec3[basic.stc.thread]{Thread storage duration} \pnum -\indextext{declaration!nominable}% -A declaration is \defn{nominable} -in a class, class template, or namespace $E$ at a point $P$ if -it precedes $P$, -it does not inhabit a block scope, and -its target scope is the scope associated with $E$ or, -if $E$ is a namespace, -any element of the inline namespace set of $E$\iref{namespace.def}. -\begin{example} -\begin{codeblock} -namespace A { - void f() {void g();} - inline namespace B { - struct S { - friend void h(); - static int i; - }; - } -} -\end{codeblock} -At the end of this example, -the declarations of \tcode{f}, \tcode{B}, \tcode{S}, and \tcode{h} -are nominable in \tcode{A}, but those of \tcode{g} and \tcode{i} are not. -\end{example} +All variables declared with the \keyword{thread_local} keyword have +\defnadj{thread}{storage duration}. +The storage for these entities lasts for the duration of +the thread in which they are created. There is a distinct object or reference +per thread, and use of the declared name refers to the entity associated with +the current thread. \pnum -When instantiating a templated entity\iref{temp.pre}, -any scope $S$ introduced by any part of the template definition is considered -to be introduced by the instantiated entity and -to contain the instantiations of any declarations that inhabit $S$. - -\rSec2[basic.scope.pdecl]{Point of declaration} - -\indextext{declaration!point of|see{locus}}% -\indextext{scope!declarations and|see{locus}}% -\indextext{locus|(}% +\begin{note} +A variable with thread storage duration is initialized as specified +in~\ref{basic.start.static}, \ref{basic.start.dynamic}, and \ref{stmt.dcl} +and, if constructed, is destroyed on thread exit\iref{basic.start.term}. +\end{note} -\pnum -\indextext{declaration!locus|see{locus}}% -The \defn{locus} of a declaration\iref{basic.pre} that is a declarator -is immediately after the complete declarator\iref{dcl.decl}. -\begin{example} -\begin{codeblock} -unsigned char x = 12; -{ unsigned char x = x; } -\end{codeblock} -Here, the initialization of the second \tcode{x} has undefined behavior, -because the initializer accesses the second \tcode{x} -outside its lifetime\iref{basic.life}. -\end{example} +\rSec3[basic.stc.auto]{Automatic storage duration} \pnum +\indextext{storage duration!local object}% +Variables that belong to a block scope and are +not explicitly declared \keyword{static}, \keyword{thread_local}, or \keyword{extern} have +\defnadj{automatic}{storage duration}. The storage +for such variables lasts until the block in which they are created exits. \begin{note} -\indextext{name hiding}% -A name from an outer scope remains visible up to -the locus of the declaration that hides it. -\begin{example} -\begin{codeblock} -const int i = 2; -{ int i[i]; } -\end{codeblock} -declares a block-scope array of two integers. -\end{example} +These variables are initialized and destroyed as described in~\ref{stmt.dcl}. \end{note} +Variables that belong to a parameter scope also have automatic storage duration. +The storage for a function parameter lasts until +immediately after its destruction\iref{expr.call}. \pnum -The locus of a \grammarterm{class-specifier} is immediately after -the \grammarterm{identifier} or \grammarterm{simple-template-id} (if any) -in its \grammarterm{class-head}\iref{class.pre}. -The locus of an \grammarterm{enum-specifier} -is immediately after -its \grammarterm{enum-head}; -the locus of an \grammarterm{opaque-enum-declaration} -is immediately after it\iref{dcl.enum}. -%FIXME: What's "it" below? What's "it" above? -The locus of an \grammarterm{alias-declaration} is immediately after it. +If a variable with automatic storage duration has initialization or a destructor with side +effects, an implementation shall not destroy it before the end of its block +nor eliminate it as an optimization, even if it appears to be +unused, except that a class object or its copy/move may be eliminated as +specified in~\ref{class.copy.elision}. -\pnum -The locus of a \grammarterm{using-declarator} -that does not name a constructor -is immediately after the \grammarterm{using-declarator}\iref{namespace.udecl}. +\rSec3[basic.stc.dynamic]{Dynamic storage duration}% -\pnum -The locus of an \grammarterm{enumerator-definition} is immediately after it. -\begin{example} -\begin{codeblock} -const int x = 12; -{ enum { x = x }; } -\end{codeblock} -Here, the enumerator \tcode{x} is initialized with the value of the -constant \tcode{x}, namely 12. -\end{example} +\rSec4[basic.stc.dynamic.general]{General}% +\indextext{storage duration!dynamic|(} \pnum +Objects can be created dynamically during program +execution\iref{intro.execution}, using +\indextext{\idxcode{new}}% +\grammarterm{new-expression}{s}\iref{expr.new}, and destroyed using +\indextext{\idxcode{delete}}% +\grammarterm{delete-expression}{s}\iref{expr.delete}. A \Cpp{} implementation +provides access to, and management of, dynamic storage via +the global \defnx{allocation functions}{allocation function} +\tcode{\keyword{operator} \keyword{new}} and +\tcode{\keyword{operator} \keyword{new}[]} and +the global \defnx{deallocation functions}{deallocation function} +\tcode{\keyword{operator} \keyword{delete}} and +\tcode{\keyword{operator} \keyword{delete}[]}. \begin{note} -\indextext{type!incomplete}% -After the declaration of a class member, -the member name can be found in the scope of its class -even if the class is an incomplete class. -\begin{example} -\begin{codeblock} -struct X { - enum E { z = 16 }; - int b[X::z]; // OK -}; -\end{codeblock} -\end{example} +The non-allocating forms described in \ref{new.delete.placement} +do not perform allocation or deallocation. \end{note} \pnum -The locus of an \grammarterm{elaborated-type-specifier} -that is a declaration\iref{dcl.type.elab} is immediately after it. - -\pnum -The locus of an injected-class-name declaration\iref{class.pre} -is immediately following the opening brace of the class definition. +The library provides default definitions for the global allocation and +deallocation functions. Some global allocation and deallocation +functions are replaceable\iref{new.delete}; +these are attached to the global module\iref{module.unit}. +A \Cpp{} program shall +provide at most one definition of a replaceable allocation or +deallocation function. Any such function definition replaces the default +version provided in the library\iref{replacement.functions}. The +following allocation and deallocation functions\iref{support.dynamic} +are implicitly declared in global scope in each translation unit of a +program. -\pnum -The locus of the implicit declaration of -a function-local predefined variable\iref{dcl.fct.def.general} -is immediately before -the \grammarterm{function-body} of its function's definition. +\begin{codeblock} +void* operator new(std::size_t); +void* operator new(std::size_t, std::align_val_t); -\pnum -The locus of the declaration of a structured binding\iref{dcl.struct.bind} -is immediately after -the \grammarterm{identifier-list} of the structured binding declaration. +void operator delete(void*) noexcept; +void operator delete(void*, std::size_t) noexcept; +void operator delete(void*, std::align_val_t) noexcept; +void operator delete(void*, std::size_t, std::align_val_t) noexcept; -\pnum -The locus of a \grammarterm{for-range-declaration} -of a range-based \keyword{for} statement\iref{stmt.ranged} -is immediately after the \grammarterm{for-range-initializer}. +void* operator new[](std::size_t); +void* operator new[](std::size_t, std::align_val_t); -\pnum -The locus of a \grammarterm{template-parameter} is immediately after it. -\begin{example} -\begin{codeblock} -typedef unsigned char T; -template struct A { }; +void operator delete[](void*) noexcept; +void operator delete[](void*, std::size_t) noexcept; +void operator delete[](void*, std::align_val_t) noexcept; +void operator delete[](void*, std::size_t, std::align_val_t) noexcept; \end{codeblock} -\end{example} -\pnum -The locus of a \grammarterm{concept-definition} -is immediately after its \grammarterm{concept-name}\iref{temp.concept}. +These implicit declarations introduce only the function names +\tcode{\keyword{operator} \keyword{new}}, +\tcode{\keyword{operator} \keyword{new}[]}, +\tcode{\keyword{operator} \keyword{delete}}, and +\tcode{\keyword{operator} \keyword{delete}[]}. \begin{note} -The \grammarterm{constraint-expression} cannot use -the \grammarterm{concept-name}. +The implicit declarations do not introduce +the names \tcode{std}, +\tcode{std::size_t}, +\tcode{std::align_val_t}, +or any other names that the library uses to +declare these names. Thus, a \grammarterm{new-expression}, +\grammarterm{delete-expression}, or function call that refers to one of +these functions without importing or including the header \libheaderref{new} +or importing a \Cpp{} library module\iref{std.modules} +is well-formed. However, referring to \tcode{std} +or \tcode{std::size_t} +or \tcode{std::align_val_t} +is ill-formed unless +a standard library declaration\iref{cstddef.syn,new.syn,std.modules} +of that name precedes\iref{basic.lookup.general} the use of that name. \end{note} +Allocation and/or +deallocation functions may also be declared and defined for any +class\iref{class.free}. \pnum -The locus of a \grammarterm{namespace-definition} -with an \grammarterm{identifier} -is immediately after the \grammarterm{identifier}. -\begin{note} -An identifier is invented -for an \grammarterm{unnamed-namespace-definition}\iref{namespace.unnamed}. -\end{note} +If the behavior of an allocation or deallocation function +does not satisfy the semantic constraints +specified in~\ref{basic.stc.dynamic.allocation} +and~\ref{basic.stc.dynamic.deallocation}, +the behavior is undefined. -\pnum -\begin{note} -Friend declarations can introduce functions or classes -that belong to the nearest enclosing namespace or block scope, -but they do not bind names anywhere\iref{class.friend}. -Function declarations at block scope and -variable declarations with the \keyword{extern} specifier at block scope -declare entities -that belong to the nearest enclosing namespace, -but they do not bind names in it. -\end{note} +\indextext{storage duration!dynamic|)} -\pnum -\begin{note} -For point of instantiation of a template, see~\ref{temp.point}. -\end{note} -\indextext{locus|)} +\rSec4[basic.stc.dynamic.allocation]{Allocation functions} -\rSec2[basic.scope.block]{Block scope} +\pnum +\indextext{function!allocation}% +An allocation function that is not a class member function +shall belong to the global scope and not have a name with internal linkage. +The return type shall be \tcode{\keyword{void}*}. The first +parameter shall have type \tcode{std::size_t}\iref{support.types}. The +first parameter shall not have an associated default +argument\iref{dcl.fct.default}. The value of the first parameter +is interpreted as the requested size of the allocation. An allocation +function can be a function template. Such a template shall declare its +return type and first parameter as specified above (that is, template +parameter types shall not be used in the return type and first parameter +type). Allocation function templates shall have two or more parameters. -\indextext{local scope|see{scope, block}}% +\pnum +An allocation function attempts to allocate the requested amount of +storage. If it is successful, it returns the address of the start +of a block of storage whose length in bytes is at least as large +as the requested size. +The order, +contiguity, and initial value of storage allocated by successive calls +to an allocation function are unspecified. +Even if the size of the space +requested is zero, the request can fail. If the request succeeds, the +value returned by a replaceable allocation function +is a non-null pointer value\iref{basic.compound} +\tcode{p0} different from any previously returned value \tcode{p1}, +unless that value \tcode{p1} was subsequently passed to a +replaceable deallocation function. +Furthermore, for the library allocation functions +in~\ref{new.delete.single} and~\ref{new.delete.array}, +\tcode{p0} represents the address of a block of storage disjoint from the storage +for any other object accessible to the caller. +The effect of indirecting through a pointer +returned from a request for zero size is undefined. +\begin{footnote} +The intent is +to have \tcode{\keyword{operator} \keyword{new}()} implementable by +calling \tcode{std::malloc()} or \tcode{std::calloc()}, so the rules are +substantially the same. \Cpp{} differs from C in requiring a zero request +to return a non-null pointer. +\end{footnote} \pnum -Each +For an allocation function other than +a reserved placement allocation function\iref{new.delete.placement}, +the pointer returned on a successful call +shall represent the address of storage that is aligned as follows: \begin{itemize} \item -selection or iteration statement\iref{stmt.select,stmt.iter}, -\item -substatement of such a statement, + If the allocation function takes an argument + of type \tcode{std::align_val_t}, + the storage will have the alignment specified + by the value of this argument. \item -\indextext{scope!\idxgram{handler}}% -\grammarterm{handler}\iref{except.pre}, or + Otherwise, if the allocation function is named \tcode{\keyword{operator} \keyword{new}[]}, + the storage is aligned for any object that + does not have new-extended alignment\iref{basic.align} and + is no larger than the requested size. \item -compound statement\iref{stmt.block} -that is not the \grammarterm{compound-statement} of a \grammarterm{handler} + Otherwise, the storage is aligned for any object that + does not have new-extended alignment and is of the requested size. \end{itemize} -introduces a \defnadj{block}{scope} -that includes that statement or \grammarterm{handler}. + +\pnum +An allocation function that fails to allocate storage can invoke the +currently installed new-handler function\iref{new.handler}, if any. \begin{note} -A substatement that is also a block has only one scope. +\indextext{\idxcode{new_handler}}% +A program-supplied allocation function can obtain the +currently installed \tcode{new_handler} using the +\tcode{std::get_new_handler} function\iref{get.new.handler}. \end{note} -A variable that belongs to a block scope is a \defn{block variable}. -\begin{example} -\begin{codeblock} -int i = 42; -int a[10]; - -for (int i = 0; i < 10; i++) - a[i] = i; - -int j = i; // \tcode{j = 42} -\end{codeblock} -\end{example} +An allocation function that has a non-throwing +exception specification\iref{except.spec} +indicates failure by returning +a null pointer value. +Any other allocation function +never returns a null pointer value and +indicates failure only by throwing an exception\iref{except.throw} of a type +that would match a handler\iref{except.handle} of type +\tcode{std::bad_alloc}\iref{bad.alloc}. \pnum -If a declaration -that is not a name-independent declaration and -that binds a name in the block scope $S$ of a -\begin{itemize} -\item -\grammarterm{compound-statement} of a \grammarterm{lambda-expression}, -\grammarterm{function-body}, or \grammarterm{function-try-block}, -\item -substatement of a selection or iteration statement -that is not itself a selection or iteration statement, or -\item -\grammarterm{handler} of a \grammarterm{function-try-block} -\end{itemize} -potentially conflicts with a declaration -whose target scope is the parent scope of $S$, -the program is ill-formed. -\begin{example} -\begin{codeblock} -if (int x = f()) { - int x; // error: redeclaration of \tcode{x} -} -else { - int x; // error: redeclaration of \tcode{x} -} -\end{codeblock} -\end{example} +A global allocation function is only called as the result of a new +expression\iref{expr.new}, or called directly using the function call +syntax\iref{expr.call}, or called indirectly to allocate storage for +a coroutine state\iref{dcl.fct.def.coroutine}, +or called indirectly through calls to the +functions in the \Cpp{} standard library. +\begin{note} +In particular, a +global allocation function is not called to allocate storage for objects +with static storage duration\iref{basic.stc.static}, for objects or references +with thread storage duration\iref{basic.stc.thread}, for objects of +type \tcode{std::type_info}\iref{expr.typeid}, or for an +exception object\iref{except.throw}. +\end{note} -\rSec2[basic.scope.param]{Function parameter scope} +\rSec4[basic.stc.dynamic.deallocation]{Deallocation functions} -\indextext{scope!function prototype|see{scope, function parameter}}% -\indextext{parameter!scope of}% +\pnum +\indextext{function!deallocation}% +A deallocation function that is not a class member function +shall belong to the global scope and not have a name with internal linkage. \pnum -A \grammarterm{parameter-declaration-clause} $P$ introduces -a \defnadj{function parameter}{scope} that includes $P$. +A deallocation function +is a \defnadj{destroying}{operator delete} +if it has at least two parameters +and its second parameter +is of type \tcode{std::destroying_delete_t}. +A destroying operator delete +shall be a class member function named \tcode{\keyword{operator} \keyword{delete}}. \begin{note} -A function parameter cannot be used for its value -within the \grammarterm{parameter-declaration-clause}\iref{dcl.fct.default}. +Array deletion cannot use a destroying operator delete. \end{note} + +\pnum +\indextext{\idxcode{delete}!overloading and}% +Each deallocation function shall return \keyword{void}. +If the function is a destroying operator delete +declared in class type \tcode{C}, +the type of its first parameter shall be \tcode{C*}; +otherwise, the type of its first +parameter shall be \tcode{\keyword{void}*}. A deallocation function may have more +than one parameter. +\indextext{deallocation function!usual}% +A \defn{usual deallocation function} is a deallocation function +whose parameters after the first are \begin{itemize} \item -If $P$ is associated with a \grammarterm{declarator} and -is preceded by a (possibly-parenthesized) \grammarterm{noptr-declarator} of -the form -\grammarterm{declarator-id} \opt{\grammarterm{attribute-specifier-seq}}, -its scope extends to the end of the nearest enclosing -\grammarterm{init-declarator}, -\grammarterm{member-declarator}, -\grammarterm{declarator} of a \grammarterm{parameter-declaration} or -a \grammarterm{nodeclspec-function-declaration}, or -\grammarterm{function-definition}, -but does not include the locus of the associated \grammarterm{declarator}. -\begin{note} -In this case, $P$ declares the parameters of a function -(or a function or template parameter declared with function type). -A member function's parameter scope is nested within its class's scope. -\end{note} -\item -If $P$ is associated with a \grammarterm{lambda-declarator}, -its scope extends to the end of the \grammarterm{compound-statement} -in the \grammarterm{lambda-expression}. +optionally, a parameter of type \tcode{std::destroying_delete_t}, then \item -If $P$ is associated with a \grammarterm{requirement-parameter-list}, -its scope extends to the end of the \grammarterm{requirement-body} of the \grammarterm{requires-expression}. +optionally, a parameter of type \tcode{std::size_t}, +\begin{footnote} +The global \tcode{\keyword{operator} \keyword{delete}(\keyword{void}*, std::size_t)} +precludes use of an +allocation function \tcode{\keyword{void} \keyword{operator} \keyword{new}(std::size_t, std::size_t)} as a placement +allocation function\iref{diff.cpp11.basic}. +\end{footnote} +then \item -If $P$ is associated with a \grammarterm{deduction-guide}, -its scope extends to the end of the \grammarterm{deduction-guide}. +optionally, a parameter of type \tcode{std::align_val_t}. \end{itemize} +A destroying operator delete shall be a usual deallocation function. +A deallocation function may be an instance of a function +template. Neither the first parameter nor the return type shall depend +on a template parameter. +A deallocation +function template shall have two or more function parameters. A template +instance is never a usual deallocation function, regardless of its +signature. -\rSec2[basic.scope.lambda]{Lambda scope} +\pnum +If a deallocation function terminates by throwing an exception, the behavior is undefined. +The value of the first argument supplied to a deallocation function may +be a null pointer value; if so, and if the deallocation function is one +supplied in the standard library, the call has no effect. -A \grammarterm{lambda-expression} \tcode{E} introduces a \defnadj{lambda}{scope} -that starts immediately after the \grammarterm{lambda-introducer} of \tcode{E} -and extends to the end of the \grammarterm{compound-statement} of \tcode{E}. +\pnum +If the argument given to a deallocation function in the standard library +is a pointer that is not the null pointer value\iref{basic.compound}, the +deallocation function shall deallocate the storage referenced by the +pointer, ending the duration of the region of storage. -\rSec2[basic.scope.namespace]{Namespace scope} +\rSec2[basic.align]{Alignment} \pnum -Any \grammarterm{namespace-definition} for a namespace $N$ introduces -a \defnadj{namespace}{scope} -that includes the \grammarterm{namespace-body} -for every \grammarterm{namespace-definition} for $N$. -For each non-friend redeclaration or specialization -whose target scope is or is contained by the scope, -the portion after the -\grammarterm{declarator-id}, -\grammarterm{class-head-name}, or -\grammarterm{enum-head-name} -is also included in the scope. -The global scope is -the namespace scope of the global namespace\iref{basic.namespace}. +Object types have \defnx{alignment requirements}{alignment requirement!implementation-defined}\iref{basic.fundamental,basic.compound} +which place restrictions on the addresses at which an object of that type +may be allocated. An \defn{alignment} is an \impldef{alignment} +integer value representing the number of bytes between successive addresses +at which a given object can be allocated. An object type imposes an alignment +requirement on every object of that type; stricter alignment can be requested +using the alignment specifier\iref{dcl.align}. +Attempting to create an object\iref{intro.object} in storage that +does not meet the alignment requirements of the object's type +is undefined behavior. + +\pnum +A \defnadj{fundamental}{alignment} is represented by an alignment +less than or equal to the greatest alignment supported by the implementation in +all contexts, which is equal to +\tcode{\keyword{alignof}(std::max_align_t)}\iref{support.types}. +The alignment required for a type may be different when it is used as the type +of a complete object and when it is used as the type of a subobject. \begin{example} \begin{codeblock} -namespace Q { - namespace V { void f(); } - void V::f() { // in the scope of \tcode{V} - void h(); // declares \tcode{Q::V::h} - } -} +struct B { long double d; }; +struct D : virtual B { char c; }; \end{codeblock} -\end{example} -\rSec2[basic.scope.class]{Class scope} +When \tcode{D} is the type of a complete object, it will have a subobject of +type \tcode{B}, so it must be aligned appropriately for a \tcode{\keyword{long} \keyword{double}}. +If \tcode{D} appears as a subobject of another object that also has \tcode{B} +as a virtual base class, the \tcode{B} subobject might be part of a different +subobject, reducing the alignment requirements on the \tcode{D} subobject. +\end{example} +The result of the \keyword{alignof} operator reflects the alignment +requirement of the type in the complete-object case. \pnum -Any declaration of a class or class template $C$ introduces -a \defnadj{class}{scope} -that includes the \grammarterm{member-specification} of -the \grammarterm{class-specifier} for $C$ (if any). -For each non-friend redeclaration or specialization -whose target scope is or is contained by the scope, -the portion after the -\grammarterm{declarator-id}, -\grammarterm{class-head-name}, or -\grammarterm{enum-head-name} is also included in the scope. +An \defnadj{extended}{alignment} is represented by an alignment +greater than \tcode{\keyword{alignof}(std::max_align_t)}. It is \impldef{support for extended alignments} +whether any extended alignments are supported and the contexts in which they are +supported\iref{dcl.align}. A type having an extended alignment +requirement is an \defnadj{over-aligned}{type}. \begin{note} -Lookup from a program point -before the \grammarterm{class-specifier} of a class -will find no bindings in the class scope. -\begin{example} -\begin{codeblock} -template -struct B { - D::type x; // \#1 -}; - -struct A { using type = int; }; -struct C : A, B {}; // error at \#1: \tcode{C::type} not found -\end{codeblock} -\end{example} +Every over-aligned type is or contains a class type +to which extended alignment applies (possibly through a non-static data member). \end{note} - -\rSec2[basic.scope.enum]{Enumeration scope}% +A \defnadj{new-extended}{alignment} is represented by +an alignment greater than \mname{STDCPP_DEFAULT_NEW_ALIGNMENT}\iref{cpp.predefined}. \pnum -Any declaration of an enumeration $E$ introduces -an \defnadj{enumeration}{scope} -that includes the \grammarterm{enumerator-list} of -the \grammarterm{enum-specifier} for $E$ (if any). - -\rSec2[basic.scope.temp]{Template parameter scope}% +Alignments are represented as values of the type \tcode{std::size_t}. +Valid alignments include only those values returned by an \keyword{alignof} +expression for the fundamental types plus an additional \impldef{alignment additional +values} +set of values, which may be empty. +Every alignment value shall be a non-negative integral power of two. \pnum -Each template \grammarterm{template-parameter} introduces -a \defnadj{template parameter}{scope} -that includes the \grammarterm{template-head} of -the \grammarterm{template-parameter}. +Alignments have an order from \defnx{weaker}{alignment!weaker} to +\defnx{stronger}{alignment!stronger} or \defnx{stricter}{alignment!stricter} alignments. Stricter +alignments have larger alignment values. An address that satisfies an alignment +requirement also satisfies any weaker valid alignment requirement. \pnum -Each \grammarterm{template-declaration} $D$ introduces -a template parameter scope -that extends from the beginning of its \grammarterm{template-parameter-list} -to the end of the \grammarterm{template-declaration}. -Any declaration outside the \grammarterm{template-parameter-list} -that would inhabit that scope instead inhabits the same scope as $D$. -The parent scope of any scope $S$ that is not a template parameter scope -is the smallest scope that contains $S$ and is not a template parameter scope. +The alignment requirement of a complete type can be queried using an +\keyword{alignof} expression\iref{expr.alignof}. Furthermore, +the narrow character types\iref{basic.fundamental} shall have the weakest +alignment requirement. \begin{note} -Therefore, only template parameters belong to a template parameter scope, and -only template parameter scopes have -a template parameter scope as a parent scope. +This enables the ordinary character types to be used as the +underlying type for an aligned memory area\iref{dcl.align}. \end{note} -\indextext{scope|)} - -\rSec1[basic.lookup]{Name lookup}% +\pnum +Comparing alignments is meaningful and provides the obvious results: -\indextext{lookup!name|(} +\begin{itemize} +\item Two alignments are equal when their numeric values are equal. +\item Two alignments are different when their numeric values are not equal. +\item When an alignment is larger than another it represents a stricter alignment. +\end{itemize} -\rSec2[basic.lookup.general]{General}% -\indextext{scope!name lookup and|see{lookup, name}}% +\pnum +\begin{note} +The runtime pointer alignment function\iref{ptr.align} +can be used to obtain an aligned pointer within a buffer; +an \grammarterm{alignment-specifier}\iref{dcl.align} +can be used to align storage explicitly. +\end{note} \pnum -The name lookup rules apply uniformly to all names (including -\grammarterm{typedef-name}{s}\iref{dcl.typedef}, -\grammarterm{namespace-name}{s}\iref{basic.namespace}, and -\grammarterm{class-name}{s}\iref{class.name}) wherever the grammar allows -such names in the context discussed by a particular rule. Name lookup -associates the use of a name with a set of declarations\iref{basic.def} of -that name. -Unless otherwise specified, -the program is ill-formed if no declarations are found. -If the declarations found by name lookup -all denote functions or function templates, -the declarations are said to form an \defn{overload set}. -Otherwise, -if the declarations found by name lookup do not all denote the same entity, -\indextext{lookup!ambiguous}% -they are \defn{ambiguous} and the program is ill-formed. -Overload resolution\iref{over.match,over.over} -takes place after name lookup has succeeded. The access rules\iref{class.access} -are considered only once name lookup and -function overload resolution (if applicable) have succeeded. Only after -name lookup, function overload resolution (if applicable) and access -checking have succeeded -are the semantic properties introduced by the declarations -used in further processing. +If a request for a specific extended alignment in a specific context is not +supported by an implementation, the program is ill-formed. + +\rSec2[class.temporary]{Temporary objects} \pnum -A program point $P$ is said to follow -any declaration in the same translation unit -whose locus\iref{basic.scope.pdecl} is before $P$. +\indextext{object temporary|see{temporary}}% +\indextext{temporary}% +\indextext{optimization of temporary|see{temporary, elimination of}}% +\indextext{temporary!elimination of}% +\indextext{temporary!implementation-defined generation of}% +Temporary objects are created +\begin{itemize} +\item +when a prvalue is converted to an xvalue\iref{conv.rval} and +\item +when needed by the implementation to pass or return an object of trivially copyable type (see below). +\end{itemize} +Even when the creation of the temporary object is +unevaluated\iref{expr.context}, +all the semantic restrictions shall be respected as if the temporary object +had been created and later destroyed. \begin{note} -The declaration might appear in a scope that does not contain $P$. +This includes accessibility\iref{class.access} and whether it is deleted, +for the constructor selected and for the destructor. However, in the special +case of the operand of a +\grammarterm{decltype-specifier}\iref{dcl.type.decltype}, no temporary is introduced, +so the foregoing does not apply to such a prvalue. \end{note} -\indextext{precede|see{declaration, precede}}% -A declaration $X$ \defnx{precedes}{declaration!precede} -a program point $P$ in a translation unit $L$ -if $P$ follows $X$, $X$ inhabits a class scope and is reachable from $P$, or -else $X$ appears in a translation unit $D$ and + +\pnum +The materialization of a temporary object is generally +delayed as long as possible +in order to avoid creating unnecessary temporary objects. +\begin{note} +Temporary objects are materialized: \begin{itemize} \item -$P$ follows -a \grammarterm{module-import-declaration} or \grammarterm{module-declaration} -that imports $D$ (directly or indirectly), and +when binding a reference to a prvalue\iref{dcl.init.ref,expr.type.conv, +expr.dynamic.cast,expr.static.cast,expr.const.cast,expr.cast}, \item -$X$ appears after the \grammarterm{module-declaration} in $D$ (if any) and -before the \grammarterm{private-module-fragment} in $D$ (if any), and +when performing certain member accesses on a class prvalue\iref{expr.ref,expr.mptr.oper}, \item -either $X$ is exported or else $D$ and $L$ are part of the same module and -$X$ does not inhabit a namespace with internal linkage or -declare a name with internal linkage. -\begin{note} -Names declared by a \grammarterm{using-declaration} have no linkage. -\end{note} +when invoking an implicit object member function on a class prvalue\iref{expr.call}, +\item +when performing an array-to-pointer conversion or subscripting on an array prvalue\iref{conv.array,expr.sub}, +\item +when initializing an object of type \tcode{std::initializer_list} from a \grammarterm{braced-init-list}\iref{dcl.init.list}, +\item +for certain unevaluated operands\iref{expr.typeid,expr.sizeof}, and +\item +when a prvalue that has type other than \cv{}~\keyword{void} appears as a discarded-value expression\iref{expr.context}. \end{itemize} -\begin{note} -A \grammarterm{module-import-declaration} imports both -the named translation unit(s) and -any modules named by exported -\grammarterm{module-import-declaration}{s} within them, -recursively. +\end{note} \begin{example} -\begin{codeblocktu}{Translation unit \#1} -export module Q; -export int sq(int i) { return i*i; } -\end{codeblocktu} +Consider the following code: +\begin{codeblock} +class X { +public: + X(int); + X(const X&); + X& operator=(const X&); + ~X(); +}; -\begin{codeblocktu}{Translation unit \#2} -export module R; -export import Q; -\end{codeblocktu} +class Y { +public: + Y(int); + Y(Y&&); + ~Y(); +}; -\begin{codeblocktu}{Translation unit \#3} -import R; -int main() { return sq(9); } // OK, \tcode{sq} from module \tcode{Q} -\end{codeblocktu} -\end{example} -\end{note} - -\pnum -\indextext{scope!search!single}% -A \defnadj{single}{search} in a scope $S$ -for a name $N$ from a program point $P$ -finds all declarations that precede $P$ -to which any name that is the same as $N$\iref{basic.pre} is bound in $S$. -If any such declaration is a \grammarterm{using-declarator} -whose terminal name\iref{expr.prim.id.unqual} -is not dependent\iref{temp.dep.type}, -it is replaced by the declarations named by -the \grammarterm{using-declarator}\iref{namespace.udecl}. +X f(X); +Y g(Y); -\pnum -In certain contexts, only certain kinds of declarations are included. -After any such restriction, any declarations of classes or enumerations are discarded if any other declarations are found. -\begin{note} -A type (but not a \grammarterm{typedef-name} or template) -is therefore hidden by any other entity in its scope. -\end{note} -\indextext{type-only!lookup|see{lookup, type-only}}% -However, if a lookup is \defnx{type-only}{lookup!type-only}, -only declarations of -types and templates whose specializations are types are considered; -furthermore, if declarations -of a \grammarterm{typedef-name} and of the type to which it refers are found, -the declaration of the \grammarterm{typedef-name} is discarded -instead of the type declaration. +void h() { + X a(1); + X b = f(X(2)); + Y c = g(Y(3)); + a = f(a); +} +\end{codeblock} -\rSec2[class.member.lookup]{Member name lookup}% -\indextext{lookup!member name}% -\indextext{ambiguity!base class member}% -\indextext{ambiguity!member access} +\indextext{class object copy|see{constructor, copy}}% +\indextext{constructor!copy}% +\tcode{X(2)} is constructed in the space used to hold \tcode{f()}'s argument and +\tcode{Y(3)} is constructed in the space used to hold \tcode{g()}'s argument. +Likewise, +\tcode{f()}'s result is constructed directly in \tcode{b} and +\tcode{g()}'s result is constructed directly in \tcode{c}. +On the other hand, the expression +\tcode{a = f(a)} +requires a temporary for +the result of \tcode{f(a)}, +which is materialized so that the reference parameter +of \tcode{X::operator=(const X\&)} can bind to it. +\end{example} \pnum -\indextext{scope!search}% -A \defn{search} in a scope $X$ for a name $M$ from a program point $P$ -is a single search in $X$ for $M$ from $P$ -unless $X$ is the scope of a class or class template $T$, in which case the -following steps define the result of the search. +When an object of class type \tcode{X} +is passed to or returned from a potentially-evaluated function call, +if \tcode{X} has at least one eligible copy or move constructor\iref{special}, +each such constructor is trivial, +and the destructor of \tcode{X} is either trivial or deleted, +implementations are permitted +to create a temporary object +to hold the function parameter or result object. +The temporary object is constructed +from the function argument or return value, respectively, +and the function's parameter or return object +is initialized as if by +using the eligible trivial constructor to copy the temporary +(even if that constructor is inaccessible +or would not be selected by overload resolution +to perform a copy or move of the object). \begin{note} -The result differs only -if $M$ is a \grammarterm{conversion-function-id} or -if the single search would find nothing. +This latitude is granted to allow objects of class type to be passed to or returned from functions in registers. \end{note} \pnum -The \defn{lookup set} for a name $N$ in a class or class template $C$, called $S(N,C)$, -consists of two component sets: -the \term{declaration set}, a set of members named $N$; and -the \term{subobject set}, -a set of subobjects where declarations of these members were found -(possibly via \grammarterm{using-declaration}{s}). -In the declaration set, type declarations (including injected-class-names) -are replaced by the types they designate. $S(N,C)$ is calculated as follows: - -\pnum -The declaration set is the result of -a single search in the scope of $C$ for $N$ -from immediately after the \grammarterm{class-specifier} of $C$ -if $P$ is in a complete-class context of $C$ or -from $P$ otherwise. -If the resulting declaration set is not empty, the subobject set -contains $C$ itself, and calculation is complete. +\indextext{temporary!constructor for}% +\indextext{temporary!destructor for}% +\indextext{temporary!destruction of}% +Temporary objects are destroyed as the last step +in evaluating +the full-expression\iref{intro.execution} +that (lexically) contains the point where +they were created. +This is true even if that evaluation ends in throwing an exception. +The +\indextext{value computation}% +value computations and +\indextext{side effects}% +side effects of destroying a temporary object +are associated only with the full-expression, not with any specific +subexpression. \pnum -Otherwise (i.e., $C$ does not contain a declaration of $N$ -or the resulting declaration set is empty), $S(N,C)$ is initially empty. -Calculate the lookup set for $N$ -in each direct non-dependent\iref{temp.dep.type} base class subobject $B_i$, and -merge each such lookup set $S(N,B_i)$ in turn into $S(N,C)$. -\begin{note} -If $C$ is incomplete, -only base classes whose \grammarterm{base-specifier} appears before $P$ -are considered. -If $C$ is an instantiated class, its base classes are not dependent. -\end{note} +\indextext{initializer!temporary and declarator}% +\indextext{temporary!order of destruction of}% +There are five contexts in which temporaries are destroyed at a different +point than the end of the full-expression. +The first context is when a default constructor is called to initialize +an element of an array with no corresponding initializer\iref{dcl.init}. +The second context is when a copy constructor is called to copy an element of +an array while the entire array is copied\iref{expr.prim.lambda.capture,class.copy.ctor}. +In either case, if the constructor has one or more default arguments, +the destruction of every temporary created in a default argument is +sequenced before the construction of the next array element, if any. \pnum -The following steps define the result of merging lookup set $S(N,B_i)$ -into the intermediate $S(N,C)$: - +The third context is when a reference binds to a temporary object. +\begin{footnote} +The same rules apply to initialization of an + \tcode{initializer_list} object\iref{dcl.init.list} with its + underlying temporary array. +\end{footnote} +The temporary object to which the reference is bound or the temporary object +that is the complete object of a subobject to which the reference is bound +persists for the lifetime of the reference if the glvalue +to which the reference is bound +was obtained through one of the following: \begin{itemize} -\item If each of the subobject members of $S(N,B_i)$ is a base class -subobject of at least one of the subobject members of $S(N,C)$, or if -$S(N,B_i)$ is empty, $S(N,C)$ is unchanged and the merge is complete. -Conversely, if each of the subobject members of $S(N,C)$ is a base class -subobject of at least one of the subobject members of $S(N,B_i)$, or if -$S(N,C)$ is empty, the new $S(N,C)$ is a copy of $S(N,B_i)$. - -\item Otherwise, if the declaration sets of $S(N,B_i)$ and $S(N,C)$ -differ, the merge is ambiguous: the new $S(N,C)$ is a lookup set with an -invalid declaration set and the union of the subobject sets. In -subsequent merges, an invalid declaration set is considered different -from any other. - -\item Otherwise, the new $S(N,C)$ is a lookup set with the shared set of -declarations and the union of the subobject sets. +\item + a temporary materialization conversion\iref{conv.rval}, +\item + \tcode{(} \grammarterm{expression} \tcode{)}, + where \grammarterm{expression} is one of these expressions, +\item + subscripting\iref{expr.sub} of an array operand, + where that operand is one of these expressions, +\item + a class member access\iref{expr.ref} using the \tcode{.} operator + where the left operand is one of these expressions and + the right operand designates a non-static data member of non-reference type, +\item + a pointer-to-member operation\iref{expr.mptr.oper} using the \tcode{.*} operator + where the left operand is one of these expressions and + the right operand is a pointer to data member of non-reference type, +\item + a + \begin{itemize} + \item \keyword{const_cast}\iref{expr.const.cast}, + \item \keyword{static_cast}\iref{expr.static.cast}, + \item \keyword{dynamic_cast}\iref{expr.dynamic.cast}, or + \item \keyword{reinterpret_cast}\iref{expr.reinterpret.cast} + \end{itemize} + converting, without a user-defined conversion, + a glvalue operand that is one of these expressions + to a glvalue that refers + to the object designated by the operand, or + to its complete object or a subobject thereof, +\item + a conditional expression\iref{expr.cond} that is a glvalue + where the second or third operand is one of these expressions, or +\item + a comma expression\iref{expr.comma} that is a glvalue + where the right operand is one of these expressions. \end{itemize} - -\pnum -The result of the search is the declaration set of $S(M,T)$. -If it is an invalid set, the program is ill-formed. -If it differs from the result of a search in $T$ for $M$ -in a complete-class context\iref{class.mem} of $T$, -the program is ill-formed, no diagnostic required. \begin{example} \begin{codeblock} -struct A { int x; }; // S(x,A) = \{ \{ \tcode{A::x} \}, \{ \tcode{A} \} \} -struct B { float x; }; // S(x,B) = \{ \{ \tcode{B::x} \}, \{ \tcode{B} \} \} -struct C: public A, public B { }; // S(x,C) = \{ invalid, \{ \tcode{A} in \tcode{C}, \tcode{B} in \tcode{C} \} \} -struct D: public virtual C { }; // S(x,D) = S(x,C) -struct E: public virtual C { char x; }; // S(x,E) = \{ \{ \tcode{E::x} \}, \{ \tcode{E} \} \} -struct F: public D, public E { }; // S(x,F) = S(x,E) -int main() { - F f; - f.x = 0; // OK, lookup finds \tcode{E::x} -} -\end{codeblock} +template using id = T; -$S(\tcode{x},\tcode{F})$ is unambiguous because the \tcode{A} and \tcode{B} base -class subobjects of \tcode{D} are also base class subobjects of \tcode{E}, so -$S(\tcode{x},\tcode{D})$ is discarded in the first merge step. +int i = 1; +int&& a = id{1, 2, 3}[i]; // temporary array has same lifetime as \tcode{a} +const int& b = static_cast(0); // temporary \tcode{int} has same lifetime as \tcode{b} +int&& c = cond ? id{1, 2, 3}[i] : static_cast(0); + // exactly one of the two temporaries is lifetime-extended +\end{codeblock} \end{example} - -\pnum -If $M$ is a non-dependent \grammarterm{conversion-function-id}, -conversion function templates that are members of $T$ are considered. -For each such template $F$, the lookup set $S(t,T)$ is constructed, -considering a function template declaration to have the name $t$ -only if it corresponds to a declaration of $F$\iref{basic.scope.scope}. -The members of the declaration set of each such lookup set, -which shall not be an invalid set, are included in the result. -\begin{note} -Overload resolution will discard those -that cannot convert to the type specified by $M$\iref{temp.over}. -\end{note} - -\pnum \begin{note} -A static member, a nested type or an enumerator defined in a base class -\tcode{T} can unambiguously be found even if an object has more than one -base class subobject of type \tcode{T}. Two base class subobjects share -the non-static member subobjects of their common virtual base classes. -\end{note} +An explicit type conversion\iref{expr.type.conv,expr.cast} +is interpreted as +a sequence of elementary casts, +covered above. \begin{example} \begin{codeblock} -struct V { - int v; -}; -struct A { - int a; - static int s; - enum { e }; -}; -struct B : A, virtual V { }; -struct C : A, virtual V { }; -struct D : B, C { }; - -void f(D* pd) { - pd->v++; // OK, only one \tcode{v} (virtual) - pd->s++; // OK, only one \tcode{s} (static) - int i = pd->e; // OK, only one \tcode{e} (enumerator) - pd->a++; // error: ambiguous: two \tcode{a}{s} in \tcode{D} -} +const int& x = (const int&)1; // temporary for value 1 has same lifetime as x \end{codeblock} \end{example} - -\pnum -\begin{note} -\indextext{dominance!virtual base class}% -When virtual base classes are used, a hidden declaration can be reached -along a path through the subobject lattice that does not pass through -the hiding declaration. This is not an ambiguity. The identical use with -non-virtual base classes is an ambiguity; in that case there is no -unique instance of the name that hides all the others. \end{note} +\begin{note} +If a temporary object has a reference member initialized by another temporary object, +lifetime extension applies recursively to such a member's initializer. \begin{example} \begin{codeblock} -struct V { int f(); int x; }; -struct W { int g(); int y; }; -struct B : virtual V, W { - int f(); int x; - int g(); int y; +struct S { + const int& m; }; -struct C : virtual V, W { }; - -struct D : B, C { void glorp(); }; -\end{codeblock} - -\begin{importgraphic} -{Name lookup} -{class.lookup} -{figname.pdf} -\end{importgraphic} - -As illustrated in \fref{class.lookup}, -the names declared in \tcode{V} and the left-hand instance of \tcode{W} -are hidden by those in \tcode{B}, but the names declared in the -right-hand instance of \tcode{W} are not hidden at all. -\begin{codeblock} -void D::glorp() { - x++; // OK, \tcode{B::x} hides \tcode{V::x} - f(); // OK, \tcode{B::f()} hides \tcode{V::f()} - y++; // error: \tcode{B::y} and \tcode{C}'s \tcode{W::y} - g(); // error: \tcode{B::g()} and \tcode{C}'s \tcode{W::g()} -} +const S& s = S{1}; // both \tcode{S} and \tcode{int} temporaries have lifetime of \tcode{s} \end{codeblock} \end{example} -\indextext{ambiguity!class conversion}% +\end{note} -\pnum -An explicit or implicit conversion from a pointer to or -an expression designating an object -of a -derived class to a pointer or reference to one of its base classes shall -unambiguously refer to a unique object representing the base class. -\begin{example} -\begin{codeblock} -struct V { }; -struct A { }; -struct B : A, virtual V { }; -struct C : A, virtual V { }; -struct D : B, C { }; +The exceptions to this lifetime rule are: +\begin{itemize} +\item A temporary object bound to a reference parameter in a function call\iref{expr.call} +persists until the completion of the full-expression containing the call. -void g() { - D d; - B* pb = &d; - A* pa = &d; // error: ambiguous: \tcode{C}'s \tcode{A} or \tcode{B}'s \tcode{A}? - V* pv = &d; // OK, only one \tcode{V} subobject -} -\end{codeblock} -\end{example} +\item A temporary object bound to a reference element of +an aggregate of class type initialized from +a parenthesized \grammarterm{expression-list}\iref{dcl.init} +persists until the completion of the full-expression +containing the \grammarterm{expression-list}. -\pnum +\item A temporary bound to a reference in a \grammarterm{new-initializer}\iref{expr.new} persists until the completion of the full-expression containing the \grammarterm{new-initializer}. \begin{note} -Even if the result of name lookup is unambiguous, use of a name found in -multiple subobjects might still be -ambiguous\iref{conv.mem,expr.ref,class.access.base}. +This might introduce a dangling reference. \end{note} \begin{example} \begin{codeblock} -struct B1 { - void f(); - static void f(int); - int i; -}; -struct B2 { - void f(double); -}; -struct I1: B1 { }; -struct I2: B1 { }; - -struct D: I1, I2, B2 { - using B1::f; - using B2::f; - void g() { - f(); // Ambiguous conversion of \keyword{this} - f(0); // Unambiguous (static) - f(0.0); // Unambiguous (only one \tcode{B2}) - int B1::* mpB1 = &D::i; // Unambiguous - int D::* mpD = &D::i; // Ambiguous conversion - } -}; +struct S { int mi; const std::pair& mp; }; +S a { 1, {2,3} }; +S* p = new S{ 1, {2,3} }; // creates dangling reference \end{codeblock} \end{example} - -\rSec2[basic.lookup.unqual]{Unqualified name lookup} - -\indextext{name!unqualified}% - -\pnum -A \grammarterm{using-directive} is -\term{active} in a scope $S$ at a program point $P$ -if it precedes $P$ and inhabits either $S$ or -the scope of a namespace nominated by a \grammarterm{using-directive} -that is active in $S$ at $P$. +\end{itemize} \pnum -An \term{unqualified search} in a scope $S$ from a program point $P$ -includes the results of searches from $P$ in -\begin{itemize} -\item -$S$, and -\item -for any scope $U$ that contains $P$ and is or is contained by $S$, -each namespace contained by $S$ that is nominated by -a \grammarterm{using-directive} that is active in $U$ at $P$. -\end{itemize} -If no declarations are found, -the results of the unqualified search are -the results of an unqualified search in the parent scope of $S$, if any, -from $P$. -\begin{note} -When a class scope is searched, -the scopes of its base classes are also searched\iref{class.member.lookup}. -If it inherits from a single base, -it is as if the scope of the base immediately contains -the scope of the derived class. -Template parameter scopes -that are associated with one scope in the chain of parents -are also considered\iref{temp.local}. -\end{note} +The fourth context is when a temporary object +is created in the \grammarterm{for-range-initializer} of a range-based \keyword{for} statement. +If such a temporary object would otherwise be destroyed +at the end of the \grammarterm{for-range-initializer} full-expression, +the object persists for the lifetime of the reference +initialized by the \grammarterm{for-range-initializer}. \pnum -\defnx{Unqualified name lookup}{lookup!unqualified name} -from a program point performs an unqualified search in its immediate scope. +The fifth context is when a temporary object +is created in a structured binding declaration\iref{dcl.struct.bind}. +Any temporary objects introduced by +the \grammarterm{initializer}{s} for the variables +with unique names +are destroyed at the end of the structured binding declaration. \pnum -An \defnadj{unqualified}{name} is a name -that does not immediately follow a \grammarterm{nested-name-specifier} or -the \tcode{.} or \tcode{->} in a class member access expression\iref{expr.ref}, -possibly after a \keyword{template} keyword or \tcode{\~}. -Unless otherwise specified, -such a name undergoes unqualified name lookup from the point where it appears. +Let \tcode{x} and \tcode{y} each be either +a temporary object whose lifetime is not extended, or +a function parameter. +If the lifetimes of \tcode{x} and \tcode{y} end at +the end of the same full-expression, and +\tcode{x} is initialized before \tcode{y}, then +the destruction of \tcode{y} is sequenced before that of \tcode{x}. +If the lifetime of two or more temporaries +with lifetimes extending beyond the full-expressions in which they were created +ends at the same point, +these temporaries are destroyed at that point in the reverse order of the +completion of their construction. +In addition, the destruction of such temporaries shall +take into account the ordering of destruction of objects with static, thread, or +automatic storage duration\iref{basic.stc.static,basic.stc.thread,basic.stc.auto}; +that is, if +\tcode{obj1} +is an object with the same storage duration as the temporary and +created before the temporary is created +the temporary shall be destroyed before +\tcode{obj1} +is destroyed; +if +\tcode{obj2} +is an object with the same storage duration as the temporary and +created after the temporary is created +the temporary shall be destroyed after +\tcode{obj2} +is destroyed. \pnum -An unqualified name that is a component name\iref{expr.prim.id.unqual} of -a \grammarterm{type-specifier} or \grammarterm{ptr-operator} of -a \grammarterm{conversion-type-id} is looked up in the same fashion -as the \grammarterm{conversion-function-id} in which it appears. -If that lookup finds nothing, it undergoes unqualified name lookup; -in each case, only names -that denote types or templates whose specializations are types are considered. \begin{example} \begin{codeblock} -struct T1 { struct U { int i; }; }; -struct T2 { }; -struct U1 {}; -struct U2 {}; - -struct B { - using T = T1; - using U = U1; - operator U1 T1::*(); - operator U1 T2::*(); - operator U2 T1::*(); - operator U2 T2::*(); +struct S { + S(); + S(int); + friend S operator+(const S&, const S&); + ~S(); }; - -template -int g() { - using U = U2; - X().operator U T::*(); // \#1, searches for \tcode{T} in the scope of \tcode{X} first - X().operator U decltype(T())::*(); // \#2 - return 0; -} -int x = g(); // \#1 calls \tcode{B::operator U1 T1::*} - // \#2 calls \tcode{B::operator U1 T2::*} +S obj1; +const S& cr = S(16)+S(23); +S obj2; \end{codeblock} -\end{example} -\pnum -In a friend declaration \grammarterm{declarator} -whose \grammarterm{declarator-id} is a \grammarterm{qualified-id} -whose lookup context\iref{basic.lookup.qual} is a class or namespace $S$, -lookup for an unqualified name -that appears after the \grammarterm{declarator-id} -performs a search in the scope associated with $S$. -If that lookup finds nothing, it undergoes unqualified name lookup. -\begin{example} -\begin{codeblock} -using I = int; -using D = double; -namespace A { - inline namespace N {using C = char; } - using F = float; - void f(I); - void f(D); - void f(C); - void f(F); -} -struct X0 {using F = float; }; -struct W { - using D = void; - struct X : X0 { - void g(I); - void g(::D); - void g(F); - }; -}; -namespace B { - typedef short I, F; - class Y { - friend void A::f(I); // error: no \tcode{void A::f(short)} - friend void A::f(D); // OK - friend void A::f(C); // error: \tcode{A::N::C} not found - friend void A::f(F); // OK - friend void W::X::g(I); // error: no \tcode{void X::g(short)} - friend void W::X::g(D); // OK - friend void W::X::g(F); // OK - }; -} -\end{codeblock} -\end{example} - -\rSec2[basic.lookup.argdep]{Argument-dependent name lookup}% -\indextext{lookup!argument-dependent} - -\pnum -When the \grammarterm{postfix-expression} in -a function call\iref{expr.call} is an \grammarterm{unqualified-id}, -and unqualified lookup\iref{basic.lookup.unqual} -for the name in the \grammarterm{unqualified-id} does not find any -\begin{itemize} -\item -declaration of a class member, or -\item -function declaration inhabiting a block scope, or -\item -declaration not of a function or function template -\end{itemize} -then lookup for the name also includes the result of -\defnadj{argument-dependent}{lookup} in a set of associated namespaces -that depends on the types of the arguments -(and for template template arguments, the namespace of the template argument), -as specified below. -\begin{example} -\begin{codeblock} -namespace N { - struct S { }; - void f(S); -} - -void g() { - N::S s; - f(s); // OK, calls \tcode{N::f} - (f)(s); // error: \tcode{N::f} not considered; parentheses prevent argument-dependent lookup -} -\end{codeblock} -\end{example} - -\pnum -\begin{note} -For purposes of determining -(during parsing) whether an expression is a -\grammarterm{postfix-expression} for a function call, the usual name lookup -rules apply. -In some cases -a name followed by \tcode{<} is treated as a \grammarterm{template-name} -even though name lookup did not find a \grammarterm{template-name} -(see \ref{temp.names}). -For example, -\begin{codeblock} -int h; -void g(); -namespace N { - struct A {}; - template int f(T); - template int g(T); - template int h(T); -} - -int x = f(N::A()); // OK, lookup of \tcode{f} finds nothing, \tcode{f} treated as template name -int y = g(N::A()); // OK, lookup of \tcode{g} finds a function, \tcode{g} treated as template name -int z = h(N::A()); // error: \tcode{h<} does not begin a \grammarterm{template-id} -\end{codeblock} - -The rules have no effect on the syntactic interpretation of an expression. -For example, -\begin{codeblock} -typedef int f; -namespace N { - struct A { - friend void f(A &); - operator int(); - void g(A a) { - int i = f(a); // \tcode{f} is the typedef, not the friend function: equivalent to \tcode{int(a)} - } - }; -} -\end{codeblock} -Because the expression is not a function call, -argument-dependent name lookup does not apply and -the friend function \tcode{f} is not found. -\end{note} - -\pnum -For each argument type \tcode{T} in the function call, -there is a set of zero or more \defnx{associated entities}{entity!associated} -to be considered. -The set of entities is determined entirely by -the types of the function arguments -(and any template template arguments). -Any \grammarterm{typedef-name}s and \grammarterm{using-declaration}{s} -used to specify the types -do not contribute to this set. -The set of entities -is determined in the following way: -\begin{itemize} -\item If \tcode{T} is a fundamental type, its associated set of -entities is empty. - -\item If \tcode{T} is a class type (including unions), -its associated entities are: -the class itself; -the class of which it is a member, if any; -and, if it is a complete type, its direct and indirect base classes. -Furthermore, if \tcode{T} is a class template specialization, -its associated entities also include: -the entities -associated with the types of the template arguments -provided for template type parameters; -the templates used as template template arguments; and -the classes of which any member templates used as template template -arguments are members. -\begin{note} -Non-type template arguments do not -contribute to the set of associated entities. -\end{note} - -\item If \tcode{T} is an enumeration type, -its associated entities are \tcode{T} -and, if it is a class member, the member's class. - -\item If \tcode{T} is a pointer to \tcode{U} or an array of \tcode{U}, -its associated entities are those associated with \tcode{U}. - -\item If \tcode{T} is a function type, its associated -entities are those associated with the function parameter types and those -associated with the return type. - -\item If \tcode{T} is a pointer to a member function of a class -\tcode{X}, its associated entities are those associated -with the function parameter types and return type, together with those -associated with \tcode{X}. - -\item If \tcode{T} is a pointer to a data member of class \tcode{X}, its -associated entities are those associated with the member -type together with those associated with \tcode{X}. -\end{itemize} -In addition, if the argument is an overload set or the address of such a set, -its associated entities -are the union of those associated with each of the -members of the set, i.e., the entities associated with its -parameter types and return type. -Additionally, if the aforementioned overload set is named with -a \grammarterm{template-id}, its associated entities also include -its template \grammarterm{template-argument}{s} and -those associated with its type \grammarterm{template-argument}s. - -\pnum -The \term{associated namespaces} for a call are -the innermost enclosing non-inline namespaces for its associated entities -as well as every element of the inline namespace set\iref{namespace.def} -of those namespaces. -Argument-dependent lookup finds -all declarations of functions and function templates that -\begin{itemize} -\item -are found by a search of any associated namespace, or -\item -are declared as a friend\iref{class.friend} of any class -with a reachable definition in the set of associated entities, or -\item -are exported, -are attached to a named module \tcode{M}\iref{module.interface}, -do not appear in the translation unit containing the point of the lookup, and -have the same innermost enclosing non-inline namespace scope as -a declaration of an associated entity attached to \tcode{M}\iref{basic.link}. -\end{itemize} -If the lookup is for a dependent name\iref{temp.dep,temp.dep.candidate}, -the above lookup is also performed -from each point in the instantiation context\iref{module.context} of the lookup, -additionally ignoring any declaration that -appears in another translation unit, -is attached to the global module, and -is either discarded\iref{module.global.frag} or has internal linkage. - -\pnum -\begin{example} -\begin{codeblocktu}{Translation unit \#1} -export module M; -namespace R { - export struct X {}; - export void f(X); -} -namespace S { - export void f(R::X, R::X); -} -\end{codeblocktu} - -\begin{codeblocktu}{Translation unit \#2} -export module N; -import M; -export R::X make(); -namespace R { static int g(X); } -export template void apply(T t, U u) { - f(t, u); - g(t); -} -\end{codeblocktu} - -\begin{codeblocktu}{Translation unit \#3} -module Q; -import N; -namespace S { - struct Z { template operator T(); }; -} -void test() { - auto x = make(); // OK, \tcode{decltype(x)} is \tcode{R::X} in module \tcode{M} - R::f(x); // error: \tcode{R} and \tcode{R::f} are not visible here - f(x); // OK, calls \tcode{R::f} from interface of \tcode{M} - f(x, S::Z()); // error: \tcode{S::f} in module \tcode{M} not considered - // even though \tcode{S} is an associated namespace - apply(x, S::Z()); // error: \tcode{S::f} is visible in instantiation context, but - // \tcode{R::g} has internal linkage and cannot be used outside TU \#2 -} -\end{codeblocktu} -\end{example} - -\pnum -\begin{note} -The associated namespace can include namespaces -already considered by ordinary unqualified lookup. -\end{note} -\begin{example} -\begin{codeblock} -namespace NS { - class T { }; - void f(T); - void g(T, int); -} -NS::T parm; -void g(NS::T, float); -int main() { - f(parm); // OK, calls \tcode{NS::f} - extern void g(NS::T, float); - g(parm, 1); // OK, calls \tcode{g(NS::T, float)} -} -\end{codeblock} -\end{example} - -\rSec2[basic.lookup.qual]{Qualified name lookup} - -\rSec3[basic.lookup.qual.general]{General} - -\pnum -\indextext{lookup!qualified name|(}% -\indextext{name!qualified}% -\indextext{qualification!explicit}% -Lookup of an \grammarterm{identifier} -followed by a \tcode{::} scope resolution operator -considers only -namespaces, types, and templates whose specializations are types. -If a name, \grammarterm{template-id}, or \grammarterm{computed-type-specifier} -is followed by a \tcode{::}, -it shall designate a namespace, class, enumeration, or dependent type, -and the \tcode{::} is never interpreted as -a complete \grammarterm{nested-name-specifier}. -\begin{example} -\begin{codeblock} -class A { -public: - static int n; -}; -int main() { - int A; - A::n = 42; // OK - A b; // error: \tcode{A} does not name a type -} -template struct B : A {}; -namespace N { - template void B(); - int f() { - return B<0>::n; // error: \tcode{N::B<0>} is not a type - } -} -\end{codeblock} -\end{example} - -\indextext{operator!scope resolution}% -\indextext{scope resolution operator|see{operator, scope resolution}}% - -\pnum -A member-qualified name is -the (unique) component name\iref{expr.prim.id.unqual}, if any, of -\begin{itemize} -\item -an \grammarterm{unqualified-id} or -\item -a \grammarterm{nested-name-specifier} of the form -\grammarterm{type-name} \tcode{::} or \grammarterm{namespace-name} \tcode{::} -\end{itemize} -in the \grammarterm{id-expression} of a class member access expression\iref{expr.ref}. -A \defnadj{qualified}{name} is -\begin{itemize} -\item a member-qualified name or -\item the terminal name of -\begin{itemize} -\item a \grammarterm{qualified-id}, -\item a \grammarterm{using-declarator}, -\item a \grammarterm{typename-specifier}, -\item a \grammarterm{qualified-namespace-specifier}, or -\item a \grammarterm{nested-name-specifier}, -\grammarterm{elaborated-type-specifier}, or -\grammarterm{class-or-decltype} -that has a \grammarterm{nested-name-specifier}\iref{expr.prim.id.qual}. -\end{itemize} -\end{itemize} -The \defn{lookup context} of a member-qualified name is -the type of its associated object expression -(considered dependent if the object expression is type-dependent). -The lookup context of any other qualified name is -the type, template, or namespace -nominated by the preceding \grammarterm{nested-name-specifier}. -\begin{note} -When parsing a class member access, -the name following the \tcode{->} or \tcode{.} is -a qualified name even though it is not yet known of which kind. -\end{note} -\begin{example} -In -\begin{codeblock} - N::C::m.Base::f() -\end{codeblock} -\tcode{Base} is a member-qualified name; -the other qualified names are \tcode{C}, \tcode{m}, and \tcode{f}. -\end{example} - -\pnum -\defnx{Qualified name lookup}{lookup!qualified name} -in a class, namespace, or enumeration performs -a search of the scope associated with it\iref{class.member.lookup} -except as specified below. -Unless otherwise specified, -a qualified name undergoes qualified name lookup in its lookup context -from the point where it appears -unless the lookup context either -is dependent and is not the current instantiation\iref{temp.dep.type} or -is not a class or class template. -If nothing is found by qualified lookup for a member-qualified name -that is the terminal name\iref{expr.prim.id.unqual} of -a \grammarterm{nested-name-specifier} and -is not dependent, it undergoes unqualified lookup. -\begin{note} -During lookup for a template specialization, no names are dependent. -\end{note} -\begin{example} -\begin{codeblock} -int f(); -struct A { - int B, C; - template using D = void; - using T = void; - void f(); -}; -using B = A; -template using C = A; -template using D = A; -template using X = A; - -template -void g(T *p) { // as instantiated for \tcode{g}: - p->X<0>::f(); // error: \tcode{A::X} not found in \tcode{((p->X) < 0) > ::f()} - p->template X<0>::f(); // OK, \tcode{::X} found in definition context - p->B::f(); // OK, non-type \tcode{A::B} ignored - p->template C<0>::f(); // error: \tcode{A::C} is not a template - p->template D<0>::f(); // error: \tcode{A::D<0>} is not a class type - p->T::f(); // error: \tcode{A::T} is not a class type -} -template void g(A*); -\end{codeblock} -\end{example} - -\pnum -If a qualified name $Q$ follows a \tcode{\~}: -\begin{itemize} -\item -If $Q$ is a member-qualified name, -it undergoes unqualified lookup as well as qualified lookup. -\item -Otherwise, its \grammarterm{nested-name-specifier} $N$ shall nominate a type. -If $N$ has another \grammarterm{nested-name-specifier} $S$, -$Q$ is looked up as if its lookup context were that nominated by $S$. -\item -Otherwise, if the terminal name of $N$ is a member-qualified name $M$, -$Q$ is looked up as if $\tcode{\~}Q$ appeared in place of $M$ (as above). -\item -Otherwise, $Q$ undergoes unqualified lookup. -\item -Each lookup for $Q$ considers only -types (if $Q$ is not followed by a \tcode{<}) and -templates whose specializations are types. -If it finds nothing or is ambiguous, it is discarded. -\item -The \grammarterm{type-name} that is or contains $Q$ -shall refer to its (original) lookup context (ignoring cv-qualification) under -the interpretation established by at least one (successful) lookup performed. -\end{itemize} -\begin{example} -\begin{codeblock} -struct C { - typedef int I; -}; -typedef int I1, I2; -extern int* p; -extern int* q; -void f() { - p->C::I::~I(); // \tcode{I} is looked up in the scope of \tcode{C} - q->I1::~I2(); // \tcode{I2} is found by unqualified lookup -} -struct A { - ~A(); -}; -typedef A AB; -int main() { - AB* p; - p->AB::~AB(); // explicitly calls the destructor for \tcode{A} -} -\end{codeblock} -\end{example} - -\rSec3[class.qual]{Class members} - -\indextext{lookup!class member}% - -\pnum -In a lookup for a qualified name $N$ whose lookup context is a class $C$ -in which function names are not ignored, -\begin{footnote} -Lookups in which -function names are ignored include names appearing in a -\grammarterm{nested-name-specifier}, an -\grammarterm{elaborated-type-specifier}, or a \grammarterm{base-specifier}. -\end{footnote} -\begin{itemize} -\item -if the search finds the injected-class-name of \tcode{C}\iref{class.pre}, or -\item -if $N$ is dependent and -is the terminal name of a \grammarterm{using-declarator}\iref{namespace.udecl} -that names a constructor, -\end{itemize} -$N$ is instead considered to name the constructor of class \tcode{C}. -Such a constructor name shall be used only -in the \grammarterm{declarator-id} of a (friend) declaration of a constructor or -in a \grammarterm{using-declaration}. -\begin{example} -\begin{codeblock} -struct A { A(); }; -struct B: public A { B(); }; - -A::A() { } -B::B() { } - -B::A ba; // object of type \tcode{A} -A::A a; // error: \tcode{A::A} is not a type name -struct A::A a2; // object of type \tcode{A} -\end{codeblock} -\end{example} - -\rSec3[namespace.qual]{Namespace members} - -\pnum -Qualified name lookup in a namespace $N$ additionally searches -every element of the inline namespace set of $N$\iref{namespace.def}. -If nothing is found, -the results of the lookup are the results of qualified name lookup -in each namespace nominated by a \grammarterm{using-directive} -that precedes the point of the lookup and -inhabits $N$ or an element of $N$'s inline namespace set. -\begin{note} -If a \grammarterm{using-directive} refers to a namespace -that has already been considered, it does not affect the result. -\end{note} -\begin{example} -\begin{codeblock} -int x; -namespace Y { - void f(float); - void h(int); -} - -namespace Z { - void h(double); -} - -namespace A { - using namespace Y; - void f(int); - void g(int); - int i; -} - -namespace B { - using namespace Z; - void f(char); - int i; -} - -namespace AB { - using namespace A; - using namespace B; - void g(); -} - -void h() -{ - AB::g(); // \tcode{g} is declared directly in \tcode{AB}, therefore \tcode{S} is $\{ \tcode{AB::g()} \}$ and \tcode{AB::g()} is chosen - - AB::f(1); // \tcode{f} is not declared directly in \tcode{AB} so the rules are applied recursively to \tcode{A} and \tcode{B}; - // namespace \tcode{Y} is not searched and \tcode{Y::f(float)} is not considered; - // \tcode{S} is $\{ \tcode{A::f(int)}, \tcode{B::f(char)} \}$ and overload resolution chooses \tcode{A::f(int)} - - AB::f('c'); // as above but resolution chooses \tcode{B::f(char)} - - AB::x++; // \tcode{x} is not declared directly in \tcode{AB}, and is not declared in \tcode{A} or \tcode{B}, so the rules - // are applied recursively to \tcode{Y} and \tcode{Z}, \tcode{S} is $\{ \}$ so the program is ill-formed - - AB::i++; // \tcode{i} is not declared directly in \tcode{AB} so the rules are applied recursively to \tcode{A} and \tcode{B}, - // \tcode{S} is $\{ \tcode{A::i}, \tcode{B::i} \}$ so the use is ambiguous and the program is ill-formed - - AB::h(16.8); // \tcode{h} is not declared directly in \tcode{AB} and not declared directly in \tcode{A} or \tcode{B} so the rules - // are applied recursively to \tcode{Y} and \tcode{Z}, \tcode{S} is $\{ \tcode{Y::h(int)}, \tcode{Z::h(double)} \}$ and - // overload resolution chooses \tcode{Z::h(double)} -} -\end{codeblock} -\end{example} - -\pnum -\begin{note} -The same declaration found more than once is not an ambiguity (because -it is still a unique declaration). -\begin{example} -\begin{codeblock} -namespace A { - int a; -} - -namespace B { - using namespace A; -} - -namespace C { - using namespace A; -} - -namespace BC { - using namespace B; - using namespace C; -} - -void f() -{ - BC::a++; // OK, \tcode{S} is $\{ \tcode{A::a}, \tcode{A::a} \}$ -} - -namespace D { - using A::a; -} - -namespace BD { - using namespace B; - using namespace D; -} - -void g() -{ - BD::a++; // OK, \tcode{S} is $\{ \tcode{A::a}, \tcode{A::a} \}$ -} -\end{codeblock} -\end{example} -\end{note} - -\pnum -\begin{example} -Because each referenced namespace is searched at most once, the -following is well-defined: -\begin{codeblock} -namespace B { - int b; -} - -namespace A { - using namespace B; - int a; -} - -namespace B { - using namespace A; -} - -void f() -{ - A::a++; // OK, \tcode{a} declared directly in \tcode{A}, \tcode{S} is $\{ \tcode{A::a} \}$ - B::a++; // OK, both \tcode{A} and \tcode{B} searched (once), \tcode{S} is $\{ \tcode{A::a} \}$ - A::b++; // OK, both \tcode{A} and \tcode{B} searched (once), \tcode{S} is $\{ \tcode{B::b} \}$ - B::b++; // OK, \tcode{b} declared directly in \tcode{B}, \tcode{S} is $\{ \tcode{B::b} \}$ -} -\end{codeblock} -\end{example} - -\pnum -\begin{note} -Class and enumeration declarations are not discarded -because of other declarations found in other searches. -\end{note} -\begin{example} -\begin{codeblock} -namespace A { - struct x { }; - int x; - int y; -} - -namespace B { - struct y { }; -} - -namespace C { - using namespace A; - using namespace B; - int i = C::x; // OK, \tcode{A::x} (of type \tcode{int}) - int j = C::y; // ambiguous, \tcode{A::y} or \tcode{B::y} -} -\end{codeblock} -\end{example} - -\indextext{lookup!qualified name|)}% - -\rSec2[basic.lookup.elab]{Elaborated type specifiers}% -\indextext{lookup!elaborated type specifier|(}% -\indextext{type specifier!elaborated} - -\pnum -If the \grammarterm{class-key} or \keyword{enum} keyword -in an \grammarterm{elaborated-type-specifier} -is followed by an \grammarterm{identifier} -that is not followed by \tcode{::}, -lookup for the \grammarterm{identifier} is type-only\iref{basic.lookup.general}. -\begin{note} -In general, the recognition of an \grammarterm{elaborated-type-specifier} -depends on the following tokens. -If the \grammarterm{identifier} is followed by \tcode{::}, -see \ref{basic.lookup.qual}. -\end{note} - -\pnum -If the terminal name of the \grammarterm{elaborated-type-specifier} -is a qualified name, -lookup for it is type-only. -If the name lookup does not find a previously declared \grammarterm{type-name}, -the \grammarterm{elaborated-type-specifier} is ill-formed. - -\pnum -\begin{example} -\begin{codeblock} -struct Node { - struct Node* Next; // OK, refers to injected-class-name \tcode{Node} - struct Data* Data; // OK, declares type \tcode{Data} at global scope and member \tcode{Data} -}; - -struct Data { - struct Node* Node; // OK, refers to \tcode{Node} at global scope - friend struct ::Glob; // error: \tcode{Glob} is not declared, cannot introduce a qualified type\iref{dcl.type.elab} - friend struct Glob; // OK, refers to (as yet) undeclared \tcode{Glob} at global scope. - @\commentellip@ -}; - -struct Base { - struct Data; // OK, declares nested \tcode{Data} - struct ::Data* thatData; // OK, refers to \tcode{::Data} - struct Base::Data* thisData; // OK, refers to nested \tcode{Data} - friend class ::Data; // OK, global \tcode{Data} is a friend - friend class Data; // OK, nested \tcode{Data} is a friend - struct Data { @\commentellip@ }; // Defines nested \tcode{Data} -}; - -struct Data; // OK, redeclares \tcode{Data} at global scope -struct ::Data; // error: cannot introduce a qualified type\iref{dcl.type.elab} -struct Base::Data; // error: cannot introduce a qualified type\iref{dcl.type.elab} -struct Base::Datum; // error: \tcode{Datum} undefined -struct Base::Data* pBase; // OK, refers to nested \tcode{Data} -\end{codeblock} -\end{example} -\indextext{lookup!elaborated type specifier|)}% - -\rSec2[basic.lookup.udir]{Using-directives and namespace aliases} - -\pnum -\indextext{lookup!using-directives and}% -\indextext{lookup!namespace aliases and}% -In a \grammarterm{using-directive} or \grammarterm{namespace-alias-definition}, -during the lookup for a \grammarterm{namespace-name} or for a name in a -\grammarterm{nested-name-specifier}{} -only namespace names are considered.% -\indextext{lookup!name|)}% - -\rSec1[basic.link]{Linkage}% -\indextext{linkage|(} - -\pnum -A name can have -\defnadj{external}{linkage}, -\defnadj{module}{linkage}, -\defnadj{internal}{linkage}, or -\defnadj{no}{linkage}, -as determined by the rules below. -\begin{note} -All declarations of an entity with a name with internal linkage -appear in the same translation unit. -All declarations of an entity with module linkage -are attached to the same module. -\end{note} - -\pnum -\indextext{linkage!\idxcode{static} and}% -\indextext{\idxcode{static}!linkage of}% -\indextext{linkage!\idxcode{const} and}% -\indextext{\idxcode{const}!linkage of}% -\indextext{linkage!\idxcode{inline} and}% -\indextext{\idxcode{inline}!linkage of}% -The name of an entity -that belongs to a namespace scope\iref{basic.scope.namespace} -has internal linkage if it is the name of -\begin{itemize} -\item - a variable, variable template, function, or function template that is - explicitly declared \keyword{static}; or -\item - a non-template variable of non-volatile const-qualified type, unless - \begin{itemize} - \item it is declared in the purview of a module interface unit - (outside the \grammarterm{private-module-fragment}, if any) or - module partition, or - \item it is explicitly declared \keyword{extern}, or - \item it is inline, or - \item it was previously declared and the prior declaration did - not have internal linkage; or - \end{itemize} -\item - a data member of an anonymous union. -\end{itemize} -\begin{note} -An instantiated variable template that has const-qualified type -can have external or module linkage, even if not declared \keyword{extern}. -\end{note} - -\pnum -An unnamed namespace or a namespace declared directly or indirectly within an -unnamed namespace has internal linkage. All other namespaces have external linkage. -The name of an entity that belongs to a namespace scope -that has not been given internal linkage above -and that is the name of -\begin{itemize} -\item a variable; or -\item a function; or -\item -\indextext{class!linkage of}% -a named class\iref{class.pre}, or an unnamed class defined in a -typedef declaration in which the class has the typedef name for linkage -purposes\iref{dcl.typedef}; or -\item -\indextext{enumeration!linkage of}% -a named enumeration\iref{dcl.enum}, or an unnamed enumeration defined -in a typedef declaration in which the enumeration has the typedef name -for linkage purposes\iref{dcl.typedef}; or -\item an unnamed enumeration -that has an enumerator as a name for linkage purposes\iref{dcl.enum}; or -\item a template -\end{itemize} -has its linkage determined as follows: -\begin{itemize} -\item -\indextext{friend function!linkage of}% -if the entity is a function or function template -first declared in a friend declaration and -that declaration is a definition and -the enclosing class is defined within an \grammarterm{export-declaration}, -the name has the same linkage, if any, -as the name of the enclosing class\iref{class.friend}; -\item -otherwise, -\indextext{friend function!linkage of}% -if the entity is a function or function template -declared in a friend declaration and -a corresponding non-friend declaration is reachable, -%FIXME: Which declaration is "that prior declaration"? -%FIXME: "prior" with respect to what? And what about dependent lookup? -the name has the linkage determined from that prior declaration, -\item -otherwise, -if the enclosing namespace has internal linkage, -the name has internal linkage; -\item -otherwise, -if the declaration of the name is -attached to a named module\iref{module.unit} -and is not exported\iref{module.interface}, -the name has module linkage; -\item -otherwise, -the name has external linkage. -\end{itemize} - -\pnum -In addition, -a member function, -a static data member, -a named class or enumeration that inhabits a class scope, or -an unnamed class or enumeration defined in a typedef declaration -that inhabits a class scope -such that the class or enumeration -has the typedef name for linkage purposes\iref{dcl.typedef}, -has the same linkage, if any, as the name of the class of which it is a member. - -\pnum -\begin{example} -\begin{codeblock} -static void f(); -extern "C" void h(); -static int i = 0; // \#1 -void q() { - extern void f(); // internal linkage - extern void g(); // \tcode{::g}, external linkage - extern void h(); // C language linkage - int i; // \#2: \tcode{i} has no linkage - { - extern void f(); // internal linkage - extern int i; // \#3: internal linkage - } -} -\end{codeblock} -Even though the declaration at line \#2 hides the declaration at line \#1, -the declaration at line \#3 still redeclares \#1 and receives internal linkage. -\end{example} - -\pnum -\indextext{linkage!no}% -Names not covered by these rules have no linkage. Moreover, except as -noted, a name declared at block scope\iref{basic.scope.block} has no -linkage. - -\pnum -Two declarations of entities declare the same entity -if, considering declarations of unnamed types to introduce their names -for linkage purposes, if any\iref{dcl.typedef,dcl.enum}, -they correspond\iref{basic.scope.scope}, -have the same target scope that is not a function or template parameter scope, -neither is a name-independent declaration, -and either -\begin{itemize} -\item -they appear in the same translation unit, or -\item -they both declare names with module linkage and are attached to the same module, or -\item -they both declare names with external linkage. -\end{itemize} -\begin{note} -There are other circumstances in which declarations declare the same entity% -\iref{dcl.link,temp.type,temp.spec.partial}. -\end{note} - -\pnum -If a declaration $H$ that declares a name with internal linkage -precedes a declaration $D$ in another translation unit $U$ and -would declare the same entity as $D$ if it appeared in $U$, -the program is ill-formed. -\begin{note} -Such an $H$ can appear only in a header unit. -\end{note} - -\pnum -If two declarations of an entity are -attached to different modules, the program is ill-formed; -no diagnostic is required if neither is reachable from the other. -\begin{example} -\begin{codeblocktu}{\tcode{"decls.h"}} -int f(); // \#1, attached to the global module -int g(); // \#2, attached to the global module -\end{codeblocktu} - -\begin{codeblocktu}{Module interface of \tcode{M}} -module; -#include "decls.h" -export module M; -export using ::f; // OK, does not declare an entity, exports \#1 -int g(); // error: matches \#2, but attached to \tcode{M} -export int h(); // \#3 -export int k(); // \#4 -\end{codeblocktu} - -\begin{codeblocktu}{Other translation unit} -import M; -static int h(); // error: matches \#3 -int k(); // error: matches \#4 -\end{codeblocktu} -\end{example} -As a consequence of these rules, -all declarations of an entity are attached to the same module; -the entity is said to be \defnx{attached}{attached!entity} to that module. - -\pnum -\indextext{consistency!type declaration}% -\indextext{declaration!multiple}% -For any two declarations of an entity $E$: -\begin{itemize} -\item -If one declares $E$ to be a variable or function, -the other shall declare $E$ as one of the same type. -\item -If one declares $E$ to be an enumerator, the other shall do so. -\item -If one declares $E$ to be a namespace, the other shall do so. -\item -If one declares $E$ to be a type, -the other shall declare $E$ to be a type of the same kind\iref{dcl.type.elab}. -\item -If one declares $E$ to be a class template, -the other shall do so with the same kind and -an equivalent \grammarterm{template-head}\iref{temp.over.link}. -\begin{note} -The declarations can supply different default template arguments. -\end{note} -\item -If one declares $E$ to be a function template or -a (partial specialization of a) variable template, -the other shall declare $E$ to be one -with an equivalent \grammarterm{template-head} and type. -\item -If one declares $E$ to be an alias template, -the other shall declare $E$ to be one with -an equivalent \grammarterm{template-head} and \grammarterm{defining-type-id}. -\item -If one declares $E$ to be a concept, the other shall do so. -\end{itemize} -Types are compared after all adjustments of types (during which -typedefs\iref{dcl.typedef} are replaced by their definitions); -declarations for an array -object can specify array types that differ by the presence or absence of -a major array bound\iref{dcl.array}. -No diagnostic is required if neither declaration is reachable from the other. -\begin{example} -\begin{codeblock} -int f(int x, int x); // error: different entities for \tcode{x} -void g(); // \#1 -void g(int); // OK, different entity from \#1 -int g(); // error: same entity as \#1 with different type -void h(); // \#2 -namespace h {} // error: same entity as \#2, but not a function -\end{codeblock} -\end{example} - -\pnum -\begin{note} -Linkage to non-\Cpp{} declarations can be achieved using a -\grammarterm{linkage-specification}\iref{dcl.link}. -\end{note} -\indextext{linkage|)} - -\pnum -A declaration $D$ \defnx{names}{name} an entity $E$ if -\begin{itemize} -\item -$D$ contains a \grammarterm{lambda-expression} whose closure type is $E$, -\item -$E$ is not a function or function template and $D$ contains an -\grammarterm{id-expression}, -\grammarterm{type-specifier}, -\grammarterm{nested-name-specifier}, -\grammarterm{template-name}, or -\grammarterm{concept-name} -denoting $E$, or -\item -$E$ is a function or function template and -$D$ contains an expression that names $E$\iref{basic.def.odr} or -an \grammarterm{id-expression} -that refers to a set of overloads that contains $E$. -\begin{note} -Non-dependent names in an instantiated declaration -do not refer to a set of overloads\iref{temp.res}. -\end{note} -\end{itemize} - -\pnum -A declaration is an \defn{exposure} -if it either names a TU-local entity (defined below), ignoring -\begin{itemize} -\item -the \grammarterm{function-body} -for a non-inline function or function template -(but not the deduced return type -for a (possibly instantiated) definition of a function -with a declared return type that uses a placeholder type\iref{dcl.spec.auto}), -\item -the \grammarterm{initializer} -for a variable or variable template (but not the variable's type), -\item -friend declarations in a class definition, and -\item -any reference to a non-volatile const object or reference -with internal or no linkage initialized with a constant expression -that is not an odr-use\iref{term.odr.use}, -\end{itemize} -or defines a constexpr variable initialized to a TU-local value (defined below). -\begin{note} -An inline function template can be an exposure even though -certain explicit specializations of it would be usable in other translation units. -\end{note} - -\pnum -An entity is \defnx{TU-local}{TU-local!entity} if it is -\begin{itemize} -\item -a type, function, variable, or template that -\begin{itemize} -\item -has a name with internal linkage, or -\item -does not have a name with linkage and is declared, -or introduced by a \grammarterm{lambda-expression}, -within the definition of a TU-local entity, -\end{itemize} -\item -a type with no name that is defined outside a -\grammarterm{class-specifier}, -function body, or -\grammarterm{initializer} -or is introduced by a \grammarterm{defining-type-specifier} -that is used to declare only TU-local entities, -\item -a specialization of a TU-local template, -\item -a specialization of a template with any TU-local template argument, or -\item -a specialization of a template -whose (possibly instantiated) declaration is an exposure. -\begin{note} -A specialization can be produced by implicit or explicit instantiation. -\end{note} -\end{itemize} - -\pnum -A value or object is \defnx{TU-local}{TU-local!value or object} if either -\begin{itemize} -\item -it is, or is a pointer to, -a TU-local function or the object associated with a TU-local variable, or -\item -it is an object of class or array type and -any of its subobjects or -any of the objects or functions -to which its non-static data members of reference type refer -is TU-local and is usable in constant expressions. -\end{itemize} - -\pnum -If a (possibly instantiated) declaration of, or a deduction guide for, -a non-TU-local entity in a module interface unit -(outside the \grammarterm{private-module-fragment}, if any) or -module partition\iref{module.unit} is an exposure, -the program is ill-formed. -Such a declaration in any other context is deprecated\iref{depr.local}. - -\pnum -If a declaration that appears in one translation unit -names a TU-local entity declared -in another translation unit that is not a header unit, -the program is ill-formed. -A declaration instantiated for a template specialization\iref{temp.spec} -appears at the point of instantiation of the specialization\iref{temp.point}. - -\pnum -\begin{example} -\begin{codeblocktu}{Translation unit \#1} -export module A; -static void f() {} -inline void it() { f(); } // error: is an exposure of \tcode{f} -static inline void its() { f(); } // OK -template void g() { its(); } // OK -template void g<0>(); - -decltype(f) *fp; // error: \tcode{f} (though not its type) is TU-local -auto &fr = f; // OK -constexpr auto &fr2 = fr; // error: is an exposure of \tcode{f} -constexpr static auto fp2 = fr; // OK - -struct S { void (&ref)(); } s{f}; // OK, value is TU-local -constexpr extern struct W { S &s; } wrap{s}; // OK, value is not TU-local - -static auto x = []{f();}; // OK -auto x2 = x; // error: the closure type is TU-local -int y = ([]{f();}(),0); // error: the closure type is not TU-local -int y2 = (x,0); // OK - -namespace N { - struct A {}; - void adl(A); - static void adl(int); -} -void adl(double); - -inline void h(auto x) { adl(x); } // OK, but certain specializations are exposures -\end{codeblocktu} -\begin{codeblocktu}{Translation unit \#2} -module A; -void other() { - g<0>(); // OK, specialization is explicitly instantiated - g<1>(); // error: instantiation uses TU-local \tcode{its} - h(N::A{}); // error: overload set contains TU-local \tcode{N::adl(int)} - h(0); // OK, calls \tcode{adl(double)} - adl(N::A{}); // OK; \tcode{N::adl(int)} not found, calls \tcode{N::adl(N::A)} - fr(); // OK, calls \tcode{f} - constexpr auto ptr = fr; // error: \tcode{fr} is not usable in constant expressions here -} -\end{codeblocktu} -\end{example} - -\rSec1[basic.memobj]{Memory and objects} - -\rSec2[intro.memory]{Memory model} - -\pnum -\indextext{memory model|(}% -The fundamental storage unit in the \Cpp{} memory model is the -\defn{byte}. -A byte is at least large enough to contain -the ordinary literal encoding of any element of the basic -\indextext{character set!basic literal}% -literal character set\iref{lex.charset} -and the eight-bit code units of the Unicode -\indextext{UTF-8}% -UTF-8 encoding form -and is composed of a contiguous sequence of -bits, -\begin{footnote} -The number of bits in a byte is reported by the macro -\tcode{CHAR_BIT} in the header \libheaderref{climits}. -\end{footnote} -the number of which is \impldef{bits in a byte}. The least -significant bit is called the \defn{low-order bit}; the most -significant bit is called the \defn{high-order bit}. The memory -available to a \Cpp{} program consists of one or more sequences of -contiguous bytes. Every byte has a unique address. - -\pnum -\begin{note} -The representation of types is described -in~\ref{basic.types.general}. -\end{note} - -\pnum -A \defn{memory location} is either an object of scalar type that is not a bit-field -or a maximal sequence of adjacent bit-fields all having nonzero width. -\begin{note} -Various -features of the language, such as references and virtual functions, might -involve additional memory locations that are not accessible to programs but are -managed by the implementation. -\end{note} -Two or more threads of -execution\iref{intro.multithread} can access separate memory -locations without interfering with each other. - -\pnum -\begin{note} -Thus a bit-field and an adjacent non-bit-field are in separate memory -locations, and therefore can be concurrently updated by two threads of execution -without interference. The same applies to two bit-fields, if one is declared -inside a nested struct declaration and the other is not, or if the two are -separated by a zero-length bit-field declaration, or if they are separated by a -non-bit-field declaration. It is not safe to concurrently update two bit-fields -in the same struct if all fields between them are also bit-fields of nonzero -width. -\end{note} - -\pnum -\begin{example} -A class declared as -\begin{codeblock} -struct { - char a; - int b:5, - c:11, - :0, - d:8; - struct {int ee:8;} e; -}; -\end{codeblock} -contains four separate memory locations: The member \tcode{a} and bit-fields -\tcode{d} and \tcode{e.ee} are each separate memory locations, and can be -modified concurrently without interfering with each other. The bit-fields -\tcode{b} and \tcode{c} together constitute the fourth memory location. The -bit-fields \tcode{b} and \tcode{c} cannot be concurrently modified, but -\tcode{b} and \tcode{a}, for example, can be. -\end{example} -\indextext{memory model|)} - -\rSec2[intro.object]{Object model} - -\pnum -\indextext{object model|(}% -The constructs in a \Cpp{} program create, destroy, refer to, access, and -manipulate objects. -An \defn{object} is created -by a definition\iref{basic.def}, -by a \grammarterm{new-expression}\iref{expr.new}, -by an operation that implicitly creates objects (see below), -when implicitly changing the active member of a union\iref{class.union}, -or -when a temporary object is created\iref{conv.rval,class.temporary}. -An object occupies a region of storage -in its period of construction\iref{class.cdtor}, -throughout its lifetime\iref{basic.life}, -and -in its period of destruction\iref{class.cdtor}. -\begin{note} -A function is not an object, regardless of whether or not it -occupies storage in the way that objects do. -\end{note} -The properties of an -object are determined when the object is created. An object can have a -name\iref{basic.pre}. An object has a storage -duration\iref{basic.stc} which influences its -lifetime\iref{basic.life}. An object has a -type\iref{basic.types}. -\begin{note} -Some objects are -polymorphic\iref{class.virtual}; the implementation -generates information associated with each such object that makes it -possible to determine that object's type during program execution. -\end{note} - -\pnum -\indextext{subobject}% -Objects can contain other objects, called \defnx{subobjects}{subobject}. -A subobject can be -a \defn{member subobject}\iref{class.mem}, a \defn{base class subobject}\iref{class.derived}, -or an array element. -\indextext{object!complete}% -An object that is not a subobject of any other object is called a \defn{complete -object}. -If an object is created -in storage associated with a member subobject or array element \placeholder{e} -(which may or may not be within its lifetime), -the created object -is a subobject of \placeholder{e}'s containing object if -\begin{itemize} -\item -the lifetime of \placeholder{e}'s containing object has begun and not ended, and -\item -the storage for the new object exactly overlays the storage location associated with \placeholder{e}, and -\item -the new object is of the same type as \placeholder{e} (ignoring cv-qualification). -\end{itemize} - -\pnum -\indextext{object!providing storage for}% -If a complete object is created\iref{expr.new} -in storage associated with another object \placeholder{e} -of type ``array of $N$ \tcode{\keyword{unsigned} \keyword{char}}'' or -of type ``array of $N$ \tcode{std::byte}''\iref{cstddef.syn}, -that array \defn{provides storage} -for the created object if -\begin{itemize} -\item -the lifetime of \placeholder{e} has begun and not ended, and -\item -the storage for the new object fits entirely within \placeholder{e}, and -\item -there is no array object that satisfies these constraints nested within \placeholder{e}. -\end{itemize} -\begin{note} -If that portion of the array -previously provided storage for another object, -the lifetime of that object ends -because its storage was reused\iref{basic.life}. -\end{note} -\begin{example} -\begin{codeblock} -// assumes that \tcode{sizeof(int)} is equal to 4 - -template -struct AlignedUnion { - alignas(T...) unsigned char data[max(sizeof(T)...)]; -}; -int f() { - AlignedUnion au; - int *p = new (au.data) int; // OK, \tcode{au.data} provides storage - char *c = new (au.data) char(); // OK, ends lifetime of \tcode{*p} - char *d = new (au.data + 1) char(); - return *c + *d; // OK -} - -struct A { unsigned char a[32]; }; -struct B { unsigned char b[16]; }; -alignas(int) A a; -B *b = new (a.a + 8) B; // \tcode{a.a} provides storage for \tcode{*b} -int *p = new (b->b + 4) int; // \tcode{b->b} provides storage for \tcode{*p} - // \tcode{a.a} does not provide storage for \tcode{*p} (directly), - // but \tcode{*p} is nested within \tcode{a} (see below) -\end{codeblock} -\end{example} - -\pnum -\indextext{object!nested within}% -An object \placeholder{a} is \defn{nested within} another object \placeholder{b} if -\begin{itemize} -\item -\placeholder{a} is a subobject of \placeholder{b}, or -\item -\placeholder{b} provides storage for \placeholder{a}, or -\item -there exists an object \placeholder{c} -where \placeholder{a} is nested within \placeholder{c}, -and \placeholder{c} is nested within \placeholder{b}. -\end{itemize} - -\pnum -For every object \tcode{x}, there is some object called the -\defn{complete object of} \tcode{x}, determined as follows: -\begin{itemize} -\item -If \tcode{x} is a complete object, then the complete object -of \tcode{x} is itself. - -\item -Otherwise, the complete object of \tcode{x} is the complete object -of the (unique) object that contains \tcode{x}. -\end{itemize} - -\pnum -If a complete object, a member subobject, or an array element is of -class type, its type is considered the \defn{most derived -class}, to distinguish it from the class type of any base class subobject; -an object of a most derived class type or of a non-class type is called a -\defn{most derived object}. - -\pnum -A \defn{potentially-overlapping subobject} is either: -\begin{itemize} -\item a base class subobject, or -\item a non-static data member -declared with the \tcode{no_unique_address} attribute\iref{dcl.attr.nouniqueaddr}. -\end{itemize} - -\pnum -\indextext{object!zero size}% -\indextext{object!nonzero size}% -An object has nonzero size if it -\begin{itemize} -\item is not a potentially-overlapping subobject, or -\item is not of class type, or -\item is of a class type with virtual member functions or virtual base classes, or -\item has subobjects of nonzero size or unnamed bit-fields of nonzero length. -\end{itemize} -Otherwise, if the object is a base class subobject -of a standard-layout class type -with no non-static data members, -it has zero size. -Otherwise, the circumstances under which the object has zero size -are \impldef{which non-standard-layout objects -containing no data are considered empty}. -\indextext{most derived object!bit-field}% -Unless it is a bit-field\iref{class.bit}, -an object with nonzero size -shall occupy one or more bytes of storage, -including every byte that is occupied in full or in part -by any of its subobjects. -An object of trivially copyable or -standard-layout type\iref{basic.types.general} shall occupy contiguous bytes of -storage. - -\pnum -An object is a \defnadj{potentially non-unique}{object} if it is -a string literal object\iref{lex.string}, -the backing array of an initializer list\iref{dcl.init.ref}, or -a subobject thereof. - -\pnum -\indextext{most derived object!bit-field}% -\indextext{most derived object!zero size subobject}% -Unless an object is a bit-field or a subobject of zero size, the -address of that object is the address of the first byte it occupies. -Two objects -with overlapping lifetimes -that are not bit-fields -may have the same address if -\begin{itemize} -\item one is nested within the other, -\item at least one is a subobject of zero size and they are not of similar types\iref{conv.qual}, -or -\item they are both potentially non-unique objects; -\end{itemize} -otherwise, they have distinct addresses -and occupy disjoint bytes of storage. -\begin{footnote} -Under the ``as-if'' rule an -implementation is allowed to store two objects at the same machine address or -not store an object at all if the program cannot observe the -difference\iref{intro.execution}. -\end{footnote} -\begin{example} -\begin{codeblock} -static const char test1 = 'x'; -static const char test2 = 'x'; -const bool b = &test1 != &test2; // always \tcode{true} - -static const char (&r) [] = "x"; -static const char *s = "x"; -static std::initializer_list il = { 'x' }; -const bool b2 = r != il.begin(); // unspecified result -const bool b3 = r != s; // unspecified result -const bool b4 = il.begin() != &test1; // always \tcode{true} -const bool b5 = r != &test1; // always \tcode{true} -\end{codeblock} -\end{example} -The address of a non-bit-field subobject of zero size is -the address of an unspecified byte of storage -occupied by the complete object of that subobject. - -\pnum -Some operations are described as -\defnx{implicitly creating objects}{object!implicit creation} -within a specified region of storage. -For each operation that is specified as implicitly creating objects, -that operation implicitly creates and starts the lifetime of -zero or more objects of implicit-lifetime types\iref{term.implicit.lifetime.type} -in its specified region of storage -if doing so would result in the program having defined behavior. -If no such set of objects would give the program defined behavior, -the behavior of the program is undefined. -If multiple such sets of objects would give the program defined behavior, -it is unspecified which such set of objects is created. -\begin{note} -Such operations do not start the lifetimes of subobjects of such objects -that are not themselves of implicit-lifetime types. -\end{note} - -\pnum -Further, after implicitly creating objects within a specified region of storage, -some operations are described as producing a pointer to a -\defnadj{suitable created}{object}. -These operations select one of the implicitly-created objects -whose address is the address of the start of the region of storage, -and produce a pointer value that points to that object, -if that value would result in the program having defined behavior. -If no such pointer value would give the program defined behavior, -the behavior of the program is undefined. -If multiple such pointer values would give the program defined behavior, -it is unspecified which such pointer value is produced. - -\pnum -\begin{example} -\begin{codeblock} -#include -struct X { int a, b; }; -X *make_x() { - // The call to \tcode{std::malloc} implicitly creates an object of type \tcode{X} - // and its subobjects \tcode{a} and \tcode{b}, and returns a pointer to that \tcode{X} object - // (or an object that is pointer-interconvertible\iref{basic.compound} with it), - // in order to give the subsequent class member access operations - // defined behavior. - X *p = (X*)std::malloc(sizeof(struct X)); - p->a = 1; - p->b = 2; - return p; -} -\end{codeblock} -\end{example} - -\pnum -Except during constant evaluation, -an operation that begins the lifetime of -an array of \tcode{unsigned char} or \tcode{std::byte} -implicitly creates objects within the region of storage occupied by the array. -\begin{note} -The array object provides storage for these objects. -\end{note} -Except during constant evaluation, -any implicit or explicit invocation of a function -named \tcode{\keyword{operator} \keyword{new}} or \tcode{\keyword{operator} \keyword{new}[]} -implicitly creates objects in the returned region of storage and -returns a pointer to a suitable created object. -\begin{note} -Some functions in the \Cpp{} standard library implicitly create objects% -\iref{obj.lifetime,c.malloc,mem.res.public,bit.cast,cstring.syn}. -\end{note} -\indextext{object model|)} - -\rSec2[basic.life]{Lifetime} - -\pnum -\indextext{object lifetime|(}% -The \defn{lifetime} of an object or reference is a runtime property of the -object or reference. -A variable is said to have \defnadj{vacuous}{initialization} -if it is default-initialized, no other initialization is performed, and, -if it is of class type or a (possibly multidimensional) array thereof, -a trivial constructor of that class type is selected for -the default-initialization. -The lifetime of an object of type \tcode{T} begins when: -\begin{itemize} -\item storage with the proper alignment and size - for type \tcode{T} is obtained, and -\item its initialization (if any) is complete - (including vacuous initialization)\iref{dcl.init}, -\end{itemize} -except that if the object is a union member or subobject thereof, -its lifetime only begins if that union member is the -initialized member in the union\iref{dcl.init.aggr,class.base.init}, -or as described in -\ref{class.union}, \ref{class.copy.ctor}, and \ref{class.copy.assign}, -and except as described in \ref{allocator.members}. -The lifetime of an object \placeholder{o} of type \tcode{T} ends when: -\begin{itemize} -\item if \tcode{T} is a non-class type, the object is destroyed, or -\item if \tcode{T} is a class type, the destructor call starts, or -\item the storage which the object occupies is released, -or is reused by an object that is not nested within \placeholder{o}\iref{intro.object}. -\end{itemize} -When evaluating a \grammarterm{new-expression}, -storage is considered reused after it is returned from the allocation function, -but before the evaluation of the \grammarterm{new-initializer}\iref{expr.new}. -\begin{example} -\begin{codeblock} -struct S { - int m; -}; - -void f() { - S x{1}; - new(&x) S(x.m); // undefined behavior -} -\end{codeblock} -\end{example} - -\pnum -\indextext{reference lifetime}% -The lifetime of a reference begins when its initialization is complete. -The lifetime of a reference ends as if it were a scalar object requiring storage. - -\pnum -\begin{note} -\ref{class.base.init} -describes the lifetime of base and member subobjects. -\end{note} - -\pnum -The properties ascribed to objects and references throughout this document -apply for a given object or reference only during its lifetime. -\begin{note} -In particular, before the lifetime of an object starts and after its -lifetime ends there are significant restrictions on the use of the -object, as described below, in~\ref{class.base.init}, and -in~\ref{class.cdtor}. Also, the behavior of an object under construction -and destruction can differ from the behavior of an object whose -lifetime has started and not ended. \ref{class.base.init} -and~\ref{class.cdtor} describe the behavior of an object during its periods -of construction and destruction. -\end{note} - -\pnum -A program may end the lifetime of an object of class type without invoking the -destructor, by reusing or releasing the storage as described above. -\begin{note} -A \grammarterm{delete-expression}\iref{expr.delete} invokes the destructor -prior to releasing the storage. -\end{note} -In this case, the destructor is not implicitly invoked. -\begin{note} -The correct behavior of a program often depends on -the destructor being invoked for each object of class type. -\end{note} - -\pnum -Before the lifetime of an object has started but after the storage which -the object will occupy has been allocated -\begin{footnote} -For example, before the dynamic initialization of -an object with static storage duration\iref{basic.start.dynamic}. - -\end{footnote} -or, after the lifetime of an object has ended and before the storage -which the object occupied is reused or released, any pointer that represents the address of -the storage location where the object will be or was located may be -used but only in limited ways. -For an object under construction or destruction, see~\ref{class.cdtor}. -Otherwise, such -a pointer refers to allocated -storage\iref{basic.stc.dynamic.allocation}, and using the pointer as -if the pointer were of type \tcode{\keyword{void}*} is -well-defined. Indirection through such a pointer is permitted but the resulting lvalue may only be used in -limited ways, as described below. The -program has undefined behavior if -\begin{itemize} -\item - the pointer is used as the operand of a \grammarterm{delete-expression}, -\item - the pointer is used to access a non-static data member or call a - non-static member function of the object, or -\item - the pointer is implicitly converted\iref{conv.ptr} to a pointer - to a virtual base class, or -\item - the pointer is used as the operand of a - \keyword{static_cast}\iref{expr.static.cast}, except when the conversion - is to pointer to \cv{}~\keyword{void}, or to pointer to \cv{}~\keyword{void} - and subsequently to pointer to - \cv{}~\keyword{char}, - \cv{}~\tcode{\keyword{unsigned} \keyword{char}}, or - \cv{}~\tcode{std::byte}\iref{cstddef.syn}, or -\item - the pointer is used as the operand of a - \keyword{dynamic_cast}\iref{expr.dynamic.cast}. -\end{itemize} -\begin{example} -\begin{codeblock} -#include - -struct B { - virtual void f(); - void mutate(); - virtual ~B(); -}; - -struct D1 : B { void f(); }; -struct D2 : B { void f(); }; - -void B::mutate() { - new (this) D2; // reuses storage --- ends the lifetime of \tcode{*this} - f(); // undefined behavior - ... = this; // OK, \keyword{this} points to valid memory -} - -void g() { - void* p = std::malloc(sizeof(D1) + sizeof(D2)); - B* pb = new (p) D1; - pb->mutate(); - *pb; // OK, \tcode{pb} points to valid memory - void* q = pb; // OK, \tcode{pb} points to valid memory - pb->f(); // undefined behavior: lifetime of \tcode{*pb} has ended -} -\end{codeblock} +The expression +\tcode{S(16) + S(23)} +creates three temporaries: +a first temporary +\tcode{T1} +to hold the result of the expression +\tcode{S(16)}, +a second temporary +\tcode{T2} +to hold the result of the expression +\tcode{S(23)}, +and a third temporary +\tcode{T3} +to hold the result of the addition of these two expressions. +The temporary +\tcode{T3} +is then bound to the reference +\tcode{cr}. +It is unspecified whether +\tcode{T1} +or +\tcode{T2} +is created first. +On an implementation where +\tcode{T1} +is created before +\tcode{T2}, +\tcode{T2} +shall be destroyed before +\tcode{T1}. +The temporaries +\tcode{T1} +and +\tcode{T2} +are bound to the reference parameters of +\tcode{\keyword{operator}+}; +these temporaries are destroyed at the end of the full-expression +containing the call to +\tcode{\keyword{operator}+}. +The temporary +\tcode{T3} +bound to the reference +\tcode{cr} +is destroyed at the end of +\tcode{cr}'s +lifetime, that is, at the end of the program. +In addition, the order in which +\tcode{T3} +is destroyed takes into account the destruction order of other objects with +static storage duration. +That is, because +\tcode{obj1} +is constructed before +\tcode{T3}, +and +\tcode{T3} +is constructed before +\tcode{obj2}, +\tcode{obj2} +shall be destroyed before +\tcode{T3}, +and +\tcode{T3} +shall be destroyed before +\tcode{obj1}. \end{example} -\pnum -Similarly, before the lifetime of an object has started but after the -storage which the object will occupy has been allocated or, after the -lifetime of an object has ended and before the storage which the object -occupied is reused or released, any glvalue that refers to the original -object may be used but only in limited ways. -For an object under construction or destruction, see~\ref{class.cdtor}. -Otherwise, such -a glvalue refers to -allocated storage\iref{basic.stc.dynamic.allocation}, and using the -properties of the glvalue that do not depend on its value is -well-defined. The program has undefined behavior if -\begin{itemize} -\item the glvalue is used to access the object, or -\item the glvalue is used to call a non-static member function of the object, or -\item the glvalue is bound to a reference to a virtual base class\iref{dcl.init.ref}, or -\item the glvalue is used as the operand of a -\keyword{dynamic_cast}\iref{expr.dynamic.cast} or as the operand of -\keyword{typeid}. -\end{itemize} - -\pnum -An object $o_1$ is \defn{transparently replaceable} by an object $o_2$ if -\begin{itemize} -\item the storage that $o_2$ occupies exactly overlays -the storage that $o_1$ occupied, and - -\item $o_1$ and $o_2$ are of the same type -(ignoring the top-level cv-qualifiers), and - -\item $o_1$ is not a const, complete object, and - -\item neither $o_1$ nor $o_2$ -is a potentially-overlapping subobject\iref{intro.object}, and +\rSec1[basic.types]{Types}% -\item either $o_1$ and $o_2$ are both complete objects, or -$o_1$ and $o_2$ are direct subobjects of objects $p_1$ and $p_2$, respectively, -and $p_1$ is transparently replaceable by $p_2$. -\end{itemize} +\rSec2[basic.types.general]{General}% +\indextext{type|(} \pnum -After the lifetime of an object has ended and before the storage which the -object occupied is reused or released, if a new object is created at the -storage location which the original object occupied and the original object was -transparently replaceable by the new object, a pointer that pointed to the -original object, a reference that referred to the original object, or the name -of the original object will automatically refer to the new object and, once the -lifetime of the new object has started, can be used to manipulate the new -object. +\begin{note} +\ref{basic.types} and the subclauses thereof +impose requirements on implementations regarding the representation +of types. +There are two kinds of types: fundamental types and compound types. +Types describe objects\iref{intro.object}, +references\iref{dcl.ref}, +or functions\iref{dcl.fct}. +\end{note} +\pnum +\indextext{object!byte copying and|(}% +\indextext{type!trivially copyable}% +For any object (other than a potentially-overlapping subobject) of trivially copyable type +\tcode{T}, whether or not the object holds a valid value of type +\tcode{T}, the underlying bytes\iref{intro.memory} making up the +object can be copied into an array of +\keyword{char}, +\tcode{\keyword{unsigned} \keyword{char}}, or +\tcode{std::byte}\iref{cstddef.syn}. +\begin{footnote} +By using, for example, the library +functions\iref{headers} \tcode{std::memcpy} or \tcode{std::memmove}. +\end{footnote} +If the content of that array +is copied back into the object, the object shall +subsequently hold its original value. \begin{example} \begin{codeblock} -struct C { - int i; - void f(); - const C& operator=( const C& ); -}; - -const C& C::operator=( const C& other) { - if ( this != &other ) { - this->~C(); // lifetime of \tcode{*this} ends - new (this) C(other); // new object of type \tcode{C} created - f(); // well-defined - } - return *this; -} - -C c1; -C c2; -c1 = c2; // well-defined -c1.f(); // well-defined; \tcode{c1} refers to a new object of type \tcode{C} +constexpr std::size_t N = sizeof(T); +char buf[N]; +T obj; // \tcode{obj} initialized to its original value +std::memcpy(buf, &obj, N); // between these two calls to \tcode{std::memcpy}, \tcode{obj} might be modified +std::memcpy(&obj, buf, N); // at this point, each subobject of \tcode{obj} of scalar type holds its original value \end{codeblock} \end{example} -\begin{note} -If these conditions are not met, -a pointer to the new object can be obtained from -a pointer that represents the address of its storage -by calling \tcode{std::launder}\iref{ptr.launder}. -\end{note} \pnum -If a program ends the lifetime of an object of type \tcode{T} with -static\iref{basic.stc.static}, thread\iref{basic.stc.thread}, -or automatic\iref{basic.stc.auto} -storage duration and if \tcode{T} has a non-trivial destructor, +For two distinct objects \tcode{obj1} and \tcode{obj2} +of trivially copyable type \tcode{T}, +where neither \tcode{obj1} nor \tcode{obj2} is a potentially-overlapping subobject, +if the underlying bytes\iref{intro.memory} making up +\tcode{obj1} are copied into \tcode{obj2}, \begin{footnote} -That -is, an object for which a destructor will be called -implicitly---upon exit from the block for an object with -automatic storage duration, upon exit from the thread for an object with -thread storage duration, or upon exit from the program for an object -with static storage duration. +By using, for example, +the library functions\iref{headers} \tcode{std::memcpy} or \tcode{std::memmove}. \end{footnote} -and another object of the original type does not occupy -that same storage location when the implicit destructor call takes -place, the behavior of the program is undefined. This is true -even if the block is exited with an exception. + \tcode{obj2} shall subsequently hold the same value as +\tcode{obj1}. \begin{example} \begin{codeblock} -class T { }; -struct B { - ~B(); -}; - -void h() { - B b; - new (&b) T; -} // undefined behavior at block exit +T* t1p; +T* t2p; + // provided that \tcode{t2p} points to an initialized object ... +std::memcpy(t1p, t2p, sizeof(T)); + // at this point, every subobject of trivially copyable type in \tcode{*t1p} contains + // the same value as the corresponding subobject in \tcode{*t2p} \end{codeblock} \end{example} +\indextext{object!byte copying and|)} \pnum -Creating a new object within the storage that a const, complete -object with static, thread, or automatic storage duration occupies, -or within the storage that such a const object used to occupy before -its lifetime ended, results in undefined behavior. +\label{term.object.representation}% +The \defnx{object representation}{representation!object} +of a complete object type \tcode{T} is the +sequence of \placeholder{N} \tcode{\keyword{unsigned} \keyword{char}} objects taken up +by a non-bit-field complete object of type \tcode{T}, +where \placeholder{N} equals +\tcode{\keyword{sizeof}(T)}. +The \defnx{value representation}{representation!value} +of a type \tcode{T} is the set of bits +in the object representation of \tcode{T} +that participate in representing a value of type \tcode{T}. +The object and value representation of +a non-bit-field complete object of type \tcode{T} are +the bytes and bits, respectively, of +the object corresponding to the object and value representation of its type. +The object representation of a bit-field object is +the sequence of \placeholder{N} bits taken up by the object, +where \placeholder{N} is the width of the bit-field\iref{class.bit}. +The value representation of a bit-field object is +the set of bits in the object representation that +participate in representing its value. +\label{term.padding.bits}% +Bits in the object representation of a type or object that are +not part of the value representation +are \defn{padding bits}. +For trivially copyable types, the value representation is +a set of bits in the object representation that determines a +\defn{value}, which is one discrete element of an +\impldef{values of a trivially copyable type} set of values. +\begin{footnote} +The intent is that the memory model of \Cpp{} is compatible +with that of the C programming language. +\end{footnote} + +\pnum +\indextext{type!incompletely-defined object}% +A class that has been declared but not defined, an enumeration type in certain +contexts\iref{dcl.enum}, or an array of unknown +bound or of incomplete element type, is an +\defnadj{incompletely-defined}{object type}. +\begin{footnote} +The size and layout of an instance of an incompletely-defined +object type is unknown. +\end{footnote} +\label{term.incomplete.type}% +Incompletely-defined object types and \cv{}~\keyword{void} are +\defnadjx{incomplete}{types}{type}\iref{basic.fundamental}. +\begin{note} +Objects cannot be defined to have an incomplete type\iref{basic.def}. +\end{note} + +\pnum +A class type (such as ``\tcode{\keyword{class} X}'') can be incomplete at one +point in a translation unit and complete later on; the type +``\tcode{\keyword{class} X}'' is the same type at both points. The declared type +of an array object can be an array of incomplete class type and +therefore incomplete; if the class type is completed later on in the +translation unit, the array type becomes complete; the array type at +those two points is the same type. The declared type of an array object +can be an array of unknown bound and therefore be incomplete at one +point in a translation unit and complete later on; the array types at +those two points (``array of unknown bound of \tcode{T}'' and ``array of +\tcode{N} \tcode{T}'') are different types. +\begin{note} +The type of a pointer or reference to array of unknown bound +permanently points to or refers to an incomplete type. +An array of unknown bound named by a \keyword{typedef} declaration +permanently refers to an incomplete type. +In either case, the array type cannot be completed. +\end{note} \begin{example} +\indextext{type!example of incomplete}% \begin{codeblock} -struct B { - B(); - ~B(); -}; +class X; // \tcode{X} is an incomplete type +extern X* xp; // \tcode{xp} is a pointer to an incomplete type +extern int arr[]; // the type of arr is incomplete +typedef int UNKA[]; // \tcode{UNKA} is an incomplete type +UNKA* arrp; // \tcode{arrp} is a pointer to an incomplete type +UNKA** arrpp; + +void foo() { + xp++; // error: \tcode{X} is incomplete + arrp++; // error: incomplete type + arrpp++; // OK, sizeof \tcode{UNKA*} is known +} -const B b; +struct X { int i; }; // now \tcode{X} is a complete type +int arr[10]; // now the type of \tcode{arr} is complete -void h() { - b.~B(); - new (const_cast(&b)) const B; // undefined behavior +X x; +void bar() { + xp = &x; // OK; type is ``pointer to \tcode{X}'' + arrp = &arr; // OK; qualification conversion\iref{conv.qual} + xp++; // OK, \tcode{X} is complete + arrp++; // error: \tcode{UNKA} can't be completed } \end{codeblock} \end{example} \pnum -In this subclause, ``before'' and ``after'' refer to the ``happens before'' -relation\iref{intro.multithread}. \begin{note} -Therefore, undefined behavior results -if an object that is being constructed in one thread is referenced from another -thread without adequate synchronization. +The rules for declarations and expressions describe in which +contexts incomplete types are prohibited. \end{note} -\indextext{object lifetime|)} -\rSec2[basic.indet]{Indeterminate and erroneous values} +\pnum +\label{term.object.type}% +An \defn{object type} is a (possibly cv-qualified) type that is not +a function type, not a reference type, and not \cv{}~\keyword{void}. \pnum -When storage for an object with automatic or dynamic storage duration -is obtained, -the bytes comprising the storage for the object -have the following initial value: +\indextext{class!trivial}% +\indextext{class!trivially copyable}% +\indextext{class!standard-layout}% +\label{term.scalar.type}% +Arithmetic types\iref{basic.fundamental}, enumeration types, +pointer types, pointer-to-member types\iref{basic.compound}, +\tcode{std::nullptr_t}, +and +cv-qualified\iref{basic.type.qualifier} versions of these +types are collectively called +\defnadjx{scalar}{types}{type}. +\label{term.trivially.copyable.type}% +Scalar types, trivially copyable class types\iref{class.prop}, +arrays of such types, and cv-qualified versions of these +types are collectively called \defnadjx{trivially copyable}{types}{type}. +\label{term.trivial.type}% +Scalar types, trivial class types\iref{class.prop}, +arrays of such types, and cv-qualified versions of these +types are collectively called +\defnadjx{trivial}{types}{type}. +\label{term.standard.layout.type}% +Scalar types, standard-layout class +types\iref{class.prop}, arrays of such types, and +cv-qualified versions of these types +are collectively called \defnadjx{standard-layout}{types}{type}. +\label{term.implicit.lifetime.type}% +Scalar types, implicit-lifetime class types\iref{class.prop}, +array types, and cv-qualified versions of these types +are collectively called \defnadjx{implicit-lifetime}{types}{type}. + +\pnum +\label{term.literal.type}% +A type is a \defnadj{literal}{type} if it is: \begin{itemize} -\item -If the object has dynamic storage duration, or -is the object associated with a variable or function parameter -whose first declaration is marked with -the \tcode{[[indeterminate]]} attribute\iref{dcl.attr.indet}, -the bytes have \defnadjx{indeterminate}{values}{value}; -\item -otherwise, the bytes have \defnadjx{erroneous}{values}{value}, -where each value is determined by the implementation -independently of the state of the program. +\item \cv{}~\keyword{void}; or +\item a scalar type; or +\item a reference type; or +\item an array of literal type; or +\item a possibly cv-qualified class type\iref{class} that +has all of the following properties: +\begin{itemize} +\item it has a constexpr destructor\iref{dcl.constexpr}, +\item all of its non-static non-variant data members and base classes are of non-volatile literal types, and +\item it +\begin{itemize} +\item is a closure type\iref{expr.prim.lambda.closure}, +\item is an aggregate union type that has either +no variant members or +at least one variant member of non-volatile literal type, +\item is a non-union aggregate type for which +each of its anonymous union members +satisfies the above requirements for an aggregate union type, or +\item has at least one constexpr constructor or constructor template +(possibly inherited\iref{namespace.udecl} from a base class) +that is not a copy or move constructor. +\end{itemize} +\end{itemize} \end{itemize} -If no initialization is performed for an object (including subobjects), -such a byte retains its initial value -until that value is replaced\iref{dcl.init.general,expr.ass}. -If any bit in the value representation has an indeterminate value, -the object has an indeterminate value; -otherwise, if any bit in the value representation has an erroneous value, -the object has an erroneous value\iref{conv.lval}. \begin{note} -Objects with static or thread storage duration are zero-initialized, -see~\ref{basic.start.static}. +A literal type is one for which +it might be possible to create an object +within a constant expression. +It is not a guarantee that it is possible to create such an object, +nor is it a guarantee that any object of that type +will be usable in a constant expression. \end{note} \pnum -Except in the following cases, -if an indeterminate value is produced by an evaluation, -the behavior is undefined, and -if an erroneous value is produced by an evaluation, -the behavior is erroneous and -the result of the evaluation is the value so produced but is not erroneous: -\begin{itemize} -\item - If an indeterminate or erroneous value of - unsigned ordinary character type\iref{basic.fundamental} - or \tcode{std::byte} type\iref{cstddef.syn} - is produced by the evaluation of: - \begin{itemize} - \item - the second or third operand of a conditional expression\iref{expr.cond}, - \item - the right operand of a comma expression\iref{expr.comma}, - \item - the operand of a cast or conversion\iref{conv.integral, - expr.type.conv,expr.static.cast,expr.cast} - to an unsigned ordinary character type - or \tcode{std::byte} type\iref{cstddef.syn}, or - \item - a discarded-value expression\iref{expr.context}, - \end{itemize} - then the result of the operation is an indeterminate value or - that erroneous value, respectively. -\item - If an indeterminate or erroneous value of - unsigned ordinary character type or \tcode{std::byte} type - is produced by the evaluation of - the right operand of a simple assignment operator\iref{expr.ass} - whose first operand is an lvalue of - unsigned ordinary character type or \tcode{std::byte} type, - an indeterminate value or that erroneous value, respectively, replaces - the value of the object referred to by the left operand. -\item - If an indeterminate or erroneous value of unsigned ordinary character type - is produced by the evaluation of the initialization expression - when initializing an object of unsigned ordinary character type, - that object is initialized to an indeterminate - value or that erroneous value, respectively. -\item - If an indeterminate value of - unsigned ordinary character type or \tcode{std::byte} type - is produced by the evaluation of the initialization expression - when initializing an object of \tcode{std::byte} type, - that object is initialized to an indeterminate value or - that erroneous value, respectively. -\end{itemize} -Converting an indeterminate or erroneous value of -unsigned ordinary character type or \tcode{std::byte} type -produces an indeterminate or erroneous value, respectively. -In the latter case, -the result of the conversion is the value of the converted operand. -\begin{example} -\begin{codeblock} -int f(bool b) { - unsigned char *c = new unsigned char; - unsigned char d = *c; // OK, \tcode{d} has an indeterminate value - int e = d; // undefined behavior - return b ? d : 0; // undefined behavior if \tcode{b} is \tcode{true} -} +\label{term.layout.compatible.type}% +Two types \cvqual{cv1} \tcode{T1} and \cvqual{cv2} \tcode{T2} are +\defnadjx{layout-compatible}{types}{type} +if \tcode{T1} and \tcode{T2} are the same type, +layout-compatible enumerations\iref{dcl.enum}, or +layout-compatible standard-layout class types\iref{class.mem}. -int g(bool b) { - unsigned char c; - unsigned char d = c; // no erroneous behavior, but \tcode{d} has an erroneous value +\rSec2[basic.fundamental]{Fundamental types} + +\pnum +\indextext{type!implementation-defined \tcode{sizeof}}% +There are five \defnadjx{standard signed integer}{types}{type}: +\indextext{type!\idxcode{signed char}}% +\indextext{type!\idxcode{short}}% +\indextext{type!\idxcode{int}}% +\indextext{type!\idxcode{long}}% +\indextext{type!\idxcode{long long}}% +``\tcode{\keyword{signed} \keyword{char}}'', ``\tcode{\keyword{short} \keyword{int}}'', ``\keyword{int}'', +``\tcode{\keyword{long} \keyword{int}}'', and ``\tcode{\keyword{long} \keyword{long} \keyword{int}}''. In +this list, each type provides at least as much storage as those +preceding it in the list. +There may also be \impldef{extended signed integer types} +\defnadjx{extended signed integer}{types}{type}. +The standard and extended signed integer types are collectively called +\defnadjx{signed integer}{types}{type}. +The range of representable values for a signed integer type is +$-2^{N-1}$ to $2^{N-1}-1$ (inclusive), +where \placeholder{N} is called the \defn{width} of the type. +\indextext{integral type!implementation-defined \tcode{sizeof}}% +\begin{note} +Plain \tcode{int}s are intended to have +the natural width suggested by the architecture of the execution environment; +the other signed integer types are provided to meet special needs. +\end{note} + +\pnum +\indextext{type!\idxcode{unsigned}}% +For each of the standard signed integer types, +there exists a corresponding (but different) +\defnadj{standard unsigned integer}{type}: +\indextext{type!\idxcode{unsigned char}}% +\indextext{type!\idxcode{unsigned short}}% +\indextext{type!\idxcode{unsigned int}}% +\indextext{type!\idxcode{unsigned long}}% +\indextext{type!\idxcode{unsigned long long}}% +``\tcode{\keyword{unsigned} \keyword{char}}'', ``\tcode{\keyword{unsigned} \keyword{short} \keyword{int}}'', +``\tcode{\keyword{unsigned} \keyword{int}}'', ``\tcode{\keyword{unsigned} \keyword{long} \keyword{int}}'', and +``\tcode{\keyword{unsigned} \keyword{long} \keyword{long} \keyword{int}}''. +Likewise, for each of the extended signed integer types, +there exists a corresponding \defnadj{extended unsigned integer}{type}. +The standard and extended unsigned integer types +are collectively called \defnadjx{unsigned integer}{types}{type}. +An unsigned integer type has the same width \placeholder{N} +as the corresponding signed integer type. +\indextext{arithmetic!\idxcode{unsigned}}% +The range of representable values for the unsigned type is +$0$ to $2^N-1$ (inclusive); +arithmetic for the unsigned type is performed modulo $2^N$. +\begin{note} +Unsigned arithmetic does not overflow. +Overflow for signed arithmetic yields undefined behavior\iref{expr.pre}. +\end{note} + +\pnum +\indextext{signed integer representation!two's complement}% +An unsigned integer type has the same +object representation, +value representation, and +alignment requirements\iref{basic.align} +as the corresponding signed integer type. +For each value $x$ of a signed integer type, +the value of the corresponding unsigned integer type +congruent to $x$ modulo $2^N$ has the same value +of corresponding bits in its value representation. +\begin{footnote} +This +is also known as two's complement representation. +\end{footnote} +\begin{example} +The value $-1$ of a signed integer type has the same representation as +the largest value of the corresponding unsigned type. +\end{example} - assert(c == d); // holds, both integral promotions have erroneous behavior +\begin{floattable}{Minimum width}{basic.fundamental.width}{lc} +\topline +\lhdr{Type} & \rhdr{Minimum width $N$} \\ +\capsep +\tcode{\keyword{signed} \keyword{char}} & 8 \\ +\tcode{\keyword{short} \keyword{int}} & 16 \\ +\keyword{int} & 16 \\ +\tcode{\keyword{long} \keyword{int}} & 32 \\ +\tcode{\keyword{long} \keyword{long} \keyword{int}} & 64 \\ +\end{floattable} - int e = d; // erroneous behavior - return b ? d : 0; // erroneous behavior if \tcode{b} is \tcode{true} -} +\pnum +The width of each standard signed integer type +shall not be less than the values specified in \tref{basic.fundamental.width}. +The value representation of a signed or unsigned integer type +comprises $N$ bits, where N is the respective width. +Each set of values for any padding bits\iref{basic.types.general} +in the object representation are +alternative representations of the value specified by the value representation. +\begin{note} +Padding bits have unspecified value, but cannot cause traps. +In contrast, see \IsoC{} 6.2.6.2. +\end{note} +\begin{note} +The signed and unsigned integer types satisfy +the constraints given in \IsoC{} 5.2.4.2.1. +\end{note} +Except as specified above, +the width of a signed or unsigned integer type is +\impldef{width of integral type}. -void h() { - int d1, d2; +\pnum +Each value $x$ of an unsigned integer type with width $N$ has +a unique representation $x = x_0 2^0 + x_1 2^1 + \ldots + x_{N-1} 2^{N-1}$, +where each coefficient $x_i$ is either 0 or 1; +this is called the \defn{base-2 representation} of $x$. +The base-2 representation of a value of signed integer type is +the base-2 representation of the congruent value +of the corresponding unsigned integer type. +The standard signed integer types and standard unsigned integer types +are collectively called the \defnadjx{standard integer}{types}{type}, and the extended +signed integer types and extended +unsigned integer types are collectively called the +\defnadjx{extended integer}{types}{type}. - int e1 = d1; // erroneous behavior - int e2 = d1; // erroneous behavior +\pnum +A fundamental type specified to have +a signed or unsigned integer type as its \defnadj{underlying}{type} has +the same object representation, +value representation, +alignment requirements\iref{basic.align}, and +range of representable values as the underlying type. +Further, each value has the same representation in both types. - assert(e1 == e2); // holds - assert(e1 == d1); // holds, erroneous behavior - assert(e2 == d1); // holds, erroneous behavior +\pnum +\indextext{type!\idxcode{char}}% +\indextext{type!character}% +\indextext{\idxcode{char}!implementation-defined sign of}% +\indextext{type!\idxcode{signed char}}% +\indextext{character!\idxcode{signed}}% +\indextext{type!\idxcode{unsigned char}}% +Type \keyword{char} is a distinct type +that has an \impldef{underlying type of \tcode{char}} choice of +``\tcode{\keyword{signed} \keyword{char}}'' or ``\tcode{\keyword{unsigned} \keyword{char}}'' as its underlying type. +The three types \keyword{char}, \tcode{\keyword{signed} \keyword{char}}, and \tcode{\keyword{unsigned} \keyword{char}} +are collectively called +\defnadjx{ordinary character}{types}{type}. +The ordinary character types and \keyword{char8_t} +are collectively called \defnadjx{narrow character}{types}{type}. +For narrow character types, +each possible bit pattern of the object representation represents +a distinct value. +\begin{note} +This requirement does not hold for other types. +\end{note} +\begin{note} +A bit-field of narrow character type whose width is larger than +the width of that type has padding bits; see \ref{basic.types.general}. +\end{note} - std::memcpy(&d2, &d1, sizeof(int)); // no erroneous behavior, but \tcode{d2} has an erroneous value - assert(e1 == d2); // holds, erroneous behavior - assert(e2 == d2); // holds, erroneous behavior -} -\end{codeblock} -\end{example} +\pnum +\indextext{\idxcode{wchar_t}|see{type, \tcode{wchar_t}}}% +\indextext{type!\idxcode{wchar_t}}% +\indextext{type!underlying!\idxcode{wchar_t}}% +Type \keyword{wchar_t} is a distinct type that has +an \impldef{underlying type of \tcode{wchar_t}} +signed or unsigned integer type as its underlying type. -\rSec2[basic.stc]{Storage duration} +\pnum +\indextext{\idxcode{char8_t}|see{type, \tcode{char8_t}}}% +\indextext{type!\idxcode{char8_t}}% +\indextext{type!underlying!\idxcode{char8_t}}% +Type \keyword{char8_t} denotes a distinct type +whose underlying type is \tcode{\keyword{unsigned} \keyword{char}}. +\indextext{\idxcode{char16_t}|see{type, \tcode{char16_t}}}% +\indextext{\idxcode{char32_t}|see{type, \tcode{char32_t}}}% +\indextext{type!\idxcode{char16_t}}% +\indextext{type!\idxcode{char32_t}}% +\indextext{type!underlying!\idxcode{char16_t}}% +\indextext{type!underlying!\idxcode{char32_t}}% +Types \keyword{char16_t} and \keyword{char32_t} denote distinct types +whose underlying types are \tcode{uint_least16_t} and \tcode{uint_least32_t}, +respectively, in \libheaderref{cstdint}. -\rSec3[basic.stc.general]{General} +\pnum +\indextext{Boolean type}% +\indextext{type!Boolean}% +Type \tcode{bool} is a distinct type that has +the same object representation, +value representation, and +alignment requirements as +an \impldef{underlying type of \tcode{bool}} unsigned integer type. +The values of type \keyword{bool} are +\keyword{true} and \keyword{false}. +\begin{note} +There are no \keyword{signed}, \keyword{unsigned}, +\keyword{short}, or \tcode{\keyword{long} \keyword{bool}} types or values. +\end{note} \pnum -\indextext{storage duration|(}% -The \defn{storage duration} is the property of an object that defines the minimum -potential lifetime of the storage containing the object. The storage -duration is determined by the construct used to create the object and is -one of the following: -\begin{itemize} -\item static storage duration -\item thread storage duration -\item automatic storage duration -\item dynamic storage duration -\end{itemize} +\indextext{type!integral}% +The types \keyword{char}, \keyword{wchar_t}, +\keyword{char8_t}, \keyword{char16_t}, and \keyword{char32_t} +are collectively called \defnadjx{character}{types}{type}. +The character types, \keyword{bool}, +the signed and unsigned integer types, +and cv-qualified versions\iref{basic.type.qualifier} thereof, +are collectively termed +\defnx{integral types}{integral type}. +A synonym for integral type is \defn{integer type}. \begin{note} -After the duration of a region of storage has ended, -the use of pointers to that region of storage is limited\iref{basic.compound}. +Enumerations\iref{dcl.enum} are not integral; +however, unscoped enumerations can be promoted to integral types +as specified in \ref{conv.prom}. \end{note} \pnum -\indextext{storage duration!static}% -\indextext{storage duration!thread}% -\indextext{storage duration!automatic}% -\indextext{storage duration!dynamic}% -Static, thread, and automatic storage durations are associated with objects -introduced by declarations\iref{basic.def} and -with temporary objects\iref{class.temporary}. -The dynamic storage duration -is associated with objects created by a -\grammarterm{new-expression}\iref{expr.new} or -with implicitly created objects\iref{intro.object}. +\indextext{floating-point type|see{type, floating-point}}% +The three distinct types +\indextext{type!\idxcode{float}}% +\keyword{float}, +\indextext{type!\idxcode{double}}% +\keyword{double}, +and +\indextext{type!\idxcode{long double}}% +\tcode{\keyword{long} \keyword{double}} +can represent floating-point numbers. +The type \keyword{double} provides at least as much +precision as \keyword{float}, and the type \tcode{\keyword{long} \keyword{double}} provides at +least as much precision as \keyword{double}. The set of values of the type +\keyword{float} is a subset of the set of values of the type +\keyword{double}; the set of values of the type \keyword{double} is a subset +of the set of values of the type \tcode{\keyword{long} \keyword{double}}. +The types +\keyword{float}, \keyword{double}, and \tcode{\keyword{long} \keyword{double}}, +and cv-qualified versions\iref{basic.type.qualifier} thereof, +are collectively termed +\defnx{standard floating-point types}{type!floating-point!standard}. +An implementation may also provide additional types +that represent floating-point values and define them (and cv-qualified versions thereof) to be +\defnx{extended floating-point types}{type!floating-point!extended}. +The standard and extended floating-point types +are collectively termed \defnx{floating-point types}{type!floating-point}. +\begin{note} +Any additional implementation-specific types representing floating-point values +that are not defined by the implementation to be extended floating-point types +are not considered to be floating-point types, and +this document imposes no requirements on them or +their interactions with floating-point types. +\end{note} +Except as specified in \ref{basic.extended.fp}, +the object and value representations and accuracy of operations +of floating-point types are \impldef{representation of floating-point types}. \pnum -The storage duration categories apply to references as well. +The minimum range of representable values for a floating-point type is +the most negative finite floating-point number representable +in that type through +the most positive finite floating-point number representable in that type. +In addition, if negative infinity is representable in a type, +the range of that type is extended to all negative real numbers; +likewise, if positive infinity is representable in a type, +the range of that type is extended to all positive real numbers. +\begin{note} +Since negative and positive infinity are representable +in \IsoFloatUndated{} formats, +all real numbers lie within the range of representable values of +a floating-point type adhering to \IsoFloatUndated{}. +\end{note} -\rSec3[basic.stc.static]{Static storage duration} +\pnum +Integral and floating-point types are collectively +termed \defnx{arithmetic types}{type!arithmetic}. +\begin{note} +Properties of the arithmetic types, +such as their minimum and maximum representable value, +can be queried using the facilities in the standard library headers +\libheaderref{limits}, +\libheaderref{climits}, and +\libheaderref{cfloat}. +\end{note} \pnum -All variables which +\indextext{type!\idxcode{void}}% +A type \cv{}~\keyword{void} +is an incomplete type that cannot be completed; such a type has +an empty set of values. It is used as the return +type for functions that do not return a value. +An expression of type \cv{}~\keyword{void} shall +be used only as \begin{itemize} -\item -do not have thread storage duration and -\item -belong to a namespace scope\iref{basic.scope.namespace} or -are first declared with -the \keyword{static} or \keyword{extern} keywords\iref{dcl.stc} +\item an expression statement\iref{stmt.expr}, +\item the expression in a \keyword{return} statement\iref{stmt.return} +for a function with the return type \cv{}~\keyword{void}, +\item an operand of a comma expression\iref{expr.comma}, +\item the second or third operand of \tcode{?:}\iref{expr.cond}, +\item the operand of a \keyword{typeid} expression\iref{expr.typeid}, +\item the operand of a \keyword{noexcept} operator\iref{expr.unary.noexcept}, +\item the operand of a \keyword{decltype} specifier\iref{dcl.type.decltype}, or +\item the operand of an explicit conversion to type +\cv{}~\keyword{void}\iref{expr.type.conv,expr.static.cast,expr.cast}. \end{itemize} -have \defnadj{static}{storage duration}. -The storage for these entities lasts for the duration of the -program\iref{basic.start.static,basic.start.term}. \pnum -If a variable with static storage duration has initialization or a -destructor with side effects, it shall not be eliminated even if it -appears to be unused, except that a class object or its copy/move may be -eliminated as specified in~\ref{class.copy.elision}. +The types denoted by \cv~\tcode{std::nullptr_t} are distinct types. +A value of type \tcode{std::nullptr_t} is a null pointer +constant\iref{conv.ptr}. Such values participate in the pointer and the +pointer-to-member conversions\iref{conv.ptr,conv.mem}. +\tcode{\keyword{sizeof}(std::nullptr_t)} shall be equal to \tcode{\keyword{sizeof}(\keyword{void}*)}. \pnum +\indextext{type!fundamental}% +The types described in this subclause +are called \defnx{fundamental types}{fundamental type}. \begin{note} -\indextext{object!local static@local \tcode{static}}% -The keyword \keyword{static} can be used to declare -a block variable\iref{basic.scope.block} with static storage duration; -\ref{stmt.dcl} and \ref{basic.start.term} describe the -initialization and destruction of such variables. -\indextext{member!class static@class \tcode{static}}% -The keyword \keyword{static} applied to -a class data member in a class definition -gives the data member static storage duration\iref{class.static.data}. +Even if the implementation defines two or more fundamental types to have the +same value representation, they are nevertheless different types. \end{note} -\rSec3[basic.stc.thread]{Thread storage duration} +\rSec2[basic.extended.fp]{Optional extended floating-point types} \pnum -All variables declared with the \keyword{thread_local} keyword have -\defnadj{thread}{storage duration}. -The storage for these entities lasts for the duration of -the thread in which they are created. There is a distinct object or reference -per thread, and use of the declared name refers to the entity associated with -the current thread. +If the implementation supports an extended floating-point type\iref{basic.fundamental} +whose properties are specified by +the \IsoFloatUndated{} floating-point interchange format binary16, +then the \grammarterm{typedef-name} \tcode{std::float16_t} +is defined in the header \libheaderref{stdfloat} and names such a type, +the macro \mname{STDCPP_FLOAT16_T} is defined\iref{cpp.predefined}, and +the floating-point literal suffixes \tcode{f16} and \tcode{F16} +are supported\iref{lex.fcon}. \pnum -\begin{note} -A variable with thread storage duration is initialized as specified -in~\ref{basic.start.static}, \ref{basic.start.dynamic}, and \ref{stmt.dcl} -and, if constructed, is destroyed on thread exit\iref{basic.start.term}. -\end{note} - -\rSec3[basic.stc.auto]{Automatic storage duration} +If the implementation supports an extended floating-point type +whose properties are specified by +the \IsoFloatUndated{} floating-point interchange format binary32, +then the \grammarterm{typedef-name} \tcode{std::float32_t} +is defined in the header \libheader{stdfloat} and names such a type, +the macro \mname{STDCPP_FLOAT32_T} is defined, and +the floating-point literal suffixes \tcode{f32} and \tcode{F32} are supported. \pnum -\indextext{storage duration!local object}% -Variables that belong to a block scope and are -not explicitly declared \keyword{static}, \keyword{thread_local}, or \keyword{extern} have -\defnadj{automatic}{storage duration}. The storage -for such variables lasts until the block in which they are created exits. -\begin{note} -These variables are initialized and destroyed as described in~\ref{stmt.dcl}. -\end{note} -Variables that belong to a parameter scope also have automatic storage duration. -The storage for a function parameter lasts until -immediately after its destruction\iref{expr.call}. +If the implementation supports an extended floating-point type +whose properties are specified by +the \IsoFloatUndated{} floating-point interchange format binary64, +then the \grammarterm{typedef-name} \tcode{std::float64_t} +is defined in the header \libheader{stdfloat} and names such a type, +the macro \mname{STDCPP_FLOAT64_T} is defined, and +the floating-point literal suffixes \tcode{f64} and \tcode{F64} are supported. \pnum -If a variable with automatic storage duration has initialization or a destructor with side -effects, an implementation shall not destroy it before the end of its block -nor eliminate it as an optimization, even if it appears to be -unused, except that a class object or its copy/move may be eliminated as -specified in~\ref{class.copy.elision}. - -\rSec3[basic.stc.dynamic]{Dynamic storage duration}% +If the implementation supports an extended floating-point type +whose properties are specified by +the \IsoFloatUndated{} floating-point interchange format binary128, +then the \grammarterm{typedef-name} \tcode{std::float128_t} +is defined in the header \libheader{stdfloat} and names such a type, +the macro \mname{STDCPP_FLOAT128_T} is defined, and +the floating-point literal suffixes \tcode{f128} and \tcode{F128} are supported. -\rSec4[basic.stc.dynamic.general]{General}% -\indextext{storage duration!dynamic|(} +\pnum +If the implementation supports an extended floating-point type +with the properties, as specified by \IsoFloatUndated{}, of +radix ($b$) of 2, +storage width in bits ($k$) of 16, +precision in bits ($p$) of 8, +maximum exponent ($emax$) of 127, and +exponent field width in bits ($w$) of 8, then +the \grammarterm{typedef-name} \tcode{std::bfloat16_t} +is defined in the header \libheader{stdfloat} and names such a type, +the macro \mname{STDCPP_BFLOAT16_T} is defined, and +the floating-point literal suffixes \tcode{bf16} and \tcode{BF16} are supported. \pnum -Objects can be created dynamically during program -execution\iref{intro.execution}, using -\indextext{\idxcode{new}}% -\grammarterm{new-expression}{s}\iref{expr.new}, and destroyed using -\indextext{\idxcode{delete}}% -\grammarterm{delete-expression}{s}\iref{expr.delete}. A \Cpp{} implementation -provides access to, and management of, dynamic storage via -the global \defnx{allocation functions}{allocation function} -\tcode{\keyword{operator} \keyword{new}} and -\tcode{\keyword{operator} \keyword{new}[]} and -the global \defnx{deallocation functions}{deallocation function} -\tcode{\keyword{operator} \keyword{delete}} and -\tcode{\keyword{operator} \keyword{delete}[]}. \begin{note} -The non-allocating forms described in \ref{new.delete.placement} -do not perform allocation or deallocation. +A summary of the parameters for each type is given in \tref{basic.extended.fp}. +The precision $p$ includes the implicit 1 bit at the beginning of the significand, +so the storage used for the significand is $p-1$ bits. +\IsoFloatUndated{} does not assign a name for a type +having the parameters specified for \tcode{std::bfloat16_t}. \end{note} +\begin{floattable} +{Properties of named extended floating-point types}{basic.extended.fp}{llllll} +\topline +\lhdr{Parameter} & \chdr{\tcode{float16_t}} & \chdr{\tcode{float32_t}} & +\chdr{\tcode{float64_t}} & \chdr{\tcode{float128_t}} & +\rhdr{\tcode{bfloat16_t}} \\ +\capsep +\IsoFloatUndated{} name & binary16 & binary32 & binary64 & binary128 & \\ +$k$, storage width in bits & 16 & 32 & 64 & 128 & 16 \\ +$p$, precision in bits & 11 & 24 & 53 & 113 & 8 \\ +$emax$, maximum exponent & 15 & 127 & 1023 & 16383 & 127 \\ +$w$, exponent field width in bits & 5 & 8 & 11 & 15 & 8 \\ +\end{floattable} \pnum -The library provides default definitions for the global allocation and -deallocation functions. Some global allocation and deallocation -functions are replaceable\iref{new.delete}; -these are attached to the global module\iref{module.unit}. -A \Cpp{} program shall -provide at most one definition of a replaceable allocation or -deallocation function. Any such function definition replaces the default -version provided in the library\iref{replacement.functions}. The -following allocation and deallocation functions\iref{support.dynamic} -are implicitly declared in global scope in each translation unit of a -program. - -\begin{codeblock} -void* operator new(std::size_t); -void* operator new(std::size_t, std::align_val_t); - -void operator delete(void*) noexcept; -void operator delete(void*, std::size_t) noexcept; -void operator delete(void*, std::align_val_t) noexcept; -void operator delete(void*, std::size_t, std::align_val_t) noexcept; - -void* operator new[](std::size_t); -void* operator new[](std::size_t, std::align_val_t); - -void operator delete[](void*) noexcept; -void operator delete[](void*, std::size_t) noexcept; -void operator delete[](void*, std::align_val_t) noexcept; -void operator delete[](void*, std::size_t, std::align_val_t) noexcept; -\end{codeblock} +\recommended +Any names that the implementation provides for +the extended floating-point types described in this subsection +that are in addition to the names defined in the \libheader{stdfloat} header +should be chosen to increase compatibility and interoperability +with the interchange types +\tcode{_Float16}, \tcode{_Float32}, \tcode{_Float64}, and \tcode{_Float128} +defined in ISO/IEC TS 18661-3 and with future versions of \IsoCUndated{}. -These implicit declarations introduce only the function names -\tcode{\keyword{operator} \keyword{new}}, -\tcode{\keyword{operator} \keyword{new}[]}, -\tcode{\keyword{operator} \keyword{delete}}, and -\tcode{\keyword{operator} \keyword{delete}[]}. -\begin{note} -The implicit declarations do not introduce -the names \tcode{std}, -\tcode{std::size_t}, -\tcode{std::align_val_t}, -or any other names that the library uses to -declare these names. Thus, a \grammarterm{new-expression}, -\grammarterm{delete-expression}, or function call that refers to one of -these functions without importing or including the header \libheaderref{new} -or importing a \Cpp{} library module\iref{std.modules} -is well-formed. However, referring to \tcode{std} -or \tcode{std::size_t} -or \tcode{std::align_val_t} -is ill-formed unless -a standard library declaration\iref{cstddef.syn,new.syn,std.modules} -of that name precedes\iref{basic.lookup.general} the use of that name. -\end{note} -Allocation and/or -deallocation functions may also be declared and defined for any -class\iref{class.free}. +\rSec2[basic.compound]{Compound types} \pnum -If the behavior of an allocation or deallocation function -does not satisfy the semantic constraints -specified in~\ref{basic.stc.dynamic.allocation} -and~\ref{basic.stc.dynamic.deallocation}, -the behavior is undefined. - -\indextext{storage duration!dynamic|)} +\indextext{type!compound}% +Compound types can be constructed in the following ways: +\begin{itemize} +\item \defnx{arrays}{type!array} of objects of a given type, \ref{dcl.array}; -\rSec4[basic.stc.dynamic.allocation]{Allocation functions} +\item \defnx{functions}{type!function}, which have parameters of given types and return +\keyword{void} or references or objects of a given type, \ref{dcl.fct}; -\pnum -\indextext{function!allocation}% -An allocation function that is not a class member function -shall belong to the global scope and not have a name with internal linkage. -The return type shall be \tcode{\keyword{void}*}. The first -parameter shall have type \tcode{std::size_t}\iref{support.types}. The -first parameter shall not have an associated default -argument\iref{dcl.fct.default}. The value of the first parameter -is interpreted as the requested size of the allocation. An allocation -function can be a function template. Such a template shall declare its -return type and first parameter as specified above (that is, template -parameter types shall not be used in the return type and first parameter -type). Allocation function templates shall have two or more parameters. +\item \defnx{pointers}{type!pointer} to \cv{}~\keyword{void} or objects or functions (including +static members of classes) of a given type, \ref{dcl.ptr}; -\pnum -An allocation function attempts to allocate the requested amount of -storage. If it is successful, it returns the address of the start -of a block of storage whose length in bytes is at least as large -as the requested size. -The order, -contiguity, and initial value of storage allocated by successive calls -to an allocation function are unspecified. -Even if the size of the space -requested is zero, the request can fail. If the request succeeds, the -value returned by a replaceable allocation function -is a non-null pointer value\iref{basic.compound} -\tcode{p0} different from any previously returned value \tcode{p1}, -unless that value \tcode{p1} was subsequently passed to a -replaceable deallocation function. -Furthermore, for the library allocation functions -in~\ref{new.delete.single} and~\ref{new.delete.array}, -\tcode{p0} represents the address of a block of storage disjoint from the storage -for any other object accessible to the caller. -The effect of indirecting through a pointer -returned from a request for zero size is undefined. +\item +\indextext{reference!lvalue}% +\indextext{reference!rvalue}% +\defnx{references}{reference} to objects or functions of a given +type, \ref{dcl.ref}. There are two types of references: +\begin{itemize} +\item lvalue reference +\item rvalue reference +\end{itemize} + +\item +\defnx{classes}{class} containing a sequence of objects of various types\iref{class}, +a set of types, enumerations and functions for +manipulating these objects\iref{class.mfct}, and a set of restrictions +on the access to these entities\iref{class.access}; + +\item +\defnx{unions}{\idxcode{union}}, which are classes capable of containing objects of +different types at different times, \ref{class.union}; + +\item +\defnx{enumerations}{\idxcode{enum}}, +which comprise a set of named constant values, \ref{dcl.enum}; + +\item +\indextext{member pointer to|see{pointer to member}}% +\defnx{pointers to non-static class members}{pointer to member},% \begin{footnote} -The intent is -to have \tcode{\keyword{operator} \keyword{new}()} implementable by -calling \tcode{std::malloc()} or \tcode{std::calloc()}, so the rules are -substantially the same. \Cpp{} differs from C in requiring a zero request -to return a non-null pointer. +Static class members are objects or functions, and pointers to them are +ordinary pointers to objects or functions. \end{footnote} +which identify members of a given +type within objects of a given class, \ref{dcl.mptr}. +Pointers to data members and pointers to member functions are collectively +called \term{pointer-to-member} types. +\end{itemize} \pnum -For an allocation function other than -a reserved placement allocation function\iref{new.delete.placement}, -the pointer returned on a successful call -shall represent the address of storage that is aligned as follows: +These methods of constructing types can be applied recursively; +restrictions are mentioned in~\ref{dcl.meaning}. +Constructing a type such that the number of +bytes in its object representation exceeds the maximum value representable in +the type \tcode{std::size_t}\iref{support.types} is ill-formed. + +\pnum +\indextext{terminology!pointer}% +The type of a pointer to \cv{}~\keyword{void} or a pointer to an object type is +called an \defn{object pointer type}. +\begin{note} +A pointer to \keyword{void} +does not have a pointer-to-object type, however, because \keyword{void} is not +an object type. +\end{note} +The type of a pointer that can designate a function +is called a \defn{function pointer type}. +A pointer to an object of type \tcode{T} is referred to as a ``pointer to +\tcode{T}''. +\begin{example} +A pointer to an object of type \keyword{int} is +referred to as ``pointer to \keyword{int}'' and a pointer to an object of +class \tcode{X} is called a ``pointer to \tcode{X}''. +\end{example} +Except for pointers to static members, text referring to ``pointers'' +does not apply to pointers to members. Pointers to incomplete types are +allowed although there are restrictions on what can be done with +them\iref{basic.types.general}. +\indextext{address}% +Every value of pointer type is one of the following: \begin{itemize} \item - If the allocation function takes an argument - of type \tcode{std::align_val_t}, - the storage will have the alignment specified - by the value of this argument. +a \defn{pointer to} an object or function (the pointer is said to \defn{point} to the object or function), or \item - Otherwise, if the allocation function is named \tcode{\keyword{operator} \keyword{new}[]}, - the storage is aligned for any object that - does not have new-extended alignment\iref{basic.align} and - is no larger than the requested size. +a \defn{pointer past the end of} an object\iref{expr.add}, or \item - Otherwise, the storage is aligned for any object that - does not have new-extended alignment and is of the requested size. +\indextext{null pointer value|see{value, null pointer}} +the \defnx{null pointer value}{value!null pointer} for that type, or +\item +\indextext{invalid pointer value|see{value, invalid pointer}} +an \defnx{invalid pointer value}{value!invalid pointer}. \end{itemize} - -\pnum -An allocation function that fails to allocate storage can invoke the -currently installed new-handler function\iref{new.handler}, if any. +A value of a +pointer type +that is a pointer to or past the end of an object +\defn{represents the address} of +the first byte in memory\iref{intro.memory} occupied by the object +\begin{footnote} +For an object that is not within its lifetime, +this is the first byte in memory that it will occupy or used to occupy. +\end{footnote} +or the first byte in memory +after the end of the storage occupied by the object, +respectively. \begin{note} -\indextext{\idxcode{new_handler}}% -A program-supplied allocation function can obtain the -currently installed \tcode{new_handler} using the -\tcode{std::get_new_handler} function\iref{get.new.handler}. +A pointer past the end of an object\iref{expr.add} +is not considered to point to an unrelated object +of the object's type, +even if the unrelated object is located at that address. \end{note} -An allocation function that has a non-throwing -exception specification\iref{except.spec} -indicates failure by returning -a null pointer value. -Any other allocation function -never returns a null pointer value and -indicates failure only by throwing an exception\iref{except.throw} of a type -that would match a handler\iref{except.handle} of type -\tcode{std::bad_alloc}\iref{bad.alloc}. - -\pnum -A global allocation function is only called as the result of a new -expression\iref{expr.new}, or called directly using the function call -syntax\iref{expr.call}, or called indirectly to allocate storage for -a coroutine state\iref{dcl.fct.def.coroutine}, -or called indirectly through calls to the -functions in the \Cpp{} standard library. +For purposes of pointer arithmetic\iref{expr.add} +and comparison\iref{expr.rel,expr.eq}, +a pointer past the end of the last element of +an array \tcode{x} of $n$ elements +is considered to be equivalent to +a pointer to a hypothetical array element $n$ of \tcode{x} and +an object of type \tcode{T} that is not an array element +is considered to belong to an array with one element of type \tcode{T}. +The value representation of +pointer types is \impldef{value representation of pointer types}. Pointers to +layout-compatible types shall +have the same value representation and alignment +requirements\iref{basic.align}. \begin{note} -In particular, a -global allocation function is not called to allocate storage for objects -with static storage duration\iref{basic.stc.static}, for objects or references -with thread storage duration\iref{basic.stc.thread}, for objects of -type \tcode{std::type_info}\iref{expr.typeid}, or for an -exception object\iref{except.throw}. +Pointers to over-aligned types\iref{basic.align} have no special +representation, but their range of valid values is restricted by the extended +alignment requirement. \end{note} -\rSec4[basic.stc.dynamic.deallocation]{Deallocation functions} - -\pnum -\indextext{function!deallocation}% -A deallocation function that is not a class member function -shall belong to the global scope and not have a name with internal linkage. - \pnum -A deallocation function -is a \defnadj{destroying}{operator delete} -if it has at least two parameters -and its second parameter -is of type \tcode{std::destroying_delete_t}. -A destroying operator delete -shall be a class member function named \tcode{\keyword{operator} \keyword{delete}}. +A pointer value $P$ is +\indextext{value!valid in the context of an evaluation}% +\defn{valid in the context of} an evaluation $E$ +if $P$ is a null pointer value, or +if it is a pointer to or past the end of an object $O$ and +$E$ happens before the end of the duration of the region of storage for $O$. +If a pointer value $P$ is used in an evaluation $E$ and +$P$ is not valid in the context of $E$, +then the behavior is undefined if $E$ is +an indirection\iref{expr.unary.op} or +an invocation of a deallocation function\iref{basic.stc.dynamic.deallocation}, +and \impldef{invalid pointer value in the context of an evaluation} otherwise. +\begin{footnote} +Some implementations might define that +copying such a pointer value causes a system-generated runtime fault. +\end{footnote} \begin{note} -Array deletion cannot use a destroying operator delete. +$P$ can be valid in the context of $E$ even +if it points to a type unrelated to that of $O$ or +if $O$ is not within its lifetime, +although further restrictions apply +to such pointer values\iref{basic.life, basic.lval, expr.add}. \end{note} \pnum -\indextext{\idxcode{delete}!overloading and}% -Each deallocation function shall return \keyword{void}. -If the function is a destroying operator delete -declared in class type \tcode{C}, -the type of its first parameter shall be \tcode{C*}; -otherwise, the type of its first -parameter shall be \tcode{\keyword{void}*}. A deallocation function may have more -than one parameter. -\indextext{deallocation function!usual}% -A \defn{usual deallocation function} is a deallocation function -whose parameters after the first are +Two objects \placeholder{a} and \placeholder{b} are \defn{pointer-interconvertible} if \begin{itemize} \item -optionally, a parameter of type \tcode{std::destroying_delete_t}, then +they are the same object, or \item -optionally, a parameter of type \tcode{std::size_t}, -\begin{footnote} -The global \tcode{\keyword{operator} \keyword{delete}(\keyword{void}*, std::size_t)} -precludes use of an -allocation function \tcode{\keyword{void} \keyword{operator} \keyword{new}(std::size_t, std::size_t)} as a placement -allocation function\iref{diff.cpp11.basic}. -\end{footnote} -then +one is a union object and +the other is a non-static data member of that object\iref{class.union}, or \item -optionally, a parameter of type \tcode{std::align_val_t}. +one is a standard-layout class object and +the other is the first non-static data member of that object or +any base class subobject of that object\iref{class.mem}, or +\item +there exists an object \placeholder{c} such that +\placeholder{a} and \placeholder{c} are pointer-interconvertible, and +\placeholder{c} and \placeholder{b} are pointer-interconvertible. \end{itemize} -A destroying operator delete shall be a usual deallocation function. -A deallocation function may be an instance of a function -template. Neither the first parameter nor the return type shall depend -on a template parameter. -A deallocation -function template shall have two or more function parameters. A template -instance is never a usual deallocation function, regardless of its -signature. +If two objects are pointer-interconvertible, +then they have the same address, +and it is possible to obtain a pointer to one +from a pointer to the other +via a \keyword{reinterpret_cast}\iref{expr.reinterpret.cast}. +\begin{note} +An array object and its first element are not pointer-interconvertible, +even though they have the same address. +\end{note} \pnum -If a deallocation function terminates by throwing an exception, the behavior is undefined. -The value of the first argument supplied to a deallocation function may -be a null pointer value; if so, and if the deallocation function is one -supplied in the standard library, the call has no effect. +A byte of storage \placeholder{b} +is \defnx{reachable through}{storage!reachable through a pointer value} +a pointer value that points to an object \placeholder{x} +if there is an object \placeholder{y}, +pointer-interconvertible with \placeholder{x}, +such that \placeholder{b} is within the storage occupied by +\placeholder{y}, or the immediately-enclosing array object +if \placeholder{y} is an array element. \pnum -If the argument given to a deallocation function in the standard library -is a pointer that is not the null pointer value\iref{basic.compound}, the -deallocation function shall deallocate the storage referenced by the -pointer, ending the duration of the region of storage. +\indextext{pointer|seealso{\tcode{void*}}}% +\indextext{\idxcode{void*}!type}% +A pointer to \cv{}~\keyword{void} +can be used to point to objects of +unknown type. Such a pointer shall be able to hold any object pointer. +An object of type ``pointer to \cv{}~\keyword{void}'' +shall have the same representation and alignment +requirements as an object of type ``pointer to \cv{}~\keyword{char}''. -\rSec3[basic.stc.inherit]{Duration of subobjects} +\rSec2[basic.type.qualifier]{CV-qualifiers} \pnum -\indextext{storage duration!class member}% -The storage duration of subobjects and reference members -is that of their complete object\iref{intro.object}. -\indextext{storage duration|)}% +\indextext{cv-qualifier}% +\indextext{\idxcode{const}}% +\indextext{\idxcode{volatile}}% +Each type other than a function or reference type +is part of a group of four distinct, but related, types: +a \defn{cv-unqualified} version, +a \defn{const-qualified} version, +a \defn{volatile-qualified} version, and +a \defn{const-volatile-qualified} version. +The types in each such group shall have +the same representation and alignment requirements\iref{basic.align}. +\begin{footnote} +The same representation and alignment requirements +are meant to imply interchangeability as +arguments to functions, +return values from functions, and +non-static data members of unions. +\end{footnote} +A function or reference type is always cv-unqualified. +\begin{itemize} +\item A \defnadj{const}{object} is an object of type \tcode{\keyword{const} T} or a + non-mutable subobject of a const object. -\rSec2[basic.align]{Alignment} +\item A \defnadj{volatile}{object} is an object of type + \tcode{\keyword{volatile} T} or a subobject of a volatile object. + +\item A \defnadj{const volatile}{object} is an object of type + \tcode{\keyword{const} \keyword{volatile} T}, a non-mutable subobject of a const volatile object, + a const subobject of a volatile object, or a non-mutable volatile + subobject of a const object. +\end{itemize} +\begin{note} +The type of an object\iref{intro.object} includes +the \grammarterm{cv-qualifier}s specified in the +\grammarterm{decl-specifier-seq}\iref{dcl.spec}, +\grammarterm{declarator}\iref{dcl.decl}, +\grammarterm{type-id}\iref{dcl.name}, or +\grammarterm{new-type-id}\iref{expr.new} +when the object is created. +\end{note} \pnum -Object types have \defnx{alignment requirements}{alignment requirement!implementation-defined}\iref{basic.fundamental,basic.compound} -which place restrictions on the addresses at which an object of that type -may be allocated. An \defn{alignment} is an \impldef{alignment} -integer value representing the number of bytes between successive addresses -at which a given object can be allocated. An object type imposes an alignment -requirement on every object of that type; stricter alignment can be requested -using the alignment specifier\iref{dcl.align}. -Attempting to create an object\iref{intro.object} in storage that -does not meet the alignment requirements of the object's type -is undefined behavior. +Except for array types, a compound type\iref{basic.compound} is not cv-qualified by the +cv-qualifiers (if any) of the types from which it is compounded. \pnum -A \defnadj{fundamental}{alignment} is represented by an alignment -less than or equal to the greatest alignment supported by the implementation in -all contexts, which is equal to -\tcode{\keyword{alignof}(std::max_align_t)}\iref{support.types}. -The alignment required for a type may be different when it is used as the type -of a complete object and when it is used as the type of a subobject. +\indextext{array!\idxcode{const}}% +An array type whose elements are cv-qualified +is also considered to have the same cv-qualifications +as its elements. +\begin{note} +Cv-qualifiers applied to an array +type attach to the underlying element type, so the notation +``\cv{}~\tcode{T}'', where \tcode{T} is an array type, refers to +an array whose elements are so-qualified\iref{dcl.array}. +\end{note} \begin{example} \begin{codeblock} -struct B { long double d; }; -struct D : virtual B { char c; }; +typedef char CA[5]; +typedef const char CC; +CC arr1[5] = { 0 }; +const CA arr2 = { 0 }; \end{codeblock} - -When \tcode{D} is the type of a complete object, it will have a subobject of -type \tcode{B}, so it must be aligned appropriately for a \tcode{\keyword{long} \keyword{double}}. -If \tcode{D} appears as a subobject of another object that also has \tcode{B} -as a virtual base class, the \tcode{B} subobject might be part of a different -subobject, reducing the alignment requirements on the \tcode{D} subobject. +The type of both \tcode{arr1} and \tcode{arr2} is ``array of 5 +\tcode{\keyword{const} \keyword{char}}'', and the array type is considered to be +const-qualified. \end{example} -The result of the \keyword{alignof} operator reflects the alignment -requirement of the type in the complete-object case. +\indextext{type|)} \pnum -An \defnadj{extended}{alignment} is represented by an alignment -greater than \tcode{\keyword{alignof}(std::max_align_t)}. It is \impldef{support for extended alignments} -whether any extended alignments are supported and the contexts in which they are -supported\iref{dcl.align}. A type having an extended alignment -requirement is an \defnadj{over-aligned}{type}. \begin{note} -Every over-aligned type is or contains a class type -to which extended alignment applies (possibly through a non-static data member). +See~\ref{dcl.fct} and~\ref{over.match.funcs} regarding function +types that have \grammarterm{cv-qualifier}{s}. \end{note} -A \defnadj{new-extended}{alignment} is represented by -an alignment greater than \mname{STDCPP_DEFAULT_NEW_ALIGNMENT}\iref{cpp.predefined}. \pnum -Alignments are represented as values of the type \tcode{std::size_t}. -Valid alignments include only those values returned by an \keyword{alignof} -expression for the fundamental types plus an additional \impldef{alignment additional -values} -set of values, which may be empty. -Every alignment value shall be a non-negative integral power of two. +There is a partial ordering on cv-qualifiers, so that a type can be +said to be \defn{more cv-qualified} than another. +\tref{basic.type.qualifier.rel} shows the relations that +constitute this ordering. + +\begin{floattable}{Relations on \keyword{const} and \keyword{volatile}}{basic.type.qualifier.rel} +{ccc} +\topline +\cvqual{no cv-qualifier} &<& \keyword{const} \\ +\cvqual{no cv-qualifier} &<& \keyword{volatile} \\ +\cvqual{no cv-qualifier} &<& \tcode{\keyword{const} \keyword{volatile}} \\ +\keyword{const} &<& \tcode{\keyword{const} \keyword{volatile}} \\ +\keyword{volatile} &<& \tcode{\keyword{const} \keyword{volatile}} \\ +\end{floattable} \pnum -Alignments have an order from \defnx{weaker}{alignment!weaker} to -\defnx{stronger}{alignment!stronger} or \defnx{stricter}{alignment!stricter} alignments. Stricter -alignments have larger alignment values. An address that satisfies an alignment -requirement also satisfies any weaker valid alignment requirement. +In this document, the notation \cv{} (or +\cvqual{cv1}, \cvqual{cv2}, etc.), used in the description of types, +represents an arbitrary set of cv-qualifiers, i.e., one of +\{\keyword{const}\}, \{\keyword{volatile}\}, \{\keyword{const}, +\keyword{volatile}\}, or the empty set. +For a type \cv{}~\tcode{T}, the \defnx{top-level cv-qualifiers}{cv-qualifier!top-level} +of that type are those denoted by \cv. +\begin{example} +The type corresponding to the \grammarterm{type-id} +\tcode{\keyword{const} \keyword{int}\&} +has no top-level cv-qualifiers. +The type corresponding to the \grammarterm{type-id} +\tcode{\keyword{volatile} \keyword{int} * \keyword{const}} +has the top-level cv-qualifier \keyword{const}. +For a class type \tcode{C}, +the type corresponding to the \grammarterm{type-id} +\tcode{\keyword{void} (C::* \keyword{volatile})(\keyword{int}) \keyword{const}} +has the top-level cv-qualifier \keyword{volatile}. +\end{example} + +\rSec2[conv.rank]{Conversion ranks}% +\indextext{conversion!integer rank} \pnum -The alignment requirement of a complete type can be queried using an -\keyword{alignof} expression\iref{expr.alignof}. Furthermore, -the narrow character types\iref{basic.fundamental} shall have the weakest -alignment requirement. +Every integer type has an \term{integer conversion rank} defined as follows: + +\begin{itemize} +\item No two signed integer types other than \keyword{char} and \tcode{\keyword{signed} +\keyword{char}} (if \keyword{char} is signed) have the same rank, even if they have +the same representation. + +\item The rank of a signed integer type is greater than the rank +of any signed integer type with a smaller width. + +\item The rank of \tcode{\keyword{long} \keyword{long} \keyword{int}} is greater +than the rank of \tcode{\keyword{long} \keyword{int}}, which is greater than +the rank of \keyword{int}, which is greater than the rank of +\tcode{\keyword{short} \keyword{int}}, which is greater than the rank of +\tcode{\keyword{signed} \keyword{char}}. + +\item The rank of any unsigned integer type equals the rank of the +corresponding signed integer type. + +\item The rank of any standard integer type is greater than the +rank of any extended integer type with the same width. + +\item The rank of \keyword{char} equals the rank of \tcode{\keyword{signed} \keyword{char}} +and \tcode{\keyword{unsigned} \keyword{char}}. + +\item The rank of \tcode{bool} is less than the rank of all +standard integer types. + +\item +\indextext{type!\idxcode{wchar_t}}% +\indextext{type!\idxcode{char16_t}}% +\indextext{type!\idxcode{char32_t}}% +The ranks of \keyword{char8_t}, \keyword{char16_t}, \keyword{char32_t}, and +\keyword{wchar_t} equal the ranks of their underlying +types\iref{basic.fundamental}. + +\item The rank of any extended signed integer type relative to another +extended signed integer type with the same width is \impldef{rank of extended signed +integer type}, but still subject to the other rules for determining the integer +conversion rank. + +\item For all integer types \tcode{T1}, \tcode{T2}, and \tcode{T3}, if +\tcode{T1} has greater rank than \tcode{T2} and \tcode{T2} has greater +rank than \tcode{T3}, then \tcode{T1} has greater rank than +\tcode{T3}. +\end{itemize} + \begin{note} -This enables the ordinary character types to be used as the -underlying type for an aligned memory area\iref{dcl.align}. +The integer conversion rank is used in the definition of the integral +promotions\iref{conv.prom} and the usual arithmetic +conversions\iref{expr.arith.conv}. \end{note} \pnum -Comparing alignments is meaningful and provides the obvious results: - +Every floating-point type has a \defnadj{floating-point}{conversion rank} +defined as follows: \begin{itemize} -\item Two alignments are equal when their numeric values are equal. -\item Two alignments are different when their numeric values are not equal. -\item When an alignment is larger than another it represents a stricter alignment. +\item +The rank of a floating point type \tcode{T} is greater than +the rank of any floating-point type +whose set of values is a proper subset of the set of values of \tcode{T}. +\item +The rank of \tcode{\keyword{long} \keyword{double}} is greater than +the rank of \keyword{double}, +which is greater than the rank of \keyword{float}. +\item +Two extended floating-point types with the same set of values have equal ranks. +\item +An extended floating-point type with the same set of values as +exactly one cv-unqualified standard floating-point type +has a rank equal to the rank of that standard floating-point type. +\item +An extended floating-point type with the same set of values as +more than one cv-unqualified standard floating-point type +has a rank equal to the rank of \keyword{double}. +\begin{tailnote} +The treatment of \tcode{std::float64_t} differs from +that of the analoguous \tcode{_Float64} in C, +for example on platforms where all of +\tcode{\keyword{long} \keyword{double}}, +\keyword{double}, and +\tcode{std::float64_t} +have the same set of values (see \IsoCUndated{}:2024 H.4.2). +\end{tailnote} \end{itemize} +\begin{note} +The conversion ranks of floating-point types \tcode{T1} and \tcode{T2} +are unordered if the set of values of \tcode{T1} is +neither a subset nor a superset of the set of values of \tcode{T2}. +This can happen when one type has both a larger range and a lower precision +than the other. +\end{note} + +\pnum +Floating-point types that have equal floating-point conversion ranks +are ordered by floating-point conversion subrank. +The subrank forms a total order among types with equal ranks. +The types +\tcode{std::float16_t}, +\tcode{std::float32_t}, +\tcode{std::float64_t}, and +\tcode{std::float128_t}\iref{stdfloat.syn} +have a greater conversion subrank than any standard floating-point type +with equal conversion rank. +Otherwise, the conversion subrank order is +\impldef{floating-point conversion subrank}. \pnum \begin{note} -The runtime pointer alignment function\iref{ptr.align} -can be used to obtain an aligned pointer within a buffer; -an \grammarterm{alignment-specifier}\iref{dcl.align} -can be used to align storage explicitly. +The floating-point conversion rank and subrank are used in +the definition of the usual arithmetic conversions\iref{expr.arith.conv}. \end{note} -\pnum -If a request for a specific extended alignment in a specific context is not -supported by an implementation, the program is ill-formed. - -\rSec2[class.temporary]{Temporary objects} +\rSec1[basic.def]{Declarations and definitions} \pnum -\indextext{object temporary|see{temporary}}% -\indextext{temporary}% -\indextext{optimization of temporary|see{temporary, elimination of}}% -\indextext{temporary!elimination of}% -\indextext{temporary!implementation-defined generation of}% -Temporary objects are created +\indextext{declaration!definition versus}% +\indextext{declaration}% +\indextext{declaration!name}% +A declaration\iref{dcl} may (re)introduce +one or more names and/or entities into a translation +unit. +If so, the +declaration specifies the interpretation and semantic properties of these names. +A declaration of an entity or \grammarterm{typedef-name} $X$ is +a redeclaration of $X$ +if another declaration of $X$ is reachable from it\iref{module.reach}. +A declaration may also have effects including: \begin{itemize} -\item -when a prvalue is converted to an xvalue\iref{conv.rval} and -\item -when needed by the implementation to pass or return an object of trivially copyable type (see below). +\item a static assertion\iref{dcl.pre}, +\item controlling template instantiation\iref{temp.explicit}, +\item guiding template argument deduction for constructors\iref{temp.deduct.guide}, +\item use of attributes\iref{dcl.attr}, and +\item nothing (in the case of an \grammarterm{empty-declaration}). \end{itemize} -Even when the creation of the temporary object is -unevaluated\iref{expr.context}, -all the semantic restrictions shall be respected as if the temporary object -had been created and later destroyed. -\begin{note} -This includes accessibility\iref{class.access} and whether it is deleted, -for the constructor selected and for the destructor. However, in the special -case of the operand of a -\grammarterm{decltype-specifier}\iref{dcl.type.decltype}, no temporary is introduced, -so the foregoing does not apply to such a prvalue. -\end{note} \pnum -The materialization of a temporary object is generally -delayed as long as possible -in order to avoid creating unnecessary temporary objects. -\begin{note} -Temporary objects are materialized: +\indextext{declaration!function}% +\indextext{definition}% +Each entity declared by a \grammarterm{declaration} is +also \defnx{defined}{define} by that declaration unless: \begin{itemize} \item -when binding a reference to a prvalue\iref{dcl.init.ref,expr.type.conv, -expr.dynamic.cast,expr.static.cast,expr.const.cast,expr.cast}, +it declares a function +without specifying the function's body\iref{dcl.fct.def}, \item -when performing certain member accesses on a class prvalue\iref{expr.ref,expr.mptr.oper}, +it contains +the +\indextext{declaration!\idxcode{extern}}% +\keyword{extern} specifier\iref{dcl.stc} or a +\grammarterm{linkage-specification} +\begin{footnote} +Appearing inside the brace-enclosed +\grammarterm{declaration-seq} in a \grammarterm{linkage-specification} does +not affect whether a declaration is a definition. +\end{footnote} +\iref{dcl.link} +and neither an \grammarterm{initializer} nor a +\grammarterm{function-body}, \item -when invoking an implicit object member function on a class prvalue\iref{expr.call}, +\indextext{declaration!static member@\tcode{static} member}% +it declares a non-inline static data member in a class +definition\iref{class.mem,class.static}, \item -when performing an array-to-pointer conversion or subscripting on an array prvalue\iref{conv.array,expr.sub}, +it declares a static data member outside a class definition +and the variable was defined within the class with the \keyword{constexpr} +specifier\iref{class.static.data} (this usage is deprecated; see \ref{depr.static.constexpr}), \item -when initializing an object of type \tcode{std::initializer_list} from a \grammarterm{braced-init-list}\iref{dcl.init.list}, +\indextext{declaration!class name}% +it is an \grammarterm{elaborated-type-specifier}\iref{class.name}, \item -for certain unevaluated operands\iref{expr.typeid,expr.sizeof}, and +it is an +\indextext{declaration!opaque enum}% +\grammarterm{opaque-enum-declaration}\iref{dcl.enum}, \item -when a prvalue that has type other than \cv{}~\keyword{void} appears as a discarded-value expression\iref{expr.context}. +it is a +\indextext{parameter!template}\indextext{template parameter}% +\grammarterm{template-parameter}\iref{temp.param}, +\item +it is a +\indextext{declaration!parameter}\indextext{parameter declaration}% +\grammarterm{parameter-declaration}\iref{dcl.fct} in a function +\indextext{declarator}% +declarator that is not the \grammarterm{declarator} of a +\grammarterm{function-definition}, +\item +it is a +\indextext{declaration!\idxcode{typedef}}% +\keyword{typedef} declaration\iref{dcl.typedef}, +\item it is +an \grammarterm{alias-declaration}\iref{dcl.typedef}, +\item it is +a +\grammarterm{using-declaration}\iref{namespace.udecl}, +\item it is +a \grammarterm{deduction-guide}\iref{temp.deduct.guide}, +\item it is +a \grammarterm{static_assert-declaration}\iref{dcl.pre}, +\item +it is an +\grammarterm{attribute-declaration}\iref{dcl.pre}, +\item +it is an +\grammarterm{empty-declaration}\iref{dcl.pre}, +\item it is +a \grammarterm{using-directive}\iref{namespace.udir}, +\item it is +a \grammarterm{using-enum-declaration}\iref{enum.udecl}, +\item it is +a \grammarterm{template-declaration}\iref{temp.pre} +whose \grammarterm{template-head} is not followed by +either a \grammarterm{concept-definition} or a \grammarterm{declaration} +that defines a function, a class, a variable, or a static data member, +\item it is +an explicit instantiation declaration\iref{temp.explicit}, or +\item it is +an explicit specialization\iref{temp.expl.spec} whose +\grammarterm{declaration} is not a definition. \end{itemize} -\end{note} +A declaration is said to be a \defn{definition} of each entity that it defines. \begin{example} -Consider the following code: +All but one of the following are definitions: \begin{codeblock} -class X { -public: - X(int); - X(const X&); - X& operator=(const X&); - ~X(); +int a; // defines \tcode{a} +extern const int c = 1; // defines \tcode{c} +int f(int x) { return x+a; } // defines \tcode{f} and defines \tcode{x} +struct S { int a; int b; }; // defines \tcode{S}, \tcode{S::a}, and \tcode{S::b} +struct X { // defines \tcode{X} + int x; // defines non-static data member \tcode{x} + static int y; // declares static data member \tcode{y} + X(): x(0) { } // defines a constructor of \tcode{X} }; +int X::y = 1; // defines \tcode{X::y} +enum { up, down }; // defines \tcode{up} and \tcode{down} +namespace N { int d; } // defines \tcode{N} and \tcode{N::d} +namespace N1 = N; // defines \tcode{N1} +X anX; // defines \tcode{anX} -class Y { -public: - Y(int); - Y(Y&&); - ~Y(); -}; +\end{codeblock} +whereas these are just declarations: +\begin{codeblock} +extern int a; // declares \tcode{a} +extern const int c; // declares \tcode{c} +int f(int); // declares \tcode{f} +struct S; // declares \tcode{S} +typedef int Int; // declares \tcode{Int} +extern X anotherX; // declares \tcode{anotherX} +using N::d; // declares \tcode{d} +\end{codeblock} +\end{example} -X f(X); -Y g(Y); +\pnum +\begin{note} +\indextext{implementation-generated}% +In some circumstances, \Cpp{} implementations implicitly define the +default constructor\iref{class.default.ctor}, +copy constructor, move constructor\iref{class.copy.ctor}, +copy assignment operator, move assignment operator\iref{class.copy.assign}, +or destructor\iref{class.dtor} member functions. +\end{note} +\begin{example} +Given +\begin{codeblock} +#include -void h() { - X a(1); - X b = f(X(2)); - Y c = g(Y(3)); - a = f(a); +struct C { + std::string s; // \tcode{std::string} is the standard library class\iref{string.classes} +}; + +int main() { + C a; + C b = a; + b = a; } \end{codeblock} - -\indextext{class object copy|see{constructor, copy}}% -\indextext{constructor!copy}% -\tcode{X(2)} is constructed in the space used to hold \tcode{f()}'s argument and -\tcode{Y(3)} is constructed in the space used to hold \tcode{g()}'s argument. -Likewise, -\tcode{f()}'s result is constructed directly in \tcode{b} and -\tcode{g()}'s result is constructed directly in \tcode{c}. -On the other hand, the expression -\tcode{a = f(a)} -requires a temporary for -the result of \tcode{f(a)}, -which is materialized so that the reference parameter -of \tcode{X::operator=(const X\&)} can bind to it. +the implementation will implicitly define functions to make the +definition of \tcode{C} equivalent to +\begin{codeblock} +struct C { + std::string s; + C() : s() { } + C(const C& x): s(x.s) { } + C(C&& x): s(static_cast(x.s)) { } + @\rlap{\textnormal{\textit{//}}}@ : s(std::move(x.s)) { } + C& operator=(const C& x) { s = x.s; return *this; } + C& operator=(C&& x) { s = static_cast(x.s); return *this; } + @\rlap{\textnormal{\textit{//}}}@ { s = std::move(x.s); return *this; } + ~C() { } +}; +\end{codeblock} \end{example} \pnum -When an object of class type \tcode{X} -is passed to or returned from a potentially-evaluated function call, -if \tcode{X} has at least one eligible copy or move constructor\iref{special}, -each such constructor is trivial, -and the destructor of \tcode{X} is either trivial or deleted, -implementations are permitted -to create a temporary object -to hold the function parameter or result object. -The temporary object is constructed -from the function argument or return value, respectively, -and the function's parameter or return object -is initialized as if by -using the eligible trivial constructor to copy the temporary -(even if that constructor is inaccessible -or would not be selected by overload resolution -to perform a copy or move of the object). \begin{note} -This latitude is granted to allow objects of class type to be passed to or returned from functions in registers. +A class name can also be implicitly declared by an +\grammarterm{elaborated-type-specifier}\iref{dcl.type.elab}. \end{note} \pnum -\indextext{temporary!constructor for}% -\indextext{temporary!destructor for}% -\indextext{temporary!destruction of}% -Temporary objects are destroyed as the last step -in evaluating -the full-expression\iref{intro.execution} -that (lexically) contains the point where -they were created. -This is true even if that evaluation ends in throwing an exception. -The -\indextext{value computation}% -value computations and -\indextext{side effects}% -side effects of destroying a temporary object -are associated only with the full-expression, not with any specific -subexpression. +\indextext{type!incomplete}% +In the definition of an object, +the type of that object shall not be +an incomplete type\iref{term.incomplete.type}, +an abstract class type\iref{class.abstract}, or +a (possibly multidimensional) array thereof. + +\rSec1[basic.scope]{Scope}% +\indextext{scope|(} + +\rSec2[basic.scope.scope]{General} \pnum -\indextext{initializer!temporary and declarator}% -\indextext{temporary!order of destruction of}% -There are five contexts in which temporaries are destroyed at a different -point than the end of the full-expression. -The first context is when a default constructor is called to initialize -an element of an array with no corresponding initializer\iref{dcl.init}. -The second context is when a copy constructor is called to copy an element of -an array while the entire array is copied\iref{expr.prim.lambda.capture,class.copy.ctor}. -In either case, if the constructor has one or more default arguments, -the destruction of every temporary created in a default argument is -sequenced before the construction of the next array element, if any. +The declarations in a program appear in a number of \defnx{scopes}{scope} +that are in general discontiguous. +The \defnadj{global}{scope} contains the entire program; +every other scope $S$ is introduced by a +declaration, +\grammarterm{parameter-declaration-clause}, +\grammarterm{statement}, or \grammarterm{handler} +(as described in the following subclauses of \ref{basic.scope}) +appearing in another scope which thereby contains $S$. +An \defnadj{enclosing}{scope} at a program point is any scope that contains it; +the smallest such scope is said to be the \defnadj{immediate}{scope} +at that point. +A scope \defnx{intervenes}{scope!intervene} +between a program point $P$ and a scope $S$ +(that does not contain $P$) if it is or contains $S$ but does not contain $P$. \pnum -The third context is when a reference binds to a temporary object. -\begin{footnote} -The same rules apply to initialization of an - \tcode{initializer_list} object\iref{dcl.init.list} with its - underlying temporary array. -\end{footnote} -The temporary object to which the reference is bound or the temporary object -that is the complete object of a subobject to which the reference is bound -persists for the lifetime of the reference if the glvalue -to which the reference is bound -was obtained through one of the following: +Unless otherwise specified: \begin{itemize} \item - a temporary materialization conversion\iref{conv.rval}, +The smallest scope that contains a scope $S$ is +the \defnadj{parent}{scope} of $S$. \item - \tcode{(} \grammarterm{expression} \tcode{)}, - where \grammarterm{expression} is one of these expressions, +No two declarations (re)introduce the same entity. \item - subscripting\iref{expr.sub} of an array operand, - where that operand is one of these expressions, +A declaration \defnx{inhabits}{scope!inhabit} +the immediate scope at its locus\iref{basic.scope.pdecl}. \item - a class member access\iref{expr.ref} using the \tcode{.} operator - where the left operand is one of these expressions and - the right operand designates a non-static data member of non-reference type, +A declaration's \defnadj{target}{scope} is the scope it inhabits. \item - a pointer-to-member operation\iref{expr.mptr.oper} using the \tcode{.*} operator - where the left operand is one of these expressions and - the right operand is a pointer to data member of non-reference type, +Any names (re)introduced by a declaration are \defnx{bound}{name!bound} to it +in its target scope. +\end{itemize} +An entity \defnx{belongs}{entity!belong} to a scope $S$ +if $S$ is the target scope of a declaration of the entity. +\begin{note} +Special cases include that: +\begin{itemize} \item - a - \begin{itemize} - \item \keyword{const_cast}\iref{expr.const.cast}, - \item \keyword{static_cast}\iref{expr.static.cast}, - \item \keyword{dynamic_cast}\iref{expr.dynamic.cast}, or - \item \keyword{reinterpret_cast}\iref{expr.reinterpret.cast} - \end{itemize} - converting, without a user-defined conversion, - a glvalue operand that is one of these expressions - to a glvalue that refers - to the object designated by the operand, or - to its complete object or a subobject thereof, +Template parameter scopes are parents +only to other template parameter scopes\iref{basic.scope.temp}. \item - a conditional expression\iref{expr.cond} that is a glvalue - where the second or third operand is one of these expressions, or +Corresponding declarations with appropriate linkage +declare the same entity\iref{basic.link}. \item - a comma expression\iref{expr.comma} that is a glvalue - where the right operand is one of these expressions. +The declaration in a \grammarterm{template-declaration} +inhabits the same scope as the \grammarterm{template-declaration}. +\item +Friend declarations and +declarations of template specializations do not bind names\iref{dcl.meaning}; +those with qualified names target a specified scope, and +other friend declarations and +certain \grammarterm{elaborated-type-specifier}s\iref{dcl.type.elab} +target a larger enclosing scope. +\item +Block-scope extern declarations target a larger enclosing scope +but bind a name in their immediate scope. +\item +The names of unscoped enumerators are bound +in the two innermost enclosing scopes\iref{dcl.enum}. +\item +A class's name is also bound in its own scope\iref{class.pre}. +\item +The names of the members of an anonymous union are bound in +the union's parent scope\iref{class.union.anon}. \end{itemize} -\begin{example} -\begin{codeblock} -template using id = T; +\end{note} -int i = 1; -int&& a = id{1, 2, 3}[i]; // temporary array has same lifetime as \tcode{a} -const int& b = static_cast(0); // temporary \tcode{int} has same lifetime as \tcode{b} -int&& c = cond ? id{1, 2, 3}[i] : static_cast(0); - // exactly one of the two temporaries is lifetime-extended -\end{codeblock} -\end{example} +\pnum +Two non-static member functions have +\defnadjx{corresponding}{object parameters}{object parameter} if +\begin{itemize} +\item +exactly one is an implicit object member function +with no \grammarterm{ref-qualifier} and +the types of their object parameters\iref{dcl.fct}, +after removing references, +are the same, or +\item +their object parameters have the same type. +\end{itemize} +\indextext{template!function!corresponding object parameter}% +Two non-static member function templates have +\defnadjx{corresponding}{object parameters}{object parameter} if +\begin{itemize} +\item +exactly one is an implicit object member function +with no \grammarterm{ref-qualifier} and +the types of their object parameters, +after removing any references, +are equivalent, or +\item +the types of their object parameters are equivalent. +\end{itemize} +\indextext{template!function!corresponding signature}% +Two function templates have +\defnadjx{corresponding}{signatures}{signature} if +their \grammarterm{template-parameter-list}{s} +have the same length, +their corresponding \grammarterm{template-parameter}{s} are equivalent, +they have equivalent non-object-parameter-type-lists and return types (if any), and, +if both are non-static members, they have corresponding object parameters. + +\pnum +Two declarations \defn{correspond} +if they (re)introduce the same name, +both declare constructors, or +both declare destructors, +unless +\begin{itemize} +\item +either is a \grammarterm{using-declarator}, or +\item +one declares a type (not a \grammarterm{typedef-name}) and the other declares a +variable, +non-static data member other than of an anonymous union\iref{class.union.anon}, +enumerator, +function, or +function template, or +\item +each declares a function or function template +and they do not declare corresponding overloads. +\end{itemize} +Two function or function template declarations declare +\defn{corresponding overloads} if +\begin{itemize} +\item +both declare functions with the same non-object-parameter-type-list, +\begin{footnote} +An implicit object parameter\iref{over.match.funcs} +is not part of the parameter-type-list. +\end{footnote} +equivalent\iref{temp.over.link} trailing \grammarterm{requires-clause}s +(if any, except as specified in \ref{temp.friend}), and, +if both are non-static members, +they have corresponding object parameters, or +\item +both declare function templates with corresponding signatures and equivalent +\grammarterm{template-head}s and +trailing \grammarterm{requires-clause}s (if any). +\end{itemize} \begin{note} -An explicit type conversion\iref{expr.type.conv,expr.cast} -is interpreted as -a sequence of elementary casts, -covered above. +Declarations can correspond even if neither binds a name. \begin{example} \begin{codeblock} -const int& x = (const int&)1; // temporary for value 1 has same lifetime as x +struct A { + friend void f(); // \#1 +}; +struct B { + friend void f() {} // corresponds to, and defines, \#1 +}; \end{codeblock} \end{example} \end{note} -\begin{note} -If a temporary object has a reference member initialized by another temporary object, -lifetime extension applies recursively to such a member's initializer. \begin{example} \begin{codeblock} -struct S { - const int& m; +typedef int Int; +enum E : int { a }; +void f(int); // \#1 +void f(Int) {} // defines \#1 +void f(E) {} // OK, another overload + +struct X { + static void f(); + void f() const; // error: redeclaration + void g(); + void g() const; // OK + void g() &; // error: redeclaration + + void h(this X&, int); + void h(int) &&; // OK, another overload + void j(this const X&); + void j() const &; // error: redeclaration + void k(); + void k(this X&); // error: redeclaration }; -const S& s = S{1}; // both \tcode{S} and \tcode{int} temporaries have lifetime of \tcode{s} \end{codeblock} \end{example} -\end{note} -The exceptions to this lifetime rule are: +\pnum +A declaration is \defnx{name-independent}{declaration!name-independent} +if its name is \tcode{_} (\unicode{005f}{low line}) and it declares \begin{itemize} -\item A temporary object bound to a reference parameter in a function call\iref{expr.call} -persists until the completion of the full-expression containing the call. +\item +a variable with automatic storage duration, +\item +a structured binding +%FIXME: "and" is strange below; maybe reword to something like: +%FIXME: "that has no \grammarterm{storage-class-specifier} and +%FIXME: that is not inhabiting a namespace scope," +with no \grammarterm{storage-class-specifier} and +not inhabiting a namespace scope, +\item +the variable introduced by an \grammarterm{init-capture}, or +\item +%FIXME: "of" is strange below; remove it? +a non-static data member of other than an anonymous union. +\end{itemize} -\item A temporary object bound to a reference element of -an aggregate of class type initialized from -a parenthesized \grammarterm{expression-list}\iref{dcl.init} -persists until the completion of the full-expression -containing the \grammarterm{expression-list}. +\recommended +Implementations should not emit a warning +that a name-independent declaration is used or unused. -\item A temporary bound to a reference in a \grammarterm{new-initializer}\iref{expr.new} persists until the completion of the full-expression containing the \grammarterm{new-initializer}. +\pnum +\indextext{declaration!potentially conflict}% +Two declarations \defn{potentially conflict} +if they correspond and +cause their shared name to denote different entities\iref{basic.link}. +The program is ill-formed +if, in any scope, a name is bound to two declarations $A$ and $B$ +that potentially conflict and $A$ precedes $B$\iref{basic.lookup}, +unless $B$ is name-independent. \begin{note} -This might introduce a dangling reference. +An \grammarterm{id-expression} that names a unique name-independent declaration +is usable until an additional declaration of the same name +is introduced in the same scope\iref{basic.lookup.general}. +\end{note} +\begin{note} +Overload resolution can consider potentially conflicting declarations +found in multiple scopes +(e.g., via \grammarterm{using-directive}s or for operator functions), +in which case it is often ambiguous. \end{note} \begin{example} \begin{codeblock} -struct S { int mi; const std::pair& mp; }; -S a { 1, {2,3} }; -S* p = new S{ 1, {2,3} }; // creates dangling reference +void f() { + int x,y; + void x(); // error: different entity for \tcode{x} + int y; // error: redefinition +} +enum { f }; // error: different entity for \tcode{::f} +namespace A {} +namespace B = A; +namespace B = A; // OK, no effect +namespace B = B; // OK, no effect +namespace A = B; // OK, no effect +namespace B {} // error: different entity for \tcode{B} + +void g() { + int _; + _ = 0; // OK + int _; // OK, name-independent declaration + _ = 0; // error: two non-function declarations in the lookup set +} +void h () { + int _; // \#1 + _ ++; // OK + static int _; // error: conflicts with \#1 because static variables are not name-independent +} \end{codeblock} \end{example} -\end{itemize} - -\pnum -The fourth context is when a temporary object -is created in the \grammarterm{for-range-initializer} of a range-based \keyword{for} statement. -If such a temporary object would otherwise be destroyed -at the end of the \grammarterm{for-range-initializer} full-expression, -the object persists for the lifetime of the reference -initialized by the \grammarterm{for-range-initializer}. - -\pnum -The fifth context is when a temporary object -is created in a structured binding declaration\iref{dcl.struct.bind}. -Any temporary objects introduced by -the \grammarterm{initializer}{s} for the variables -with unique names -are destroyed at the end of the structured binding declaration. - -\pnum -Let \tcode{x} and \tcode{y} each be either -a temporary object whose lifetime is not extended, or -a function parameter. -If the lifetimes of \tcode{x} and \tcode{y} end at -the end of the same full-expression, and -\tcode{x} is initialized before \tcode{y}, then -the destruction of \tcode{y} is sequenced before that of \tcode{x}. -If the lifetime of two or more temporaries -with lifetimes extending beyond the full-expressions in which they were created -ends at the same point, -these temporaries are destroyed at that point in the reverse order of the -completion of their construction. -In addition, the destruction of such temporaries shall -take into account the ordering of destruction of objects with static, thread, or -automatic storage duration\iref{basic.stc.static,basic.stc.thread,basic.stc.auto}; -that is, if -\tcode{obj1} -is an object with the same storage duration as the temporary and -created before the temporary is created -the temporary shall be destroyed before -\tcode{obj1} -is destroyed; -if -\tcode{obj2} -is an object with the same storage duration as the temporary and -created after the temporary is created -the temporary shall be destroyed after -\tcode{obj2} -is destroyed. \pnum +\indextext{declaration!nominable}% +A declaration is \defn{nominable} +in a class, class template, or namespace $E$ at a point $P$ if +it precedes $P$, +it does not inhabit a block scope, and +its target scope is the scope associated with $E$ or, +if $E$ is a namespace, +any element of the inline namespace set of $E$\iref{namespace.def}. \begin{example} \begin{codeblock} -struct S { - S(); - S(int); - friend S operator+(const S&, const S&); - ~S(); -}; -S obj1; -const S& cr = S(16)+S(23); -S obj2; +namespace A { + void f() {void g();} + inline namespace B { + struct S { + friend void h(); + static int i; + }; + } +} \end{codeblock} - -The expression -\tcode{S(16) + S(23)} -creates three temporaries: -a first temporary -\tcode{T1} -to hold the result of the expression -\tcode{S(16)}, -a second temporary -\tcode{T2} -to hold the result of the expression -\tcode{S(23)}, -and a third temporary -\tcode{T3} -to hold the result of the addition of these two expressions. -The temporary -\tcode{T3} -is then bound to the reference -\tcode{cr}. -It is unspecified whether -\tcode{T1} -or -\tcode{T2} -is created first. -On an implementation where -\tcode{T1} -is created before -\tcode{T2}, -\tcode{T2} -shall be destroyed before -\tcode{T1}. -The temporaries -\tcode{T1} -and -\tcode{T2} -are bound to the reference parameters of -\tcode{\keyword{operator}+}; -these temporaries are destroyed at the end of the full-expression -containing the call to -\tcode{\keyword{operator}+}. -The temporary -\tcode{T3} -bound to the reference -\tcode{cr} -is destroyed at the end of -\tcode{cr}'s -lifetime, that is, at the end of the program. -In addition, the order in which -\tcode{T3} -is destroyed takes into account the destruction order of other objects with -static storage duration. -That is, because -\tcode{obj1} -is constructed before -\tcode{T3}, -and -\tcode{T3} -is constructed before -\tcode{obj2}, -\tcode{obj2} -shall be destroyed before -\tcode{T3}, -and -\tcode{T3} -shall be destroyed before -\tcode{obj1}. +At the end of this example, +the declarations of \tcode{f}, \tcode{B}, \tcode{S}, and \tcode{h} +are nominable in \tcode{A}, but those of \tcode{g} and \tcode{i} are not. \end{example} -\rSec1[basic.types]{Types}% +\pnum +When instantiating a templated entity\iref{temp.pre}, +any scope $S$ introduced by any part of the template definition is considered +to be introduced by the instantiated entity and +to contain the instantiations of any declarations that inhabit $S$. -\rSec2[basic.types.general]{General}% -\indextext{type|(} +\rSec2[basic.scope.pdecl]{Point of declaration} -\pnum -\begin{note} -\ref{basic.types} and the subclauses thereof -impose requirements on implementations regarding the representation -of types. -There are two kinds of types: fundamental types and compound types. -Types describe objects\iref{intro.object}, -references\iref{dcl.ref}, -or functions\iref{dcl.fct}. -\end{note} +\indextext{declaration!point of|see{locus}}% +\indextext{scope!declarations and|see{locus}}% +\indextext{locus|(}% \pnum -\indextext{object!byte copying and|(}% -\indextext{type!trivially copyable}% -For any object (other than a potentially-overlapping subobject) of trivially copyable type -\tcode{T}, whether or not the object holds a valid value of type -\tcode{T}, the underlying bytes\iref{intro.memory} making up the -object can be copied into an array of -\keyword{char}, -\tcode{\keyword{unsigned} \keyword{char}}, or -\tcode{std::byte}\iref{cstddef.syn}. -\begin{footnote} -By using, for example, the library -functions\iref{headers} \tcode{std::memcpy} or \tcode{std::memmove}. -\end{footnote} -If the content of that array -is copied back into the object, the object shall -subsequently hold its original value. +\indextext{declaration!locus|see{locus}}% +The \defn{locus} of a declaration\iref{basic.link} that is a declarator +is immediately after the complete declarator\iref{dcl.decl}. \begin{example} \begin{codeblock} -constexpr std::size_t N = sizeof(T); -char buf[N]; -T obj; // \tcode{obj} initialized to its original value -std::memcpy(buf, &obj, N); // between these two calls to \tcode{std::memcpy}, \tcode{obj} might be modified -std::memcpy(&obj, buf, N); // at this point, each subobject of \tcode{obj} of scalar type holds its original value +unsigned char x = 12; +{ unsigned char x = x; } \end{codeblock} +Here, the initialization of the second \tcode{x} has undefined behavior, +because the initializer accesses the second \tcode{x} +outside its lifetime\iref{basic.life}. \end{example} \pnum -For two distinct objects \tcode{obj1} and \tcode{obj2} -of trivially copyable type \tcode{T}, -where neither \tcode{obj1} nor \tcode{obj2} is a potentially-overlapping subobject, -if the underlying bytes\iref{intro.memory} making up -\tcode{obj1} are copied into \tcode{obj2}, -\begin{footnote} -By using, for example, -the library functions\iref{headers} \tcode{std::memcpy} or \tcode{std::memmove}. -\end{footnote} - \tcode{obj2} shall subsequently hold the same value as -\tcode{obj1}. +\begin{note} +\indextext{name hiding}% +A name from an outer scope remains visible up to +the locus of the declaration that hides it. \begin{example} \begin{codeblock} -T* t1p; -T* t2p; - // provided that \tcode{t2p} points to an initialized object ... -std::memcpy(t1p, t2p, sizeof(T)); - // at this point, every subobject of trivially copyable type in \tcode{*t1p} contains - // the same value as the corresponding subobject in \tcode{*t2p} +const int i = 2; +{ int i[i]; } \end{codeblock} +declares a block-scope array of two integers. \end{example} -\indextext{object!byte copying and|)} +\end{note} \pnum -\label{term.object.representation}% -The \defnx{object representation}{representation!object} -of a complete object type \tcode{T} is the -sequence of \placeholder{N} \tcode{\keyword{unsigned} \keyword{char}} objects taken up -by a non-bit-field complete object of type \tcode{T}, -where \placeholder{N} equals -\tcode{\keyword{sizeof}(T)}. -The \defnx{value representation}{representation!value} -of a type \tcode{T} is the set of bits -in the object representation of \tcode{T} -that participate in representing a value of type \tcode{T}. -The object and value representation of -a non-bit-field complete object of type \tcode{T} are -the bytes and bits, respectively, of -the object corresponding to the object and value representation of its type. -The object representation of a bit-field object is -the sequence of \placeholder{N} bits taken up by the object, -where \placeholder{N} is the width of the bit-field\iref{class.bit}. -The value representation of a bit-field object is -the set of bits in the object representation that -participate in representing its value. -\label{term.padding.bits}% -Bits in the object representation of a type or object that are -not part of the value representation -are \defn{padding bits}. -For trivially copyable types, the value representation is -a set of bits in the object representation that determines a -\defn{value}, which is one discrete element of an -\impldef{values of a trivially copyable type} set of values. -\begin{footnote} -The intent is that the memory model of \Cpp{} is compatible -with that of the C programming language. -\end{footnote} +The locus of a \grammarterm{class-specifier} is immediately after +the \grammarterm{identifier} or \grammarterm{simple-template-id} (if any) +in its \grammarterm{class-head}\iref{class.pre}. +The locus of an \grammarterm{enum-specifier} +is immediately after +its \grammarterm{enum-head}; +the locus of an \grammarterm{opaque-enum-declaration} +is immediately after it\iref{dcl.enum}. +%FIXME: What's "it" below? What's "it" above? +The locus of an \grammarterm{alias-declaration} is immediately after it. \pnum -\indextext{type!incompletely-defined object}% -A class that has been declared but not defined, an enumeration type in certain -contexts\iref{dcl.enum}, or an array of unknown -bound or of incomplete element type, is an -\defnadj{incompletely-defined}{object type}. -\begin{footnote} -The size and layout of an instance of an incompletely-defined -object type is unknown. -\end{footnote} -\label{term.incomplete.type}% -Incompletely-defined object types and \cv{}~\keyword{void} are -\defnadjx{incomplete}{types}{type}\iref{basic.fundamental}. -\begin{note} -Objects cannot be defined to have an incomplete type\iref{basic.def}. -\end{note} +The locus of a \grammarterm{using-declarator} +that does not name a constructor +is immediately after the \grammarterm{using-declarator}\iref{namespace.udecl}. \pnum -A class type (such as ``\tcode{\keyword{class} X}'') can be incomplete at one -point in a translation unit and complete later on; the type -``\tcode{\keyword{class} X}'' is the same type at both points. The declared type -of an array object can be an array of incomplete class type and -therefore incomplete; if the class type is completed later on in the -translation unit, the array type becomes complete; the array type at -those two points is the same type. The declared type of an array object -can be an array of unknown bound and therefore be incomplete at one -point in a translation unit and complete later on; the array types at -those two points (``array of unknown bound of \tcode{T}'' and ``array of -\tcode{N} \tcode{T}'') are different types. -\begin{note} -The type of a pointer or reference to array of unknown bound -permanently points to or refers to an incomplete type. -An array of unknown bound named by a \keyword{typedef} declaration -permanently refers to an incomplete type. -In either case, the array type cannot be completed. -\end{note} +The locus of an \grammarterm{enumerator-definition} is immediately after it. \begin{example} -\indextext{type!example of incomplete}% \begin{codeblock} -class X; // \tcode{X} is an incomplete type -extern X* xp; // \tcode{xp} is a pointer to an incomplete type -extern int arr[]; // the type of arr is incomplete -typedef int UNKA[]; // \tcode{UNKA} is an incomplete type -UNKA* arrp; // \tcode{arrp} is a pointer to an incomplete type -UNKA** arrpp; - -void foo() { - xp++; // error: \tcode{X} is incomplete - arrp++; // error: incomplete type - arrpp++; // OK, sizeof \tcode{UNKA*} is known -} - -struct X { int i; }; // now \tcode{X} is a complete type -int arr[10]; // now the type of \tcode{arr} is complete - -X x; -void bar() { - xp = &x; // OK; type is ``pointer to \tcode{X}'' - arrp = &arr; // OK; qualification conversion\iref{conv.qual} - xp++; // OK, \tcode{X} is complete - arrp++; // error: \tcode{UNKA} can't be completed -} +const int x = 12; +{ enum { x = x }; } \end{codeblock} +Here, the enumerator \tcode{x} is initialized with the value of the +constant \tcode{x}, namely 12. \end{example} \pnum \begin{note} -The rules for declarations and expressions describe in which -contexts incomplete types are prohibited. +\indextext{type!incomplete}% +After the declaration of a class member, +the member name can be found in the scope of its class +even if the class is an incomplete class. +\begin{example} +\begin{codeblock} +struct X { + enum E { z = 16 }; + int b[X::z]; // OK +}; +\end{codeblock} +\end{example} \end{note} \pnum -\label{term.object.type}% -An \defn{object type} is a (possibly cv-qualified) type that is not -a function type, not a reference type, and not \cv{}~\keyword{void}. +The locus of an \grammarterm{elaborated-type-specifier} +that is a declaration\iref{dcl.type.elab} is immediately after it. \pnum -\indextext{class!trivial}% -\indextext{class!trivially copyable}% -\indextext{class!standard-layout}% -\label{term.scalar.type}% -Arithmetic types\iref{basic.fundamental}, enumeration types, -pointer types, pointer-to-member types\iref{basic.compound}, -\tcode{std::nullptr_t}, -and -cv-qualified\iref{basic.type.qualifier} versions of these -types are collectively called -\defnadjx{scalar}{types}{type}. -\label{term.trivially.copyable.type}% -Scalar types, trivially copyable class types\iref{class.prop}, -arrays of such types, and cv-qualified versions of these -types are collectively called \defnadjx{trivially copyable}{types}{type}. -\label{term.trivial.type}% -Scalar types, trivial class types\iref{class.prop}, -arrays of such types, and cv-qualified versions of these -types are collectively called -\defnadjx{trivial}{types}{type}. -\label{term.standard.layout.type}% -Scalar types, standard-layout class -types\iref{class.prop}, arrays of such types, and -cv-qualified versions of these types -are collectively called \defnadjx{standard-layout}{types}{type}. -\label{term.implicit.lifetime.type}% -Scalar types, implicit-lifetime class types\iref{class.prop}, -array types, and cv-qualified versions of these types -are collectively called \defnadjx{implicit-lifetime}{types}{type}. +The locus of an injected-class-name declaration\iref{class.pre} +is immediately following the opening brace of the class definition. \pnum -\label{term.literal.type}% -A type is a \defnadj{literal}{type} if it is: -\begin{itemize} -\item \cv{}~\keyword{void}; or -\item a scalar type; or -\item a reference type; or -\item an array of literal type; or -\item a possibly cv-qualified class type\iref{class} that -has all of the following properties: -\begin{itemize} -\item it has a constexpr destructor\iref{dcl.constexpr}, -\item all of its non-static non-variant data members and base classes are of non-volatile literal types, and -\item it -\begin{itemize} -\item is a closure type\iref{expr.prim.lambda.closure}, -\item is an aggregate union type that has either -no variant members or -at least one variant member of non-volatile literal type, -\item is a non-union aggregate type for which -each of its anonymous union members -satisfies the above requirements for an aggregate union type, or -\item has at least one constexpr constructor or constructor template -(possibly inherited\iref{namespace.udecl} from a base class) -that is not a copy or move constructor. -\end{itemize} -\end{itemize} -\end{itemize} -\begin{note} -A literal type is one for which -it might be possible to create an object -within a constant expression. -It is not a guarantee that it is possible to create such an object, -nor is it a guarantee that any object of that type -will be usable in a constant expression. +The locus of the implicit declaration of +a function-local predefined variable\iref{dcl.fct.def.general} +is immediately before +the \grammarterm{function-body} of its function's definition. + +\pnum +The locus of the declaration of a structured binding\iref{dcl.struct.bind} +is immediately after +the \grammarterm{identifier-list} of the structured binding declaration. + +\pnum +The locus of a \grammarterm{for-range-declaration} +of a range-based \keyword{for} statement\iref{stmt.ranged} +is immediately after the \grammarterm{for-range-initializer}. + +\pnum +The locus of a \grammarterm{template-parameter} is immediately after it. +\begin{example} +\begin{codeblock} +typedef unsigned char T; +template struct A { }; +\end{codeblock} +\end{example} + +\pnum +The locus of a \grammarterm{concept-definition} +is immediately after its \grammarterm{concept-name}\iref{temp.concept}. +\begin{note} +The \grammarterm{constraint-expression} cannot use +the \grammarterm{concept-name}. \end{note} \pnum -\label{term.layout.compatible.type}% -Two types \cvqual{cv1} \tcode{T1} and \cvqual{cv2} \tcode{T2} are -\defnadjx{layout-compatible}{types}{type} -if \tcode{T1} and \tcode{T2} are the same type, -layout-compatible enumerations\iref{dcl.enum}, or -layout-compatible standard-layout class types\iref{class.mem}. +The locus of a \grammarterm{namespace-definition} +with an \grammarterm{identifier} +is immediately after the \grammarterm{identifier}. +\begin{note} +An identifier is invented +for an \grammarterm{unnamed-namespace-definition}\iref{namespace.unnamed}. +\end{note} -\rSec2[basic.fundamental]{Fundamental types} +\pnum +\begin{note} +Friend declarations can introduce functions or classes +that belong to the nearest enclosing namespace or block scope, +but they do not bind names anywhere\iref{class.friend}. +Function declarations at block scope and +variable declarations with the \keyword{extern} specifier at block scope +declare entities +that belong to the nearest enclosing namespace, +but they do not bind names in it. +\end{note} \pnum -\indextext{type!implementation-defined \tcode{sizeof}}% -There are five \defnadjx{standard signed integer}{types}{type}: -\indextext{type!\idxcode{signed char}}% -\indextext{type!\idxcode{short}}% -\indextext{type!\idxcode{int}}% -\indextext{type!\idxcode{long}}% -\indextext{type!\idxcode{long long}}% -``\tcode{\keyword{signed} \keyword{char}}'', ``\tcode{\keyword{short} \keyword{int}}'', ``\keyword{int}'', -``\tcode{\keyword{long} \keyword{int}}'', and ``\tcode{\keyword{long} \keyword{long} \keyword{int}}''. In -this list, each type provides at least as much storage as those -preceding it in the list. -There may also be \impldef{extended signed integer types} -\defnadjx{extended signed integer}{types}{type}. -The standard and extended signed integer types are collectively called -\defnadjx{signed integer}{types}{type}. -The range of representable values for a signed integer type is -$-2^{N-1}$ to $2^{N-1}-1$ (inclusive), -where \placeholder{N} is called the \defn{width} of the type. -\indextext{integral type!implementation-defined \tcode{sizeof}}% \begin{note} -Plain \tcode{int}s are intended to have -the natural width suggested by the architecture of the execution environment; -the other signed integer types are provided to meet special needs. +For point of instantiation of a template, see~\ref{temp.point}. \end{note} +\indextext{locus|)} + +\rSec2[basic.scope.block]{Block scope} + +\indextext{local scope|see{scope, block}}% \pnum -\indextext{type!\idxcode{unsigned}}% -For each of the standard signed integer types, -there exists a corresponding (but different) -\defnadj{standard unsigned integer}{type}: -\indextext{type!\idxcode{unsigned char}}% -\indextext{type!\idxcode{unsigned short}}% -\indextext{type!\idxcode{unsigned int}}% -\indextext{type!\idxcode{unsigned long}}% -\indextext{type!\idxcode{unsigned long long}}% -``\tcode{\keyword{unsigned} \keyword{char}}'', ``\tcode{\keyword{unsigned} \keyword{short} \keyword{int}}'', -``\tcode{\keyword{unsigned} \keyword{int}}'', ``\tcode{\keyword{unsigned} \keyword{long} \keyword{int}}'', and -``\tcode{\keyword{unsigned} \keyword{long} \keyword{long} \keyword{int}}''. -Likewise, for each of the extended signed integer types, -there exists a corresponding \defnadj{extended unsigned integer}{type}. -The standard and extended unsigned integer types -are collectively called \defnadjx{unsigned integer}{types}{type}. -An unsigned integer type has the same width \placeholder{N} -as the corresponding signed integer type. -\indextext{arithmetic!\idxcode{unsigned}}% -The range of representable values for the unsigned type is -$0$ to $2^N-1$ (inclusive); -arithmetic for the unsigned type is performed modulo $2^N$. +Each +\begin{itemize} +\item +selection or iteration statement\iref{stmt.select,stmt.iter}, +\item +substatement of such a statement, +\item +\indextext{scope!\idxgram{handler}}% +\grammarterm{handler}\iref{except.pre}, or +\item +compound statement\iref{stmt.block} +that is not the \grammarterm{compound-statement} of a \grammarterm{handler} +\end{itemize} +introduces a \defnadj{block}{scope} +that includes that statement or \grammarterm{handler}. \begin{note} -Unsigned arithmetic does not overflow. -Overflow for signed arithmetic yields undefined behavior\iref{expr.pre}. +A substatement that is also a block has only one scope. \end{note} +A variable that belongs to a block scope is a \defn{block variable}. +\begin{example} +\begin{codeblock} +int i = 42; +int a[10]; + +for (int i = 0; i < 10; i++) + a[i] = i; + +int j = i; // \tcode{j = 42} +\end{codeblock} +\end{example} \pnum -\indextext{signed integer representation!two's complement}% -An unsigned integer type has the same -object representation, -value representation, and -alignment requirements\iref{basic.align} -as the corresponding signed integer type. -For each value $x$ of a signed integer type, -the value of the corresponding unsigned integer type -congruent to $x$ modulo $2^N$ has the same value -of corresponding bits in its value representation. -\begin{footnote} -This -is also known as two's complement representation. -\end{footnote} +If a declaration +that is not a name-independent declaration and +that binds a name in the block scope $S$ of a +\begin{itemize} +\item +\grammarterm{compound-statement} of a \grammarterm{lambda-expression}, +\grammarterm{function-body}, or \grammarterm{function-try-block}, +\item +substatement of a selection or iteration statement +that is not itself a selection or iteration statement, or +\item +\grammarterm{handler} of a \grammarterm{function-try-block} +\end{itemize} +potentially conflicts with a declaration +whose target scope is the parent scope of $S$, +the program is ill-formed. \begin{example} -The value $-1$ of a signed integer type has the same representation as -the largest value of the corresponding unsigned type. +\begin{codeblock} +if (int x = f()) { + int x; // error: redeclaration of \tcode{x} +} +else { + int x; // error: redeclaration of \tcode{x} +} +\end{codeblock} \end{example} -\begin{floattable}{Minimum width}{basic.fundamental.width}{lc} -\topline -\lhdr{Type} & \rhdr{Minimum width $N$} \\ -\capsep -\tcode{\keyword{signed} \keyword{char}} & 8 \\ -\tcode{\keyword{short} \keyword{int}} & 16 \\ -\keyword{int} & 16 \\ -\tcode{\keyword{long} \keyword{int}} & 32 \\ -\tcode{\keyword{long} \keyword{long} \keyword{int}} & 64 \\ -\end{floattable} +\rSec2[basic.scope.param]{Function parameter scope} + +\indextext{scope!function prototype|see{scope, function parameter}}% +\indextext{parameter!scope of}% \pnum -The width of each standard signed integer type -shall not be less than the values specified in \tref{basic.fundamental.width}. -The value representation of a signed or unsigned integer type -comprises $N$ bits, where N is the respective width. -Each set of values for any padding bits\iref{basic.types.general} -in the object representation are -alternative representations of the value specified by the value representation. +A \grammarterm{parameter-declaration-clause} $P$ introduces +a \defnadj{function parameter}{scope} that includes $P$. \begin{note} -Padding bits have unspecified value, but cannot cause traps. -In contrast, see \IsoC{} 6.2.6.2. +A function parameter cannot be used for its value +within the \grammarterm{parameter-declaration-clause}\iref{dcl.fct.default}. \end{note} +\begin{itemize} +\item +If $P$ is associated with a \grammarterm{declarator} and +is preceded by a (possibly-parenthesized) \grammarterm{noptr-declarator} of +the form +\grammarterm{declarator-id} \opt{\grammarterm{attribute-specifier-seq}}, +its scope extends to the end of the nearest enclosing +\grammarterm{init-declarator}, +\grammarterm{member-declarator}, +\grammarterm{declarator} of a \grammarterm{parameter-declaration} or +a \grammarterm{nodeclspec-function-declaration}, or +\grammarterm{function-definition}, +but does not include the locus of the associated \grammarterm{declarator}. \begin{note} -The signed and unsigned integer types satisfy -the constraints given in \IsoC{} 5.2.4.2.1. +In this case, $P$ declares the parameters of a function +(or a function or template parameter declared with function type). +A member function's parameter scope is nested within its class's scope. \end{note} -Except as specified above, -the width of a signed or unsigned integer type is -\impldef{width of integral type}. +\item +If $P$ is associated with a \grammarterm{lambda-declarator}, +its scope extends to the end of the \grammarterm{compound-statement} +in the \grammarterm{lambda-expression}. +\item +If $P$ is associated with a \grammarterm{requirement-parameter-list}, +its scope extends to the end of the \grammarterm{requirement-body} of the \grammarterm{requires-expression}. +\item +If $P$ is associated with a \grammarterm{deduction-guide}, +its scope extends to the end of the \grammarterm{deduction-guide}. +\end{itemize} -\pnum -Each value $x$ of an unsigned integer type with width $N$ has -a unique representation $x = x_0 2^0 + x_1 2^1 + \ldots + x_{N-1} 2^{N-1}$, -where each coefficient $x_i$ is either 0 or 1; -this is called the \defn{base-2 representation} of $x$. -The base-2 representation of a value of signed integer type is -the base-2 representation of the congruent value -of the corresponding unsigned integer type. -The standard signed integer types and standard unsigned integer types -are collectively called the \defnadjx{standard integer}{types}{type}, and the extended -signed integer types and extended -unsigned integer types are collectively called the -\defnadjx{extended integer}{types}{type}. +\rSec2[basic.scope.lambda]{Lambda scope} + +A \grammarterm{lambda-expression} \tcode{E} introduces a \defnadj{lambda}{scope} +that starts immediately after the \grammarterm{lambda-introducer} of \tcode{E} +and extends to the end of the \grammarterm{compound-statement} of \tcode{E}. + +\rSec2[basic.scope.namespace]{Namespace scope} \pnum -A fundamental type specified to have -a signed or unsigned integer type as its \defnadj{underlying}{type} has -the same object representation, -value representation, -alignment requirements\iref{basic.align}, and -range of representable values as the underlying type. -Further, each value has the same representation in both types. +Any \grammarterm{namespace-definition} for a namespace $N$ introduces +a \defnadj{namespace}{scope} +that includes the \grammarterm{namespace-body} +for every \grammarterm{namespace-definition} for $N$. +For each non-friend redeclaration or specialization +whose target scope is or is contained by the scope, +the portion after the +\grammarterm{declarator-id}, +\grammarterm{class-head-name}, or +\grammarterm{enum-head-name} +is also included in the scope. +The global scope is +the namespace scope of the global namespace\iref{basic.namespace}. +\begin{example} +\begin{codeblock} +namespace Q { + namespace V { void f(); } + void V::f() { // in the scope of \tcode{V} + void h(); // declares \tcode{Q::V::h} + } +} +\end{codeblock} +\end{example} + +\rSec2[basic.scope.class]{Class scope} \pnum -\indextext{type!\idxcode{char}}% -\indextext{type!character}% -\indextext{\idxcode{char}!implementation-defined sign of}% -\indextext{type!\idxcode{signed char}}% -\indextext{character!\idxcode{signed}}% -\indextext{type!\idxcode{unsigned char}}% -Type \keyword{char} is a distinct type -that has an \impldef{underlying type of \tcode{char}} choice of -``\tcode{\keyword{signed} \keyword{char}}'' or ``\tcode{\keyword{unsigned} \keyword{char}}'' as its underlying type. -The three types \keyword{char}, \tcode{\keyword{signed} \keyword{char}}, and \tcode{\keyword{unsigned} \keyword{char}} -are collectively called -\defnadjx{ordinary character}{types}{type}. -The ordinary character types and \keyword{char8_t} -are collectively called \defnadjx{narrow character}{types}{type}. -For narrow character types, -each possible bit pattern of the object representation represents -a distinct value. -\begin{note} -This requirement does not hold for other types. -\end{note} +Any declaration of a class or class template $C$ introduces +a \defnadj{class}{scope} +that includes the \grammarterm{member-specification} of +the \grammarterm{class-specifier} for $C$ (if any). +For each non-friend redeclaration or specialization +whose target scope is or is contained by the scope, +the portion after the +\grammarterm{declarator-id}, +\grammarterm{class-head-name}, or +\grammarterm{enum-head-name} is also included in the scope. \begin{note} -A bit-field of narrow character type whose width is larger than -the width of that type has padding bits; see \ref{basic.types.general}. +Lookup from a program point +before the \grammarterm{class-specifier} of a class +will find no bindings in the class scope. +\begin{example} +\begin{codeblock} +template +struct B { + D::type x; // \#1 +}; + +struct A { using type = int; }; +struct C : A, B {}; // error at \#1: \tcode{C::type} not found +\end{codeblock} +\end{example} \end{note} +\rSec2[basic.scope.enum]{Enumeration scope}% + \pnum -\indextext{\idxcode{wchar_t}|see{type, \tcode{wchar_t}}}% -\indextext{type!\idxcode{wchar_t}}% -\indextext{type!underlying!\idxcode{wchar_t}}% -Type \keyword{wchar_t} is a distinct type that has -an \impldef{underlying type of \tcode{wchar_t}} -signed or unsigned integer type as its underlying type. +Any declaration of an enumeration $E$ introduces +an \defnadj{enumeration}{scope} +that includes the \grammarterm{enumerator-list} of +the \grammarterm{enum-specifier} for $E$ (if any). + +\rSec2[basic.scope.temp]{Template parameter scope}% \pnum -\indextext{\idxcode{char8_t}|see{type, \tcode{char8_t}}}% -\indextext{type!\idxcode{char8_t}}% -\indextext{type!underlying!\idxcode{char8_t}}% -Type \keyword{char8_t} denotes a distinct type -whose underlying type is \tcode{\keyword{unsigned} \keyword{char}}. -\indextext{\idxcode{char16_t}|see{type, \tcode{char16_t}}}% -\indextext{\idxcode{char32_t}|see{type, \tcode{char32_t}}}% -\indextext{type!\idxcode{char16_t}}% -\indextext{type!\idxcode{char32_t}}% -\indextext{type!underlying!\idxcode{char16_t}}% -\indextext{type!underlying!\idxcode{char32_t}}% -Types \keyword{char16_t} and \keyword{char32_t} denote distinct types -whose underlying types are \tcode{uint_least16_t} and \tcode{uint_least32_t}, -respectively, in \libheaderref{cstdint}. +Each template \grammarterm{template-parameter} introduces +a \defnadj{template parameter}{scope} +that includes the \grammarterm{template-head} of +the \grammarterm{template-parameter}. \pnum -\indextext{Boolean type}% -\indextext{type!Boolean}% -Type \tcode{bool} is a distinct type that has -the same object representation, -value representation, and -alignment requirements as -an \impldef{underlying type of \tcode{bool}} unsigned integer type. -The values of type \keyword{bool} are -\keyword{true} and \keyword{false}. +Each \grammarterm{template-declaration} $D$ introduces +a template parameter scope +that extends from the beginning of its \grammarterm{template-parameter-list} +to the end of the \grammarterm{template-declaration}. +Any declaration outside the \grammarterm{template-parameter-list} +that would inhabit that scope instead inhabits the same scope as $D$. +The parent scope of any scope $S$ that is not a template parameter scope +is the smallest scope that contains $S$ and is not a template parameter scope. \begin{note} -There are no \keyword{signed}, \keyword{unsigned}, -\keyword{short}, or \tcode{\keyword{long} \keyword{bool}} types or values. +Therefore, only template parameters belong to a template parameter scope, and +only template parameter scopes have +a template parameter scope as a parent scope. \end{note} +\indextext{scope|)} + +\rSec1[basic.lookup]{Name lookup}% + +\indextext{lookup!name|(} + +\rSec2[basic.lookup.general]{General}% +\indextext{scope!name lookup and|see{lookup, name}}% + \pnum -\indextext{type!integral}% -The types \keyword{char}, \keyword{wchar_t}, -\keyword{char8_t}, \keyword{char16_t}, and \keyword{char32_t} -are collectively called \defnadjx{character}{types}{type}. -The character types, \keyword{bool}, -the signed and unsigned integer types, -and cv-qualified versions\iref{basic.type.qualifier} thereof, -are collectively termed -\defnx{integral types}{integral type}. -A synonym for integral type is \defn{integer type}. -\begin{note} -Enumerations\iref{dcl.enum} are not integral; -however, unscoped enumerations can be promoted to integral types -as specified in \ref{conv.prom}. -\end{note} +The name lookup rules apply uniformly to all names (including +\grammarterm{typedef-name}{s}\iref{dcl.typedef}, +\grammarterm{namespace-name}{s}\iref{basic.namespace}, and +\grammarterm{class-name}{s}\iref{class.name}) wherever the grammar allows +such names in the context discussed by a particular rule. Name lookup +associates the use of a name with a set of declarations\iref{basic.def} of +that name. +Unless otherwise specified, +the program is ill-formed if no declarations are found. +If the declarations found by name lookup +all denote functions or function templates, +the declarations are said to form an \defn{overload set}. +Otherwise, +if the declarations found by name lookup do not all denote the same entity, +\indextext{lookup!ambiguous}% +they are \defn{ambiguous} and the program is ill-formed. +Overload resolution\iref{over.match,over.over} +takes place after name lookup has succeeded. The access rules\iref{class.access} +are considered only once name lookup and +function overload resolution (if applicable) have succeeded. Only after +name lookup, function overload resolution (if applicable) and access +checking have succeeded +are the semantic properties introduced by the declarations +used in further processing. \pnum -\indextext{floating-point type|see{type, floating-point}}% -The three distinct types -\indextext{type!\idxcode{float}}% -\keyword{float}, -\indextext{type!\idxcode{double}}% -\keyword{double}, -and -\indextext{type!\idxcode{long double}}% -\tcode{\keyword{long} \keyword{double}} -can represent floating-point numbers. -The type \keyword{double} provides at least as much -precision as \keyword{float}, and the type \tcode{\keyword{long} \keyword{double}} provides at -least as much precision as \keyword{double}. The set of values of the type -\keyword{float} is a subset of the set of values of the type -\keyword{double}; the set of values of the type \keyword{double} is a subset -of the set of values of the type \tcode{\keyword{long} \keyword{double}}. -The types -\keyword{float}, \keyword{double}, and \tcode{\keyword{long} \keyword{double}}, -and cv-qualified versions\iref{basic.type.qualifier} thereof, -are collectively termed -\defnx{standard floating-point types}{type!floating-point!standard}. -An implementation may also provide additional types -that represent floating-point values and define them (and cv-qualified versions thereof) to be -\defnx{extended floating-point types}{type!floating-point!extended}. -The standard and extended floating-point types -are collectively termed \defnx{floating-point types}{type!floating-point}. +A program point $P$ is said to follow +any declaration in the same translation unit +whose locus\iref{basic.scope.pdecl} is before $P$. \begin{note} -Any additional implementation-specific types representing floating-point values -that are not defined by the implementation to be extended floating-point types -are not considered to be floating-point types, and -this document imposes no requirements on them or -their interactions with floating-point types. +The declaration might appear in a scope that does not contain $P$. \end{note} -Except as specified in \ref{basic.extended.fp}, -the object and value representations and accuracy of operations -of floating-point types are \impldef{representation of floating-point types}. - -\pnum -The minimum range of representable values for a floating-point type is -the most negative finite floating-point number representable -in that type through -the most positive finite floating-point number representable in that type. -In addition, if negative infinity is representable in a type, -the range of that type is extended to all negative real numbers; -likewise, if positive infinity is representable in a type, -the range of that type is extended to all positive real numbers. +\indextext{precede|see{declaration, precede}}% +A declaration $X$ \defnx{precedes}{declaration!precede} +a program point $P$ in a translation unit $L$ +if $P$ follows $X$, $X$ inhabits a class scope and is reachable from $P$, or +else $X$ appears in a translation unit $D$ and +\begin{itemize} +\item +$P$ follows +a \grammarterm{module-import-declaration} or \grammarterm{module-declaration} +that imports $D$ (directly or indirectly), and +\item +$X$ appears after the \grammarterm{module-declaration} in $D$ (if any) and +before the \grammarterm{private-module-fragment} in $D$ (if any), and +\item +either $X$ is exported or else $D$ and $L$ are part of the same module and +$X$ does not inhabit a namespace with internal linkage or +declare a name with internal linkage. \begin{note} -Since negative and positive infinity are representable -in \IsoFloatUndated{} formats, -all real numbers lie within the range of representable values of -a floating-point type adhering to \IsoFloatUndated{}. +Names declared by a \grammarterm{using-declaration} have no linkage. \end{note} - -\pnum -Integral and floating-point types are collectively -termed \defnx{arithmetic types}{type!arithmetic}. +\end{itemize} \begin{note} -Properties of the arithmetic types, -such as their minimum and maximum representable value, -can be queried using the facilities in the standard library headers -\libheaderref{limits}, -\libheaderref{climits}, and -\libheaderref{cfloat}. +A \grammarterm{module-import-declaration} imports both +the named translation unit(s) and +any modules named by exported +\grammarterm{module-import-declaration}{s} within them, +recursively. +\begin{example} +\begin{codeblocktu}{Translation unit \#1} +export module Q; +export int sq(int i) { return i*i; } +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#2} +export module R; +export import Q; +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#3} +import R; +int main() { return sq(9); } // OK, \tcode{sq} from module \tcode{Q} +\end{codeblocktu} +\end{example} \end{note} \pnum -\indextext{type!\idxcode{void}}% -A type \cv{}~\keyword{void} -is an incomplete type that cannot be completed; such a type has -an empty set of values. It is used as the return -type for functions that do not return a value. -An expression of type \cv{}~\keyword{void} shall -be used only as -\begin{itemize} -\item an expression statement\iref{stmt.expr}, -\item the expression in a \keyword{return} statement\iref{stmt.return} -for a function with the return type \cv{}~\keyword{void}, -\item an operand of a comma expression\iref{expr.comma}, -\item the second or third operand of \tcode{?:}\iref{expr.cond}, -\item the operand of a \keyword{typeid} expression\iref{expr.typeid}, -\item the operand of a \keyword{noexcept} operator\iref{expr.unary.noexcept}, -\item the operand of a \keyword{decltype} specifier\iref{dcl.type.decltype}, or -\item the operand of an explicit conversion to type -\cv{}~\keyword{void}\iref{expr.type.conv,expr.static.cast,expr.cast}. -\end{itemize} - -\pnum -The types denoted by \cv~\tcode{std::nullptr_t} are distinct types. -A value of type \tcode{std::nullptr_t} is a null pointer -constant\iref{conv.ptr}. Such values participate in the pointer and the -pointer-to-member conversions\iref{conv.ptr,conv.mem}. -\tcode{\keyword{sizeof}(std::nullptr_t)} shall be equal to \tcode{\keyword{sizeof}(\keyword{void}*)}. +\indextext{scope!search!single}% +A \defnadj{single}{search} in a scope $S$ +for a name $N$ from a program point $P$ +finds all declarations that precede $P$ +to which any name that is the same as $N$\iref{basic.link} is bound in $S$. +If any such declaration is a \grammarterm{using-declarator} +whose terminal name\iref{expr.prim.id.unqual} +is not dependent\iref{temp.dep.type}, +it is replaced by the declarations named by +the \grammarterm{using-declarator}\iref{namespace.udecl}. \pnum -\indextext{type!fundamental}% -The types described in this subclause -are called \defnx{fundamental types}{fundamental type}. +In certain contexts, only certain kinds of declarations are included. +After any such restriction, any declarations of classes or enumerations are discarded if any other declarations are found. \begin{note} -Even if the implementation defines two or more fundamental types to have the -same value representation, they are nevertheless different types. +A type (but not a \grammarterm{typedef-name} or template) +is therefore hidden by any other entity in its scope. \end{note} +\indextext{type-only!lookup|see{lookup, type-only}}% +However, if a lookup is \defnx{type-only}{lookup!type-only}, +only declarations of +types and templates whose specializations are types are considered; +furthermore, if declarations +of a \grammarterm{typedef-name} and of the type to which it refers are found, +the declaration of the \grammarterm{typedef-name} is discarded +instead of the type declaration. -\rSec2[basic.extended.fp]{Optional extended floating-point types} - -\pnum -If the implementation supports an extended floating-point type\iref{basic.fundamental} -whose properties are specified by -the \IsoFloatUndated{} floating-point interchange format binary16, -then the \grammarterm{typedef-name} \tcode{std::float16_t} -is defined in the header \libheaderref{stdfloat} and names such a type, -the macro \mname{STDCPP_FLOAT16_T} is defined\iref{cpp.predefined}, and -the floating-point literal suffixes \tcode{f16} and \tcode{F16} -are supported\iref{lex.fcon}. - -\pnum -If the implementation supports an extended floating-point type -whose properties are specified by -the \IsoFloatUndated{} floating-point interchange format binary32, -then the \grammarterm{typedef-name} \tcode{std::float32_t} -is defined in the header \libheader{stdfloat} and names such a type, -the macro \mname{STDCPP_FLOAT32_T} is defined, and -the floating-point literal suffixes \tcode{f32} and \tcode{F32} are supported. +\rSec2[class.member.lookup]{Member name lookup}% +\indextext{lookup!member name}% +\indextext{ambiguity!base class member}% +\indextext{ambiguity!member access} \pnum -If the implementation supports an extended floating-point type -whose properties are specified by -the \IsoFloatUndated{} floating-point interchange format binary64, -then the \grammarterm{typedef-name} \tcode{std::float64_t} -is defined in the header \libheader{stdfloat} and names such a type, -the macro \mname{STDCPP_FLOAT64_T} is defined, and -the floating-point literal suffixes \tcode{f64} and \tcode{F64} are supported. +\indextext{scope!search}% +A \defn{search} in a scope $X$ for a name $M$ from a program point $P$ +is a single search in $X$ for $M$ from $P$ +unless $X$ is the scope of a class or class template $T$, in which case the +following steps define the result of the search. +\begin{note} +The result differs only +if $M$ is a \grammarterm{conversion-function-id} or +if the single search would find nothing. +\end{note} \pnum -If the implementation supports an extended floating-point type -whose properties are specified by -the \IsoFloatUndated{} floating-point interchange format binary128, -then the \grammarterm{typedef-name} \tcode{std::float128_t} -is defined in the header \libheader{stdfloat} and names such a type, -the macro \mname{STDCPP_FLOAT128_T} is defined, and -the floating-point literal suffixes \tcode{f128} and \tcode{F128} are supported. +The \defn{lookup set} for a name $N$ in a class or class template $C$, called $S(N,C)$, +consists of two component sets: +the \term{declaration set}, a set of members named $N$; and +the \term{subobject set}, +a set of subobjects where declarations of these members were found +(possibly via \grammarterm{using-declaration}{s}). +In the declaration set, type declarations (including injected-class-names) +are replaced by the types they designate. $S(N,C)$ is calculated as follows: \pnum -If the implementation supports an extended floating-point type -with the properties, as specified by \IsoFloatUndated{}, of -radix ($b$) of 2, -storage width in bits ($k$) of 16, -precision in bits ($p$) of 8, -maximum exponent ($emax$) of 127, and -exponent field width in bits ($w$) of 8, then -the \grammarterm{typedef-name} \tcode{std::bfloat16_t} -is defined in the header \libheader{stdfloat} and names such a type, -the macro \mname{STDCPP_BFLOAT16_T} is defined, and -the floating-point literal suffixes \tcode{bf16} and \tcode{BF16} are supported. +The declaration set is the result of +a single search in the scope of $C$ for $N$ +from immediately after the \grammarterm{class-specifier} of $C$ +if $P$ is in a complete-class context of $C$ or +from $P$ otherwise. +If the resulting declaration set is not empty, the subobject set +contains $C$ itself, and calculation is complete. \pnum +Otherwise (i.e., $C$ does not contain a declaration of $N$ +or the resulting declaration set is empty), $S(N,C)$ is initially empty. +Calculate the lookup set for $N$ +in each direct non-dependent\iref{temp.dep.type} base class subobject $B_i$, and +merge each such lookup set $S(N,B_i)$ in turn into $S(N,C)$. \begin{note} -A summary of the parameters for each type is given in \tref{basic.extended.fp}. -The precision $p$ includes the implicit 1 bit at the beginning of the significand, -so the storage used for the significand is $p-1$ bits. -\IsoFloatUndated{} does not assign a name for a type -having the parameters specified for \tcode{std::bfloat16_t}. +If $C$ is incomplete, +only base classes whose \grammarterm{base-specifier} appears before $P$ +are considered. +If $C$ is an instantiated class, its base classes are not dependent. \end{note} -\begin{floattable} -{Properties of named extended floating-point types}{basic.extended.fp}{llllll} -\topline -\lhdr{Parameter} & \chdr{\tcode{float16_t}} & \chdr{\tcode{float32_t}} & -\chdr{\tcode{float64_t}} & \chdr{\tcode{float128_t}} & -\rhdr{\tcode{bfloat16_t}} \\ -\capsep -\IsoFloatUndated{} name & binary16 & binary32 & binary64 & binary128 & \\ -$k$, storage width in bits & 16 & 32 & 64 & 128 & 16 \\ -$p$, precision in bits & 11 & 24 & 53 & 113 & 8 \\ -$emax$, maximum exponent & 15 & 127 & 1023 & 16383 & 127 \\ -$w$, exponent field width in bits & 5 & 8 & 11 & 15 & 8 \\ -\end{floattable} \pnum -\recommended -Any names that the implementation provides for -the extended floating-point types described in this subsection -that are in addition to the names defined in the \libheader{stdfloat} header -should be chosen to increase compatibility and interoperability -with the interchange types -\tcode{_Float16}, \tcode{_Float32}, \tcode{_Float64}, and \tcode{_Float128} -defined in ISO/IEC TS 18661-3 and with future versions of \IsoCUndated{}. - -\rSec2[basic.compound]{Compound types} +The following steps define the result of merging lookup set $S(N,B_i)$ +into the intermediate $S(N,C)$: -\pnum -\indextext{type!compound}% -Compound types can be constructed in the following ways: \begin{itemize} -\item \defnx{arrays}{type!array} of objects of a given type, \ref{dcl.array}; - -\item \defnx{functions}{type!function}, which have parameters of given types and return -\keyword{void} or references or objects of a given type, \ref{dcl.fct}; +\item If each of the subobject members of $S(N,B_i)$ is a base class +subobject of at least one of the subobject members of $S(N,C)$, or if +$S(N,B_i)$ is empty, $S(N,C)$ is unchanged and the merge is complete. +Conversely, if each of the subobject members of $S(N,C)$ is a base class +subobject of at least one of the subobject members of $S(N,B_i)$, or if +$S(N,C)$ is empty, the new $S(N,C)$ is a copy of $S(N,B_i)$. -\item \defnx{pointers}{type!pointer} to \cv{}~\keyword{void} or objects or functions (including -static members of classes) of a given type, \ref{dcl.ptr}; +\item Otherwise, if the declaration sets of $S(N,B_i)$ and $S(N,C)$ +differ, the merge is ambiguous: the new $S(N,C)$ is a lookup set with an +invalid declaration set and the union of the subobject sets. In +subsequent merges, an invalid declaration set is considered different +from any other. -\item -\indextext{reference!lvalue}% -\indextext{reference!rvalue}% -\defnx{references}{reference} to objects or functions of a given -type, \ref{dcl.ref}. There are two types of references: -\begin{itemize} -\item lvalue reference -\item rvalue reference +\item Otherwise, the new $S(N,C)$ is a lookup set with the shared set of +declarations and the union of the subobject sets. \end{itemize} -\item -\defnx{classes}{class} containing a sequence of objects of various types\iref{class}, -a set of types, enumerations and functions for -manipulating these objects\iref{class.mfct}, and a set of restrictions -on the access to these entities\iref{class.access}; - -\item -\defnx{unions}{\idxcode{union}}, which are classes capable of containing objects of -different types at different times, \ref{class.union}; - -\item -\defnx{enumerations}{\idxcode{enum}}, -which comprise a set of named constant values, \ref{dcl.enum}; +\pnum +The result of the search is the declaration set of $S(M,T)$. +If it is an invalid set, the program is ill-formed. +If it differs from the result of a search in $T$ for $M$ +in a complete-class context\iref{class.mem} of $T$, +the program is ill-formed, no diagnostic required. +\begin{example} +\begin{codeblock} +struct A { int x; }; // S(x,A) = \{ \{ \tcode{A::x} \}, \{ \tcode{A} \} \} +struct B { float x; }; // S(x,B) = \{ \{ \tcode{B::x} \}, \{ \tcode{B} \} \} +struct C: public A, public B { }; // S(x,C) = \{ invalid, \{ \tcode{A} in \tcode{C}, \tcode{B} in \tcode{C} \} \} +struct D: public virtual C { }; // S(x,D) = S(x,C) +struct E: public virtual C { char x; }; // S(x,E) = \{ \{ \tcode{E::x} \}, \{ \tcode{E} \} \} +struct F: public D, public E { }; // S(x,F) = S(x,E) +int main() { + F f; + f.x = 0; // OK, lookup finds \tcode{E::x} +} +\end{codeblock} -\item -\indextext{member pointer to|see{pointer to member}}% -\defnx{pointers to non-static class members}{pointer to member},% -\begin{footnote} -Static class members are objects or functions, and pointers to them are -ordinary pointers to objects or functions. -\end{footnote} -which identify members of a given -type within objects of a given class, \ref{dcl.mptr}. -Pointers to data members and pointers to member functions are collectively -called \term{pointer-to-member} types. -\end{itemize} +$S(\tcode{x},\tcode{F})$ is unambiguous because the \tcode{A} and \tcode{B} base +class subobjects of \tcode{D} are also base class subobjects of \tcode{E}, so +$S(\tcode{x},\tcode{D})$ is discarded in the first merge step. +\end{example} \pnum -These methods of constructing types can be applied recursively; -restrictions are mentioned in~\ref{dcl.meaning}. -Constructing a type such that the number of -bytes in its object representation exceeds the maximum value representable in -the type \tcode{std::size_t}\iref{support.types} is ill-formed. +If $M$ is a non-dependent \grammarterm{conversion-function-id}, +conversion function templates that are members of $T$ are considered. +For each such template $F$, the lookup set $S(t,T)$ is constructed, +considering a function template declaration to have the name $t$ +only if it corresponds to a declaration of $F$\iref{basic.scope.scope}. +The members of the declaration set of each such lookup set, +which shall not be an invalid set, are included in the result. +\begin{note} +Overload resolution will discard those +that cannot convert to the type specified by $M$\iref{temp.over}. +\end{note} \pnum -\indextext{terminology!pointer}% -The type of a pointer to \cv{}~\keyword{void} or a pointer to an object type is -called an \defn{object pointer type}. \begin{note} -A pointer to \keyword{void} -does not have a pointer-to-object type, however, because \keyword{void} is not -an object type. +A static member, a nested type or an enumerator defined in a base class +\tcode{T} can unambiguously be found even if an object has more than one +base class subobject of type \tcode{T}. Two base class subobjects share +the non-static member subobjects of their common virtual base classes. \end{note} -The type of a pointer that can designate a function -is called a \defn{function pointer type}. -A pointer to an object of type \tcode{T} is referred to as a ``pointer to -\tcode{T}''. \begin{example} -A pointer to an object of type \keyword{int} is -referred to as ``pointer to \keyword{int}'' and a pointer to an object of -class \tcode{X} is called a ``pointer to \tcode{X}''. +\begin{codeblock} +struct V { + int v; +}; +struct A { + int a; + static int s; + enum { e }; +}; +struct B : A, virtual V { }; +struct C : A, virtual V { }; +struct D : B, C { }; + +void f(D* pd) { + pd->v++; // OK, only one \tcode{v} (virtual) + pd->s++; // OK, only one \tcode{s} (static) + int i = pd->e; // OK, only one \tcode{e} (enumerator) + pd->a++; // error: ambiguous: two \tcode{a}{s} in \tcode{D} +} +\end{codeblock} \end{example} -Except for pointers to static members, text referring to ``pointers'' -does not apply to pointers to members. Pointers to incomplete types are -allowed although there are restrictions on what can be done with -them\iref{basic.types.general}. -\indextext{address}% -Every value of pointer type is one of the following: -\begin{itemize} -\item -a \defn{pointer to} an object or function (the pointer is said to \defn{point} to the object or function), or -\item -a \defn{pointer past the end of} an object\iref{expr.add}, or -\item -\indextext{null pointer value|see{value, null pointer}} -the \defnx{null pointer value}{value!null pointer} for that type, or -\item -\indextext{invalid pointer value|see{value, invalid pointer}} -an \defnx{invalid pointer value}{value!invalid pointer}. -\end{itemize} -A value of a -pointer type -that is a pointer to or past the end of an object -\defn{represents the address} of -the first byte in memory\iref{intro.memory} occupied by the object -\begin{footnote} -For an object that is not within its lifetime, -this is the first byte in memory that it will occupy or used to occupy. -\end{footnote} -or the first byte in memory -after the end of the storage occupied by the object, -respectively. -\begin{note} -A pointer past the end of an object\iref{expr.add} -is not considered to point to an unrelated object -of the object's type, -even if the unrelated object is located at that address. -\end{note} -For purposes of pointer arithmetic\iref{expr.add} -and comparison\iref{expr.rel,expr.eq}, -a pointer past the end of the last element of -an array \tcode{x} of $n$ elements -is considered to be equivalent to -a pointer to a hypothetical array element $n$ of \tcode{x} and -an object of type \tcode{T} that is not an array element -is considered to belong to an array with one element of type \tcode{T}. -The value representation of -pointer types is \impldef{value representation of pointer types}. Pointers to -layout-compatible types shall -have the same value representation and alignment -requirements\iref{basic.align}. -\begin{note} -Pointers to over-aligned types\iref{basic.align} have no special -representation, but their range of valid values is restricted by the extended -alignment requirement. -\end{note} \pnum -A pointer value $P$ is -\indextext{value!valid in the context of an evaluation}% -\defn{valid in the context of} an evaluation $E$ -if $P$ is a null pointer value, or -if it is a pointer to or past the end of an object $O$ and -$E$ happens before the end of the duration of the region of storage for $O$. -If a pointer value $P$ is used in an evaluation $E$ and -$P$ is not valid in the context of $E$, -then the behavior is undefined if $E$ is -an indirection\iref{expr.unary.op} or -an invocation of a deallocation function\iref{basic.stc.dynamic.deallocation}, -and \impldef{invalid pointer value in the context of an evaluation} otherwise. -\begin{footnote} -Some implementations might define that -copying such a pointer value causes a system-generated runtime fault. -\end{footnote} \begin{note} -$P$ can be valid in the context of $E$ even -if it points to a type unrelated to that of $O$ or -if $O$ is not within its lifetime, -although further restrictions apply -to such pointer values\iref{basic.life, basic.lval, expr.add}. +\indextext{dominance!virtual base class}% +When virtual base classes are used, a hidden declaration can be reached +along a path through the subobject lattice that does not pass through +the hiding declaration. This is not an ambiguity. The identical use with +non-virtual base classes is an ambiguity; in that case there is no +unique instance of the name that hides all the others. \end{note} +\begin{example} +\begin{codeblock} +struct V { int f(); int x; }; +struct W { int g(); int y; }; +struct B : virtual V, W { + int f(); int x; + int g(); int y; +}; +struct C : virtual V, W { }; + +struct D : B, C { void glorp(); }; +\end{codeblock} + +\begin{importgraphic} +{Name lookup} +{class.lookup} +{figname.pdf} +\end{importgraphic} + +As illustrated in \fref{class.lookup}, +the names declared in \tcode{V} and the left-hand instance of \tcode{W} +are hidden by those in \tcode{B}, but the names declared in the +right-hand instance of \tcode{W} are not hidden at all. +\begin{codeblock} +void D::glorp() { + x++; // OK, \tcode{B::x} hides \tcode{V::x} + f(); // OK, \tcode{B::f()} hides \tcode{V::f()} + y++; // error: \tcode{B::y} and \tcode{C}'s \tcode{W::y} + g(); // error: \tcode{B::g()} and \tcode{C}'s \tcode{W::g()} +} +\end{codeblock} +\end{example} +\indextext{ambiguity!class conversion}% + +\pnum +An explicit or implicit conversion from a pointer to or +an expression designating an object +of a +derived class to a pointer or reference to one of its base classes shall +unambiguously refer to a unique object representing the base class. +\begin{example} +\begin{codeblock} +struct V { }; +struct A { }; +struct B : A, virtual V { }; +struct C : A, virtual V { }; +struct D : B, C { }; + +void g() { + D d; + B* pb = &d; + A* pa = &d; // error: ambiguous: \tcode{C}'s \tcode{A} or \tcode{B}'s \tcode{A}? + V* pv = &d; // OK, only one \tcode{V} subobject +} +\end{codeblock} +\end{example} \pnum -Two objects \placeholder{a} and \placeholder{b} are \defn{pointer-interconvertible} if -\begin{itemize} -\item -they are the same object, or -\item -one is a union object and -the other is a non-static data member of that object\iref{class.union}, or -\item -one is a standard-layout class object and -the other is the first non-static data member of that object or -any base class subobject of that object\iref{class.mem}, or -\item -there exists an object \placeholder{c} such that -\placeholder{a} and \placeholder{c} are pointer-interconvertible, and -\placeholder{c} and \placeholder{b} are pointer-interconvertible. -\end{itemize} -If two objects are pointer-interconvertible, -then they have the same address, -and it is possible to obtain a pointer to one -from a pointer to the other -via a \keyword{reinterpret_cast}\iref{expr.reinterpret.cast}. \begin{note} -An array object and its first element are not pointer-interconvertible, -even though they have the same address. +Even if the result of name lookup is unambiguous, use of a name found in +multiple subobjects might still be +ambiguous\iref{conv.mem,expr.ref,class.access.base}. \end{note} +\begin{example} +\begin{codeblock} +struct B1 { + void f(); + static void f(int); + int i; +}; +struct B2 { + void f(double); +}; +struct I1: B1 { }; +struct I2: B1 { }; -\pnum -A byte of storage \placeholder{b} -is \defnx{reachable through}{storage!reachable through a pointer value} -a pointer value that points to an object \placeholder{x} -if there is an object \placeholder{y}, -pointer-interconvertible with \placeholder{x}, -such that \placeholder{b} is within the storage occupied by -\placeholder{y}, or the immediately-enclosing array object -if \placeholder{y} is an array element. +struct D: I1, I2, B2 { + using B1::f; + using B2::f; + void g() { + f(); // Ambiguous conversion of \keyword{this} + f(0); // Unambiguous (static) + f(0.0); // Unambiguous (only one \tcode{B2}) + int B1::* mpB1 = &D::i; // Unambiguous + int D::* mpD = &D::i; // Ambiguous conversion + } +}; +\end{codeblock} +\end{example} -\pnum -\indextext{pointer|seealso{\tcode{void*}}}% -\indextext{\idxcode{void*}!type}% -A pointer to \cv{}~\keyword{void} -can be used to point to objects of -unknown type. Such a pointer shall be able to hold any object pointer. -An object of type ``pointer to \cv{}~\keyword{void}'' -shall have the same representation and alignment -requirements as an object of type ``pointer to \cv{}~\keyword{char}''. +\rSec2[basic.lookup.unqual]{Unqualified name lookup} -\rSec2[basic.type.qualifier]{CV-qualifiers} +\indextext{name!unqualified}% + +\pnum +A \grammarterm{using-directive} is +\term{active} in a scope $S$ at a program point $P$ +if it precedes $P$ and inhabits either $S$ or +the scope of a namespace nominated by a \grammarterm{using-directive} +that is active in $S$ at $P$. \pnum -\indextext{cv-qualifier}% -\indextext{\idxcode{const}}% -\indextext{\idxcode{volatile}}% -Each type other than a function or reference type -is part of a group of four distinct, but related, types: -a \defn{cv-unqualified} version, -a \defn{const-qualified} version, -a \defn{volatile-qualified} version, and -a \defn{const-volatile-qualified} version. -The types in each such group shall have -the same representation and alignment requirements\iref{basic.align}. -\begin{footnote} -The same representation and alignment requirements -are meant to imply interchangeability as -arguments to functions, -return values from functions, and -non-static data members of unions. -\end{footnote} -A function or reference type is always cv-unqualified. +An \term{unqualified search} in a scope $S$ from a program point $P$ +includes the results of searches from $P$ in \begin{itemize} -\item A \defnadj{const}{object} is an object of type \tcode{\keyword{const} T} or a - non-mutable subobject of a const object. - -\item A \defnadj{volatile}{object} is an object of type - \tcode{\keyword{volatile} T} or a subobject of a volatile object. - -\item A \defnadj{const volatile}{object} is an object of type - \tcode{\keyword{const} \keyword{volatile} T}, a non-mutable subobject of a const volatile object, - a const subobject of a volatile object, or a non-mutable volatile - subobject of a const object. +\item +$S$, and +\item +for any scope $U$ that contains $P$ and is or is contained by $S$, +each namespace contained by $S$ that is nominated by +a \grammarterm{using-directive} that is active in $U$ at $P$. \end{itemize} +If no declarations are found, +the results of the unqualified search are +the results of an unqualified search in the parent scope of $S$, if any, +from $P$. \begin{note} -The type of an object\iref{intro.object} includes -the \grammarterm{cv-qualifier}s specified in the -\grammarterm{decl-specifier-seq}\iref{dcl.spec}, -\grammarterm{declarator}\iref{dcl.decl}, -\grammarterm{type-id}\iref{dcl.name}, or -\grammarterm{new-type-id}\iref{expr.new} -when the object is created. +When a class scope is searched, +the scopes of its base classes are also searched\iref{class.member.lookup}. +If it inherits from a single base, +it is as if the scope of the base immediately contains +the scope of the derived class. +Template parameter scopes +that are associated with one scope in the chain of parents +are also considered\iref{temp.local}. \end{note} \pnum -Except for array types, a compound type\iref{basic.compound} is not cv-qualified by the -cv-qualifiers (if any) of the types from which it is compounded. +\defnx{Unqualified name lookup}{lookup!unqualified name} +from a program point performs an unqualified search in its immediate scope. \pnum -\indextext{array!\idxcode{const}}% -An array type whose elements are cv-qualified -is also considered to have the same cv-qualifications -as its elements. -\begin{note} -Cv-qualifiers applied to an array -type attach to the underlying element type, so the notation -``\cv{}~\tcode{T}'', where \tcode{T} is an array type, refers to -an array whose elements are so-qualified\iref{dcl.array}. -\end{note} +An \defnadj{unqualified}{name} is a name +that does not immediately follow a \grammarterm{nested-name-specifier} or +the \tcode{.} or \tcode{->} in a class member access expression\iref{expr.ref}, +possibly after a \keyword{template} keyword or \tcode{\~}. +Unless otherwise specified, +such a name undergoes unqualified name lookup from the point where it appears. + +\pnum +An unqualified name that is a component name\iref{expr.prim.id.unqual} of +a \grammarterm{type-specifier} or \grammarterm{ptr-operator} of +a \grammarterm{conversion-type-id} is looked up in the same fashion +as the \grammarterm{conversion-function-id} in which it appears. +If that lookup finds nothing, it undergoes unqualified name lookup; +in each case, only names +that denote types or templates whose specializations are types are considered. \begin{example} \begin{codeblock} -typedef char CA[5]; -typedef const char CC; -CC arr1[5] = { 0 }; -const CA arr2 = { 0 }; +struct T1 { struct U { int i; }; }; +struct T2 { }; +struct U1 {}; +struct U2 {}; + +struct B { + using T = T1; + using U = U1; + operator U1 T1::*(); + operator U1 T2::*(); + operator U2 T1::*(); + operator U2 T2::*(); +}; + +template +int g() { + using U = U2; + X().operator U T::*(); // \#1, searches for \tcode{T} in the scope of \tcode{X} first + X().operator U decltype(T())::*(); // \#2 + return 0; +} +int x = g(); // \#1 calls \tcode{B::operator U1 T1::*} + // \#2 calls \tcode{B::operator U1 T2::*} \end{codeblock} -The type of both \tcode{arr1} and \tcode{arr2} is ``array of 5 -\tcode{\keyword{const} \keyword{char}}'', and the array type is considered to be -const-qualified. \end{example} -\indextext{type|)} - -\pnum -\begin{note} -See~\ref{dcl.fct} and~\ref{over.match.funcs} regarding function -types that have \grammarterm{cv-qualifier}{s}. -\end{note} \pnum -There is a partial ordering on cv-qualifiers, so that a type can be -said to be \defn{more cv-qualified} than another. -\tref{basic.type.qualifier.rel} shows the relations that -constitute this ordering. +In a friend declaration \grammarterm{declarator} +whose \grammarterm{declarator-id} is a \grammarterm{qualified-id} +whose lookup context\iref{basic.lookup.qual} is a class or namespace $S$, +lookup for an unqualified name +that appears after the \grammarterm{declarator-id} +performs a search in the scope associated with $S$. +If that lookup finds nothing, it undergoes unqualified name lookup. +\begin{example} +\begin{codeblock} +using I = int; +using D = double; +namespace A { + inline namespace N {using C = char; } + using F = float; + void f(I); + void f(D); + void f(C); + void f(F); +} +struct X0 {using F = float; }; +struct W { + using D = void; + struct X : X0 { + void g(I); + void g(::D); + void g(F); + }; +}; +namespace B { + typedef short I, F; + class Y { + friend void A::f(I); // error: no \tcode{void A::f(short)} + friend void A::f(D); // OK + friend void A::f(C); // error: \tcode{A::N::C} not found + friend void A::f(F); // OK + friend void W::X::g(I); // error: no \tcode{void X::g(short)} + friend void W::X::g(D); // OK + friend void W::X::g(F); // OK + }; +} +\end{codeblock} +\end{example} -\begin{floattable}{Relations on \keyword{const} and \keyword{volatile}}{basic.type.qualifier.rel} -{ccc} -\topline -\cvqual{no cv-qualifier} &<& \keyword{const} \\ -\cvqual{no cv-qualifier} &<& \keyword{volatile} \\ -\cvqual{no cv-qualifier} &<& \tcode{\keyword{const} \keyword{volatile}} \\ -\keyword{const} &<& \tcode{\keyword{const} \keyword{volatile}} \\ -\keyword{volatile} &<& \tcode{\keyword{const} \keyword{volatile}} \\ -\end{floattable} +\rSec2[basic.lookup.argdep]{Argument-dependent name lookup}% +\indextext{lookup!argument-dependent} \pnum -In this document, the notation \cv{} (or -\cvqual{cv1}, \cvqual{cv2}, etc.), used in the description of types, -represents an arbitrary set of cv-qualifiers, i.e., one of -\{\keyword{const}\}, \{\keyword{volatile}\}, \{\keyword{const}, -\keyword{volatile}\}, or the empty set. -For a type \cv{}~\tcode{T}, the \defnx{top-level cv-qualifiers}{cv-qualifier!top-level} -of that type are those denoted by \cv. +When the \grammarterm{postfix-expression} in +a function call\iref{expr.call} is an \grammarterm{unqualified-id}, +and unqualified lookup\iref{basic.lookup.unqual} +for the name in the \grammarterm{unqualified-id} does not find any +\begin{itemize} +\item +declaration of a class member, or +\item +function declaration inhabiting a block scope, or +\item +declaration not of a function or function template +\end{itemize} +then lookup for the name also includes the result of +\defnadj{argument-dependent}{lookup} in a set of associated namespaces +that depends on the types of the arguments +(and for template template arguments, the namespace of the template argument), +as specified below. \begin{example} -The type corresponding to the \grammarterm{type-id} -\tcode{\keyword{const} \keyword{int}\&} -has no top-level cv-qualifiers. -The type corresponding to the \grammarterm{type-id} -\tcode{\keyword{volatile} \keyword{int} * \keyword{const}} -has the top-level cv-qualifier \keyword{const}. -For a class type \tcode{C}, -the type corresponding to the \grammarterm{type-id} -\tcode{\keyword{void} (C::* \keyword{volatile})(\keyword{int}) \keyword{const}} -has the top-level cv-qualifier \keyword{volatile}. +\begin{codeblock} +namespace N { + struct S { }; + void f(S); +} + +void g() { + N::S s; + f(s); // OK, calls \tcode{N::f} + (f)(s); // error: \tcode{N::f} not considered; parentheses prevent argument-dependent lookup +} +\end{codeblock} \end{example} -\rSec2[conv.rank]{Conversion ranks}% -\indextext{conversion!integer rank} +\pnum +\begin{note} +For purposes of determining +(during parsing) whether an expression is a +\grammarterm{postfix-expression} for a function call, the usual name lookup +rules apply. +In some cases +a name followed by \tcode{<} is treated as a \grammarterm{template-name} +even though name lookup did not find a \grammarterm{template-name} +(see \ref{temp.names}). +For example, +\begin{codeblock} +int h; +void g(); +namespace N { + struct A {}; + template int f(T); + template int g(T); + template int h(T); +} + +int x = f(N::A()); // OK, lookup of \tcode{f} finds nothing, \tcode{f} treated as template name +int y = g(N::A()); // OK, lookup of \tcode{g} finds a function, \tcode{g} treated as template name +int z = h(N::A()); // error: \tcode{h<} does not begin a \grammarterm{template-id} +\end{codeblock} + +The rules have no effect on the syntactic interpretation of an expression. +For example, +\begin{codeblock} +typedef int f; +namespace N { + struct A { + friend void f(A &); + operator int(); + void g(A a) { + int i = f(a); // \tcode{f} is the typedef, not the friend function: equivalent to \tcode{int(a)} + } + }; +} +\end{codeblock} +Because the expression is not a function call, +argument-dependent name lookup does not apply and +the friend function \tcode{f} is not found. +\end{note} \pnum -Every integer type has an \term{integer conversion rank} defined as follows: - +For each argument type \tcode{T} in the function call, +there is a set of zero or more \defnx{associated entities}{entity!associated} +to be considered. +The set of entities is determined entirely by +the types of the function arguments +(and any template template arguments). +Any \grammarterm{typedef-name}s and \grammarterm{using-declaration}{s} +used to specify the types +do not contribute to this set. +The set of entities +is determined in the following way: \begin{itemize} -\item No two signed integer types other than \keyword{char} and \tcode{\keyword{signed} -\keyword{char}} (if \keyword{char} is signed) have the same rank, even if they have -the same representation. - -\item The rank of a signed integer type is greater than the rank -of any signed integer type with a smaller width. - -\item The rank of \tcode{\keyword{long} \keyword{long} \keyword{int}} is greater -than the rank of \tcode{\keyword{long} \keyword{int}}, which is greater than -the rank of \keyword{int}, which is greater than the rank of -\tcode{\keyword{short} \keyword{int}}, which is greater than the rank of -\tcode{\keyword{signed} \keyword{char}}. - -\item The rank of any unsigned integer type equals the rank of the -corresponding signed integer type. +\item If \tcode{T} is a fundamental type, its associated set of +entities is empty. -\item The rank of any standard integer type is greater than the -rank of any extended integer type with the same width. +\item If \tcode{T} is a class type (including unions), +its associated entities are: +the class itself; +the class of which it is a member, if any; +and, if it is a complete type, its direct and indirect base classes. +Furthermore, if \tcode{T} is a class template specialization, +its associated entities also include: +the entities +associated with the types of the template arguments +provided for template type parameters; +the templates used as template template arguments; and +the classes of which any member templates used as template template +arguments are members. +\begin{note} +Non-type template arguments do not +contribute to the set of associated entities. +\end{note} -\item The rank of \keyword{char} equals the rank of \tcode{\keyword{signed} \keyword{char}} -and \tcode{\keyword{unsigned} \keyword{char}}. +\item If \tcode{T} is an enumeration type, +its associated entities are \tcode{T} +and, if it is a class member, the member's class. -\item The rank of \tcode{bool} is less than the rank of all -standard integer types. +\item If \tcode{T} is a pointer to \tcode{U} or an array of \tcode{U}, +its associated entities are those associated with \tcode{U}. -\item -\indextext{type!\idxcode{wchar_t}}% -\indextext{type!\idxcode{char16_t}}% -\indextext{type!\idxcode{char32_t}}% -The ranks of \keyword{char8_t}, \keyword{char16_t}, \keyword{char32_t}, and -\keyword{wchar_t} equal the ranks of their underlying -types\iref{basic.fundamental}. +\item If \tcode{T} is a function type, its associated +entities are those associated with the function parameter types and those +associated with the return type. -\item The rank of any extended signed integer type relative to another -extended signed integer type with the same width is \impldef{rank of extended signed -integer type}, but still subject to the other rules for determining the integer -conversion rank. +\item If \tcode{T} is a pointer to a member function of a class +\tcode{X}, its associated entities are those associated +with the function parameter types and return type, together with those +associated with \tcode{X}. -\item For all integer types \tcode{T1}, \tcode{T2}, and \tcode{T3}, if -\tcode{T1} has greater rank than \tcode{T2} and \tcode{T2} has greater -rank than \tcode{T3}, then \tcode{T1} has greater rank than -\tcode{T3}. +\item If \tcode{T} is a pointer to a data member of class \tcode{X}, its +associated entities are those associated with the member +type together with those associated with \tcode{X}. \end{itemize} - -\begin{note} -The integer conversion rank is used in the definition of the integral -promotions\iref{conv.prom} and the usual arithmetic -conversions\iref{expr.arith.conv}. -\end{note} +In addition, if the argument is an overload set or the address of such a set, +its associated entities +are the union of those associated with each of the +members of the set, i.e., the entities associated with its +parameter types and return type. +Additionally, if the aforementioned overload set is named with +a \grammarterm{template-id}, its associated entities also include +its template \grammarterm{template-argument}{s} and +those associated with its type \grammarterm{template-argument}s. \pnum -Every floating-point type has a \defnadj{floating-point}{conversion rank} -defined as follows: +The \term{associated namespaces} for a call are +the innermost enclosing non-inline namespaces for its associated entities +as well as every element of the inline namespace set\iref{namespace.def} +of those namespaces. +Argument-dependent lookup finds +all declarations of functions and function templates that \begin{itemize} \item -The rank of a floating point type \tcode{T} is greater than -the rank of any floating-point type -whose set of values is a proper subset of the set of values of \tcode{T}. -\item -The rank of \tcode{\keyword{long} \keyword{double}} is greater than -the rank of \keyword{double}, -which is greater than the rank of \keyword{float}. -\item -Two extended floating-point types with the same set of values have equal ranks. +are found by a search of any associated namespace, or \item -An extended floating-point type with the same set of values as -exactly one cv-unqualified standard floating-point type -has a rank equal to the rank of that standard floating-point type. +are declared as a friend\iref{class.friend} of any class +with a reachable definition in the set of associated entities, or \item -An extended floating-point type with the same set of values as -more than one cv-unqualified standard floating-point type -has a rank equal to the rank of \keyword{double}. -\begin{tailnote} -The treatment of \tcode{std::float64_t} differs from -that of the analoguous \tcode{_Float64} in C, -for example on platforms where all of -\tcode{\keyword{long} \keyword{double}}, -\keyword{double}, and -\tcode{std::float64_t} -have the same set of values (see \IsoCUndated{}:2024 H.4.2). -\end{tailnote} +are exported, +are attached to a named module \tcode{M}\iref{module.interface}, +do not appear in the translation unit containing the point of the lookup, and +have the same innermost enclosing non-inline namespace scope as +a declaration of an associated entity attached to \tcode{M}\iref{basic.link}. \end{itemize} -\begin{note} -The conversion ranks of floating-point types \tcode{T1} and \tcode{T2} -are unordered if the set of values of \tcode{T1} is -neither a subset nor a superset of the set of values of \tcode{T2}. -This can happen when one type has both a larger range and a lower precision -than the other. -\end{note} +If the lookup is for a dependent name\iref{temp.dep,temp.dep.candidate}, +the above lookup is also performed +from each point in the instantiation context\iref{module.context} of the lookup, +additionally ignoring any declaration that +appears in another translation unit, +is attached to the global module, and +is either discarded\iref{module.global.frag} or has internal linkage. \pnum -Floating-point types that have equal floating-point conversion ranks -are ordered by floating-point conversion subrank. -The subrank forms a total order among types with equal ranks. -The types -\tcode{std::float16_t}, -\tcode{std::float32_t}, -\tcode{std::float64_t}, and -\tcode{std::float128_t}\iref{stdfloat.syn} -have a greater conversion subrank than any standard floating-point type -with equal conversion rank. -Otherwise, the conversion subrank order is -\impldef{floating-point conversion subrank}. +\begin{example} +\begin{codeblocktu}{Translation unit \#1} +export module M; +namespace R { + export struct X {}; + export void f(X); +} +namespace S { + export void f(R::X, R::X); +} +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#2} +export module N; +import M; +export R::X make(); +namespace R { static int g(X); } +export template void apply(T t, U u) { + f(t, u); + g(t); +} +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#3} +module Q; +import N; +namespace S { + struct Z { template operator T(); }; +} +void test() { + auto x = make(); // OK, \tcode{decltype(x)} is \tcode{R::X} in module \tcode{M} + R::f(x); // error: \tcode{R} and \tcode{R::f} are not visible here + f(x); // OK, calls \tcode{R::f} from interface of \tcode{M} + f(x, S::Z()); // error: \tcode{S::f} in module \tcode{M} not considered + // even though \tcode{S} is an associated namespace + apply(x, S::Z()); // error: \tcode{S::f} is visible in instantiation context, but + // \tcode{R::g} has internal linkage and cannot be used outside TU \#2 +} +\end{codeblocktu} +\end{example} \pnum \begin{note} -The floating-point conversion rank and subrank are used in -the definition of the usual arithmetic conversions\iref{expr.arith.conv}. +The associated namespace can include namespaces +already considered by ordinary unqualified lookup. \end{note} +\begin{example} +\begin{codeblock} +namespace NS { + class T { }; + void f(T); + void g(T, int); +} +NS::T parm; +void g(NS::T, float); +int main() { + f(parm); // OK, calls \tcode{NS::f} + extern void g(NS::T, float); + g(parm, 1); // OK, calls \tcode{g(NS::T, float)} +} +\end{codeblock} +\end{example} + +\rSec2[basic.lookup.qual]{Qualified name lookup} -\rSec1[basic.exec]{Program execution} +\rSec3[basic.lookup.qual.general]{General} -\rSec2[intro.execution]{Sequential execution} -\indextext{program execution|(} +\pnum +\indextext{lookup!qualified name|(}% +\indextext{name!qualified}% +\indextext{qualification!explicit}% +Lookup of an \grammarterm{identifier} +followed by a \tcode{::} scope resolution operator +considers only +namespaces, types, and templates whose specializations are types. +If a name, \grammarterm{template-id}, or \grammarterm{computed-type-specifier} +is followed by a \tcode{::}, +it shall designate a namespace, class, enumeration, or dependent type, +and the \tcode{::} is never interpreted as +a complete \grammarterm{nested-name-specifier}. +\begin{example} +\begin{codeblock} +class A { +public: + static int n; +}; +int main() { + int A; + A::n = 42; // OK + A b; // error: \tcode{A} does not name a type +} +template struct B : A {}; +namespace N { + template void B(); + int f() { + return B<0>::n; // error: \tcode{N::B<0>} is not a type + } +} +\end{codeblock} +\end{example} -\pnum -An instance of each object with automatic storage -duration\iref{basic.stc.auto} is associated with each entry into its -block. Such an object exists and retains its last-stored value during -the execution of the block and while the block is suspended (by a call -of a function, suspension of a coroutine\iref{expr.await}, or receipt of a signal). +\indextext{operator!scope resolution}% +\indextext{scope resolution operator|see{operator, scope resolution}}% \pnum -A \defn{constituent expression} is defined as follows: +A member-qualified name is +the (unique) component name\iref{expr.prim.id.unqual}, if any, of \begin{itemize} \item -The constituent expression of an expression is that expression. -\item -The constituent expression of a conversion is -the corresponding implicit function call, if any, or -the converted expression otherwise. -\item -The constituent expressions of a \grammarterm{braced-init-list} or -of a (possibly parenthesized) \grammarterm{expression-list} -are the constituent expressions of the elements of the respective list. +an \grammarterm{unqualified-id} or \item -The constituent expressions of a \grammarterm{brace-or-equal-initializer} -of the form \tcode{=}~\grammarterm{initializer-clause} -are the constituent expressions of the \grammarterm{initializer-clause}. +a \grammarterm{nested-name-specifier} of the form +\grammarterm{type-name} \tcode{::} or \grammarterm{namespace-name} \tcode{::} +\end{itemize} +in the \grammarterm{id-expression} of a class member access expression\iref{expr.ref}. +A \defnadj{qualified}{name} is +\begin{itemize} +\item a member-qualified name or +\item the terminal name of +\begin{itemize} +\item a \grammarterm{qualified-id}, +\item a \grammarterm{using-declarator}, +\item a \grammarterm{typename-specifier}, +\item a \grammarterm{qualified-namespace-specifier}, or +\item a \grammarterm{nested-name-specifier}, +\grammarterm{elaborated-type-specifier}, or +\grammarterm{class-or-decltype} +that has a \grammarterm{nested-name-specifier}\iref{expr.prim.id.qual}. \end{itemize} +\end{itemize} +The \defn{lookup context} of a member-qualified name is +the type of its associated object expression +(considered dependent if the object expression is type-dependent). +The lookup context of any other qualified name is +the type, template, or namespace +nominated by the preceding \grammarterm{nested-name-specifier}. +\begin{note} +When parsing a class member access, +the name following the \tcode{->} or \tcode{.} is +a qualified name even though it is not yet known of which kind. +\end{note} \begin{example} +In \begin{codeblock} -struct A { int x; }; -struct B { int y; struct A a; }; -B b = { 5, { 1+1 } }; + N::C::m.Base::f() \end{codeblock} -The constituent expressions of the \grammarterm{initializer} -used for the initialization of \tcode{b} are \tcode{5} and \tcode{1+1}. +\tcode{Base} is a member-qualified name; +the other qualified names are \tcode{C}, \tcode{m}, and \tcode{f}. \end{example} \pnum -The \defnx{immediate subexpressions}{immediate subexpression} of an expression $E$ are -\begin{itemize} -\item -the constituent expressions of $E$'s operands\iref{expr.prop}, -\item -any function call that $E$ implicitly invokes, -\item -if $E$ is a \grammarterm{lambda-expression}\iref{expr.prim.lambda}, -the initialization of the entities captured by copy and -the constituent expressions of the \grammarterm{initializer} of the \grammarterm{init-capture}{s}, -\item -if $E$ is a function call\iref{expr.call} or implicitly invokes a function, -the constituent expressions of each default argument\iref{dcl.fct.default} -used in the call, or -\item -if $E$ creates an aggregate object\iref{dcl.init.aggr}, -the constituent expressions of each default member initializer\iref{class.mem} -used in the initialization. -\end{itemize} - -\pnum -A \defn{subexpression} of an expression $E$ is -an immediate subexpression of $E$ or -a subexpression of an immediate subexpression of $E$. +\defnx{Qualified name lookup}{lookup!qualified name} +in a class, namespace, or enumeration performs +a search of the scope associated with it\iref{class.member.lookup} +except as specified below. +Unless otherwise specified, +a qualified name undergoes qualified name lookup in its lookup context +from the point where it appears +unless the lookup context either +is dependent and is not the current instantiation\iref{temp.dep.type} or +is not a class or class template. +If nothing is found by qualified lookup for a member-qualified name +that is the terminal name\iref{expr.prim.id.unqual} of +a \grammarterm{nested-name-specifier} and +is not dependent, it undergoes unqualified lookup. \begin{note} -Expressions appearing in the \grammarterm{compound-statement} of a \grammarterm{lambda-expression} -are not subexpressions of the \grammarterm{lambda-expression}. +During lookup for a template specialization, no names are dependent. \end{note} -The \defnadjx{potentially-evaluated}{subexpressions}{subexpression} of -an expression, conversion, or \grammarterm{initializer} $E$ are -\begin{itemize} -\item -the constituent expressions of $E$ and -\item -the subexpressions thereof that -are not subexpressions of a nested unevaluated operand\iref{term.unevaluated.operand}. -\end{itemize} +\begin{example} +\begin{codeblock} +int f(); +struct A { + int B, C; + template using D = void; + using T = void; + void f(); +}; +using B = A; +template using C = A; +template using D = A; +template using X = A; + +template +void g(T *p) { // as instantiated for \tcode{g}: + p->X<0>::f(); // error: \tcode{A::X} not found in \tcode{((p->X) < 0) > ::f()} + p->template X<0>::f(); // OK, \tcode{::X} found in definition context + p->B::f(); // OK, non-type \tcode{A::B} ignored + p->template C<0>::f(); // error: \tcode{A::C} is not a template + p->template D<0>::f(); // error: \tcode{A::D<0>} is not a class type + p->T::f(); // error: \tcode{A::T} is not a class type +} +template void g(A*); +\end{codeblock} +\end{example} \pnum -A \defn{full-expression} is +If a qualified name $Q$ follows a \tcode{\~}: \begin{itemize} \item -an unevaluated operand\iref{expr.context}, +If $Q$ is a member-qualified name, +it undergoes unqualified lookup as well as qualified lookup. \item -a \grammarterm{constant-expression}\iref{expr.const}, +Otherwise, its \grammarterm{nested-name-specifier} $N$ shall nominate a type. +If $N$ has another \grammarterm{nested-name-specifier} $S$, +$Q$ is looked up as if its lookup context were that nominated by $S$. \item -an immediate invocation\iref{expr.const}, +Otherwise, if the terminal name of $N$ is a member-qualified name $M$, +$Q$ is looked up as if $\tcode{\~}Q$ appeared in place of $M$ (as above). \item -an \grammarterm{init-declarator}\iref{dcl.decl} -(including such introduced by a structured binding\iref{dcl.struct.bind}) or -a \grammarterm{mem-initializer}\iref{class.base.init}, -including the constituent expressions of the initializer, +Otherwise, $Q$ undergoes unqualified lookup. \item -an invocation of a destructor generated at the end of the lifetime -of an object other than a temporary object\iref{class.temporary} -whose lifetime has not been extended, or +Each lookup for $Q$ considers only +types (if $Q$ is not followed by a \tcode{<}) and +templates whose specializations are types. +If it finds nothing or is ambiguous, it is discarded. \item -an expression that is not a subexpression of another expression and -that is not otherwise part of a full-expression. +The \grammarterm{type-name} that is or contains $Q$ +shall refer to its (original) lookup context (ignoring cv-qualification) under +the interpretation established by at least one (successful) lookup performed. \end{itemize} -If a language construct is defined to produce an implicit call of a function, -a use of the language construct is considered to be an expression -for the purposes of this definition. -Conversions applied to the result of an expression in order to satisfy the requirements -of the language construct in which the expression appears -are also considered to be part of the full-expression. -For an initializer, performing the initialization of the entity -(including evaluating default member initializers of an aggregate) -is also considered part of the full-expression. \begin{example} \begin{codeblock} -struct S { - S(int i): I(i) { } // full-expression is initialization of \tcode{I} - int& v() { return I; } - ~S() noexcept(false) { } -private: - int I; +struct C { + typedef int I; }; - -S s1(1); // full-expression comprises call of \tcode{S::S(int)} +typedef int I1, I2; +extern int* p; +extern int* q; void f() { - S s2 = 2; // full-expression comprises call of \tcode{S::S(int)} - if (S(3).v()) // full-expression includes lvalue-to-rvalue and \tcode{int} to \tcode{bool} conversions, - // performed before temporary is deleted at end of full-expression - { } - bool b = noexcept(S(4)); // exception specification of destructor of \tcode{S} considered for \keyword{noexcept} - - // full-expression is destruction of \tcode{s2} at end of block + p->C::I::~I(); // \tcode{I} is looked up in the scope of \tcode{C} + q->I1::~I2(); // \tcode{I2} is found by unqualified lookup } -struct B { - B(S = S(0)); +struct A { + ~A(); }; -B b[2] = { B(), B() }; // full-expression is the entire initialization - // including the destruction of temporaries +typedef A AB; +int main() { + AB* p; + p->AB::~AB(); // explicitly calls the destructor for \tcode{A} +} \end{codeblock} \end{example} -\pnum -\begin{note} -The evaluation of a full-expression can include the -evaluation of subexpressions that are not lexically part of the -full-expression. For example, subexpressions involved in evaluating -default arguments\iref{dcl.fct.default} are considered to -be created in the expression that calls the function, not the expression -that defines the default argument. -\end{note} +\rSec3[class.qual]{Class members} -\pnum -\indextext{value computation|(}% -Reading an object designated by a \keyword{volatile} -glvalue\iref{basic.lval}, modifying an object, calling a library I/O -function, or calling a function that does any of those operations are -all -\defn{side effects}, which are changes in the state of the execution -environment. \defnx{Evaluation}{evaluation} 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 volatile 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 \keyword{volatile} access -may not have completed yet. - -\pnum -\defnx{Sequenced before}{sequenced before} is an asymmetric, transitive, pair-wise relation between -evaluations executed by a single thread\iref{intro.multithread}, which induces -a partial order among those evaluations. Given any two evaluations \placeholder{A} and -\placeholder{B}, if \placeholder{A} is sequenced before \placeholder{B} -(or, equivalently, \placeholder{B} is \defn{sequenced after} \placeholder{A}), -then the execution of -\placeholder{A} shall precede the execution of \placeholder{B}. If \placeholder{A} is not sequenced -before \placeholder{B} and \placeholder{B} is not sequenced before \placeholder{A}, then \placeholder{A} and -\placeholder{B} are \defn{unsequenced}. -\begin{note} -The execution of unsequenced -evaluations can overlap. -\end{note} -Evaluations \placeholder{A} and \placeholder{B} are -\defn{indeterminately sequenced} when either \placeholder{A} is sequenced before -\placeholder{B} or \placeholder{B} is sequenced before \placeholder{A}, but it is unspecified which. -\begin{note} -Indeterminately sequenced evaluations cannot overlap, but either -can be executed first. -\end{note} -An expression \placeholder{X} -is said to be sequenced before -an expression \placeholder{Y} if -every value computation and every side effect -associated with the expression \placeholder{X} -is sequenced before -every value computation and every side effect -associated with the expression \placeholder{Y}. +\indextext{lookup!class member}% \pnum -Every -\indextext{value computation}% -value computation and -\indextext{side effects}% -side effect associated with a full-expression is -sequenced before every value computation and side effect associated with the -next full-expression to be evaluated. +In a lookup for a qualified name $N$ whose lookup context is a class $C$ +in which function names are not ignored, \begin{footnote} -As specified -in~\ref{class.temporary}, after a full-expression is evaluated, a sequence of -zero or more invocations of destructor functions for temporary objects takes -place, usually in reverse order of the construction of each temporary object. +Lookups in which +function names are ignored include names appearing in a +\grammarterm{nested-name-specifier}, an +\grammarterm{elaborated-type-specifier}, or a \grammarterm{base-specifier}. \end{footnote} - -\pnum -\indextext{evaluation!unspecified order of}% -Except where noted, evaluations of operands of individual operators and -of subexpressions of individual expressions are unsequenced. -\begin{note} -In an expression that is evaluated more than once during the execution -of a program, unsequenced and indeterminately sequenced evaluations of -its subexpressions need not be performed consistently in different -evaluations. -\end{note} -The value computations of the operands of an -operator are sequenced before the value computation of the result of the -operator. If a -\indextext{side effects}% -side effect on a memory location\iref{intro.memory} is unsequenced -relative to either another side effect on the same memory location or -a value computation using the value of any object in the same memory location, -and they are not potentially concurrent\iref{intro.multithread}, -the behavior is undefined. -\begin{note} -The next subclause imposes similar, but more complex restrictions on -potentially concurrent computations. -\end{note} - +\begin{itemize} +\item +if the search finds the injected-class-name of \tcode{C}\iref{class.pre}, or +\item +if $N$ is dependent and +is the terminal name of a \grammarterm{using-declarator}\iref{namespace.udecl} +that names a constructor, +\end{itemize} +$N$ is instead considered to name the constructor of class \tcode{C}. +Such a constructor name shall be used only +in the \grammarterm{declarator-id} of a (friend) declaration of a constructor or +in a \grammarterm{using-declaration}. \begin{example} \begin{codeblock} -void g(int i) { - i = 7, i++, i++; // \tcode{i} becomes \tcode{9} +struct A { A(); }; +struct B: public A { B(); }; - i = i++ + 1; // the value of \tcode{i} is incremented - i = i++ + i; // undefined behavior - i = i + 1; // the value of \tcode{i} is incremented -} +A::A() { } +B::B() { } + +B::A ba; // object of type \tcode{A} +A::A a; // error: \tcode{A::A} is not a type name +struct A::A a2; // object of type \tcode{A} \end{codeblock} \end{example} -\pnum -When invoking a function (whether or not the function is inline), -every argument expression and -the postfix expression designating the called function -are sequenced before every expression or statement -in the body of the called function. -For each function invocation or -evaluation of an \grammarterm{await-expression} \placeholder{F}, -each evaluation that does not occur within \placeholder{F} but -is evaluated on the same thread and as part of the same signal handler (if any) -is either sequenced before all evaluations that occur within \placeholder{F} -or sequenced after all evaluations that occur within \placeholder{F}; -\begin{footnote} -In other words, -function executions do not interleave with each other. -\end{footnote} -if \placeholder{F} invokes or resumes a coroutine\iref{expr.await}, -only evaluations -subsequent to the previous suspension (if any) and -prior to the next suspension (if any) -are considered to occur within \placeholder{F}. - -Several contexts in \Cpp{} cause evaluation of a function call, even -though no corresponding function call syntax appears in the translation -unit. -\begin{example} -Evaluation of a \grammarterm{new-expression} invokes one or more allocation -and constructor functions; see~\ref{expr.new}. For another example, -invocation of a conversion function\iref{class.conv.fct} can arise in -contexts in which no function call syntax appears. -\end{example} -The sequencing constraints on the execution of the called function (as -described above) are features of the function calls as evaluated, -regardless of the syntax of the expression that calls the function.% -\indextext{value computation|)}% +\rSec3[namespace.qual]{Namespace members} -\indextext{behavior!on receipt of signal}% -\indextext{signal}% \pnum -If a signal handler is executed as a result of a call to the \tcode{std::raise} -function, then the execution of the handler is sequenced after the invocation -of the \tcode{std::raise} function and before its return. +Qualified name lookup in a namespace $N$ additionally searches +every element of the inline namespace set of $N$\iref{namespace.def}. +If nothing is found, +the results of the lookup are the results of qualified name lookup +in each namespace nominated by a \grammarterm{using-directive} +that precedes the point of the lookup and +inhabits $N$ or an element of $N$'s inline namespace set. \begin{note} -When a signal is received for another reason, the execution of the -signal handler is usually unsequenced with respect to the rest of the program. +If a \grammarterm{using-directive} refers to a namespace +that has already been considered, it does not affect the result. \end{note} +\begin{example} +\begin{codeblock} +int x; +namespace Y { + void f(float); + void h(int); +} + +namespace Z { + void h(double); +} -\rSec2[intro.multithread]{Multi-threaded executions and data races} +namespace A { + using namespace Y; + void f(int); + void g(int); + int i; +} -\rSec3[intro.multithread.general]{General} +namespace B { + using namespace Z; + void f(char); + int i; +} -\pnum -\indextext{threads!multiple|(}% -\indextext{atomic!operation|(}% -A \defn{thread of execution} (also known as a \defn{thread}) is a single flow of -control within a program, including the initial invocation of a specific -top-level function, and recursively including every function invocation -subsequently executed by the thread. -\begin{note} -When one thread creates another, -the initial call to the top-level function of the new thread is executed by the -new thread, not by the creating thread. -\end{note} -Every thread in a program can -potentially access every object and function in a program. -\begin{footnote} -An object -with automatic or thread storage duration\iref{basic.stc} is associated with -one specific thread, and can be accessed by a different thread only indirectly -through a pointer or reference\iref{basic.compound}. -\end{footnote} -Under a hosted -implementation, a \Cpp{} program can have more than one thread running -concurrently. The execution of each thread proceeds as defined by the remainder -of this document. The execution of the entire program consists of an execution -of all of its threads. -\begin{note} -Usually the execution can be viewed as an -interleaving of all its threads. However, some kinds of atomic operations, for -example, allow executions inconsistent with a simple interleaving, as described -below. -\end{note} -\indextext{implementation!freestanding}% -Under a freestanding implementation, it is \impldef{number of -threads in a program under a freestanding implementation} whether a program can -have more than one thread of execution. +namespace AB { + using namespace A; + using namespace B; + void g(); +} + +void h() +{ + AB::g(); // \tcode{g} is declared directly in \tcode{AB}, therefore \tcode{S} is $\{ \tcode{AB::g()} \}$ and \tcode{AB::g()} is chosen + + AB::f(1); // \tcode{f} is not declared directly in \tcode{AB} so the rules are applied recursively to \tcode{A} and \tcode{B}; + // namespace \tcode{Y} is not searched and \tcode{Y::f(float)} is not considered; + // \tcode{S} is $\{ \tcode{A::f(int)}, \tcode{B::f(char)} \}$ and overload resolution chooses \tcode{A::f(int)} + + AB::f('c'); // as above but resolution chooses \tcode{B::f(char)} -\pnum -For a signal handler that is not executed as a result of a call to the -\tcode{std::raise} function, it is unspecified which thread of execution -contains the signal handler invocation. + AB::x++; // \tcode{x} is not declared directly in \tcode{AB}, and is not declared in \tcode{A} or \tcode{B}, so the rules + // are applied recursively to \tcode{Y} and \tcode{Z}, \tcode{S} is $\{ \}$ so the program is ill-formed -\rSec3[intro.races]{Data races} + AB::i++; // \tcode{i} is not declared directly in \tcode{AB} so the rules are applied recursively to \tcode{A} and \tcode{B}, + // \tcode{S} is $\{ \tcode{A::i}, \tcode{B::i} \}$ so the use is ambiguous and the program is ill-formed + + AB::h(16.8); // \tcode{h} is not declared directly in \tcode{AB} and not declared directly in \tcode{A} or \tcode{B} so the rules + // are applied recursively to \tcode{Y} and \tcode{Z}, \tcode{S} is $\{ \tcode{Y::h(int)}, \tcode{Z::h(double)} \}$ and + // overload resolution chooses \tcode{Z::h(double)} +} +\end{codeblock} +\end{example} \pnum -The value of an object visible to a thread $T$ at a particular point is the -initial value of the object, a value assigned to the object by $T$, or a -value assigned to the object by another thread, according to the rules below. \begin{note} -In some cases, there might instead be undefined behavior. Much of this -subclause is motivated by the desire to support atomic operations with explicit -and detailed visibility constraints. However, it also implicitly supports a -simpler view for more restricted programs. -\end{note} +The same declaration found more than once is not an ambiguity (because +it is still a unique declaration). +\begin{example} +\begin{codeblock} +namespace A { + int a; +} -\pnum -Two expression evaluations \defn{conflict} if one of them modifies a memory -location\iref{intro.memory} and the other one reads or modifies the same -memory location. +namespace B { + using namespace A; +} -\pnum -The library defines a number of atomic operations\iref{atomics} and -operations on mutexes\iref{thread} that are specially identified as -synchronization operations. These operations play a special role in making -assignments in one thread visible to another. A synchronization operation on one -or more memory locations is either a consume operation, an acquire operation, a -release operation, or both an acquire and release operation. A synchronization -operation without an associated memory location is a fence and can be either an -acquire fence, a release fence, or both an acquire and release fence. In -addition, there are relaxed atomic operations, which are not synchronization -operations, and atomic read-modify-write operations, which have special -characteristics. -\begin{note} -For example, a call that acquires a mutex will -perform an acquire operation on the locations comprising the mutex. -Correspondingly, a call that releases the same mutex will perform a release -operation on those same locations. Informally, performing a release operation on -$A$ forces prior -\indextext{side effects}% -side effects on other memory locations to become visible -to other threads that later perform a consume or an acquire operation on -$A$. ``Relaxed'' atomic operations are not synchronization operations even -though, like synchronization operations, they cannot contribute to data races. -\end{note} +namespace C { + using namespace A; +} -\pnum -All modifications to a particular atomic object $M$ occur in some -particular total order, called the \defn{modification order} of $M$. -\begin{note} -There is a separate order for each -atomic object. There is no requirement that these can be combined into a single -total order for all objects. In general this will be impossible since different -threads can observe modifications to different objects in inconsistent orders. -\end{note} +namespace BC { + using namespace B; + using namespace C; +} -\pnum -A \defn{release sequence} headed -by a release operation $A$ on an atomic object $M$ -is a maximal contiguous sub-sequence of -\indextext{side effects}% -side effects in the modification order of $M$, -where the first operation is $A$, and -every subsequent operation is an atomic read-modify-write operation. +void f() +{ + BC::a++; // OK, \tcode{S} is $\{ \tcode{A::a}, \tcode{A::a} \}$ +} -\pnum -Certain library calls \defn{synchronize with} other library calls performed by -another thread. For example, an atomic store-release synchronizes with a -load-acquire that takes its value from the store\iref{atomics.order}. -\begin{note} -Except in the specified cases, reading a later value does not -necessarily ensure visibility as described below. Such a requirement would -sometimes interfere with efficient implementation. -\end{note} -\begin{note} -The -specifications of the synchronization operations define when one reads the value -written by another. For atomic objects, the definition is clear. All operations -on a given mutex occur in a single total order. Each mutex acquisition ``reads -the value written'' by the last mutex release. -\end{note} +namespace D { + using A::a; +} -\pnum -An evaluation $A$ \defn{carries a dependency} to an evaluation $B$ if -\begin{itemize} -\item -the value of $A$ is used as an operand of $B$, unless: -\begin{itemize} -\item -$B$ is an invocation of any specialization of -\tcode{std::kill_dependency}\iref{atomics.order}, or -\item -$A$ is the left operand of a built-in logical \logop{and} (\tcode{\&\&}, -see~\ref{expr.log.and}) or logical \logop{or} (\tcode{||}, see~\ref{expr.log.or}) -operator, or -\item -$A$ is the left operand of a conditional (\tcode{?:}, see~\ref{expr.cond}) -operator, or -\item -$A$ is the left operand of the built-in comma (\tcode{,}) -operator\iref{expr.comma}; \end{itemize} or -\item -$A$ writes a scalar object or bit-field $M$, $B$ reads the value -written by $A$ from $M$, and $A$ is sequenced before $B$, or -\item -for some evaluation $X$, $A$ carries a dependency to $X$, and -$X$ carries a dependency to $B$. -\end{itemize} -\begin{note} -``Carries a dependency to'' is a subset of ``is sequenced before'', -and is similarly strictly intra-thread. +namespace BD { + using namespace B; + using namespace D; +} + +void g() +{ + BD::a++; // OK, \tcode{S} is $\{ \tcode{A::a}, \tcode{A::a} \}$ +} +\end{codeblock} +\end{example} \end{note} \pnum -An evaluation $A$ is \defn{dependency-ordered before} an evaluation -$B$ if -\begin{itemize} -\item -$A$ performs a release operation on an atomic object $M$, and, in -another thread, $B$ performs a consume operation on $M$ and reads -the value written by $A$, or +\begin{example} +Because each referenced namespace is searched at most once, the +following is well-defined: +\begin{codeblock} +namespace B { + int b; +} -\item -for some evaluation $X$, $A$ is dependency-ordered before $X$ and -$X$ carries a dependency to $B$. +namespace A { + using namespace B; + int a; +} -\end{itemize} -\begin{note} -The relation ``is dependency-ordered before'' is analogous to -``synchronizes with'', but uses release/consume in place of release/acquire. -\end{note} +namespace B { + using namespace A; +} -\pnum -An evaluation $A$ \defn{inter-thread happens before} an evaluation $B$ -if -\begin{itemize} -\item - $A$ synchronizes with $B$, or -\item - $A$ is dependency-ordered before $B$, or -\item - for some evaluation $X$ - \begin{itemize} - \item - $A$ synchronizes with $X$ and $X$ - is sequenced before $B$, or - \item - $A$ is sequenced before $X$ and $X$ - inter-thread happens before $B$, or - \item - $A$ inter-thread happens before $X$ and $X$ - inter-thread happens before $B$. - \end{itemize} -\end{itemize} -\begin{note} -The ``inter-thread happens before'' relation describes arbitrary -concatenations of ``sequenced before'', ``synchronizes with'' and -``dependency-ordered before'' relationships, with two exceptions. The first -exception is that a concatenation never ends with -``dependency-ordered before'' followed by ``sequenced before''. The reason for -this limitation is that a consume operation participating in a -``dependency-ordered before'' relationship provides ordering only with respect -to operations to which this consume operation actually carries a dependency. The -reason that this limitation applies only to the end of such a concatenation is -that any subsequent release operation will provide the required ordering for a -prior consume operation. The second exception is that a concatenation never -consist entirely of ``sequenced before''. The reasons for this -limitation are (1) to permit ``inter-thread happens before'' to be transitively -closed and (2) the ``happens before'' relation, defined below, provides for -relationships consisting entirely of ``sequenced before''. -\end{note} +void f() +{ + A::a++; // OK, \tcode{a} declared directly in \tcode{A}, \tcode{S} is $\{ \tcode{A::a} \}$ + B::a++; // OK, both \tcode{A} and \tcode{B} searched (once), \tcode{S} is $\{ \tcode{A::a} \}$ + A::b++; // OK, both \tcode{A} and \tcode{B} searched (once), \tcode{S} is $\{ \tcode{B::b} \}$ + B::b++; // OK, \tcode{b} declared directly in \tcode{B}, \tcode{S} is $\{ \tcode{B::b} \}$ +} +\end{codeblock} +\end{example} \pnum -An evaluation $A$ \defn{happens before} an evaluation $B$ -(or, equivalently, $B$ \defn{happens after} $A$) if -\begin{itemize} -\item $A$ is sequenced before $B$, or -\item $A$ inter-thread happens before $B$. -\end{itemize} -The implementation shall ensure that no program execution demonstrates a cycle -in the ``happens before'' relation. \begin{note} -This cycle would otherwise be -possible only through the use of consume operations. +Class and enumeration declarations are not discarded +because of other declarations found in other searches. \end{note} +\begin{example} +\begin{codeblock} +namespace A { + struct x { }; + int x; + int y; +} -\pnum -An evaluation $A$ \defn{simply happens before} an evaluation $B$ -if either -\begin{itemize} -\item $A$ is sequenced before $B$, or -\item $A$ synchronizes with $B$, or -\item $A$ simply happens before $X$ and -$X$ simply happens before $B$. -\end{itemize} -\begin{note} -In the absence of consume operations, -the happens before and simply happens before relations are identical. -\end{note} +namespace B { + struct y { }; +} -\pnum -An evaluation $A$ \defn{strongly happens before} -an evaluation $D$ if, either -\begin{itemize} -\item $A$ is sequenced before $D$, or -\item $A$ synchronizes with $D$, and -both $A$ and $D$ are -sequentially consistent atomic operations\iref{atomics.order}, or -\item there are evaluations $B$ and $C$ -such that $A$ is sequenced before $B$, -$B$ simply happens before $C$, and -$C$ is sequenced before $D$, or -\item there is an evaluation $B$ such that -$A$ strongly happens before $B$, and -$B$ strongly happens before $D$. -\end{itemize} -\begin{note} -Informally, if $A$ strongly happens before $B$, -then $A$ appears to be evaluated before $B$ -in all contexts. Strongly happens before excludes consume operations. -\end{note} +namespace C { + using namespace A; + using namespace B; + int i = C::x; // OK, \tcode{A::x} (of type \tcode{int}) + int j = C::y; // ambiguous, \tcode{A::y} or \tcode{B::y} +} +\end{codeblock} +\end{example} -\pnum -A \defnadjx{visible}{side effect}{side effects} $A$ on a scalar object or bit-field $M$ -with respect to a value computation $B$ of $M$ satisfies the -conditions: -\begin{itemize} -\item $A$ happens before $B$ and -\item there is no other -\indextext{side effects}% -side effect $X$ to $M$ such that $A$ -happens before $X$ and $X$ happens before $B$. -\end{itemize} +\indextext{lookup!qualified name|)}% -The value of a non-atomic scalar object or bit-field $M$, as determined by -evaluation $B$, is the value stored by the -\indextext{side effects!visible}% -visible side effect $A$. -\begin{note} -If there is ambiguity about which side effect to a -non-atomic object or bit-field is visible, then the behavior is either -unspecified or undefined. -\end{note} -\begin{note} -This states that operations on -ordinary objects are not visibly reordered. This is not actually detectable -without data races, but is needed to ensure that data races, as defined -below, and with suitable restrictions on the use of atomics, correspond to data -races in a simple interleaved (sequentially consistent) execution. -\end{note} +\rSec2[basic.lookup.elab]{Elaborated type specifiers}% +\indextext{lookup!elaborated type specifier|(}% +\indextext{type specifier!elaborated} \pnum -The value of an -atomic object $M$, as determined by evaluation $B$, is the value -stored by some unspecified -side effect $A$ that modifies $M$, where $B$ does not happen -before $A$. +If the \grammarterm{class-key} or \keyword{enum} keyword +in an \grammarterm{elaborated-type-specifier} +is followed by an \grammarterm{identifier} +that is not followed by \tcode{::}, +lookup for the \grammarterm{identifier} is type-only\iref{basic.lookup.general}. \begin{note} -The set of such side effects is also restricted by the rest of the rules -described here, and in particular, by the coherence requirements below. +In general, the recognition of an \grammarterm{elaborated-type-specifier} +depends on the following tokens. +If the \grammarterm{identifier} is followed by \tcode{::}, +see \ref{basic.lookup.qual}. \end{note} \pnum -\indextext{coherence!write-write}% -If an operation $A$ that modifies an atomic object $M$ happens before -an operation $B$ that modifies $M$, then $A$ is earlier -than $B$ in the modification order of $M$. -\begin{note} -This requirement is known as write-write coherence. -\end{note} +If the terminal name of the \grammarterm{elaborated-type-specifier} +is a qualified name, +lookup for it is type-only. +If the name lookup does not find a previously declared \grammarterm{type-name}, +the \grammarterm{elaborated-type-specifier} is ill-formed. \pnum -\indextext{coherence!read-read}% -If a -\indextext{value computation}% -value computation $A$ of an atomic object $M$ happens before a -value computation $B$ of $M$, and $A$ takes its value from a side -effect $X$ on $M$, then the value computed by $B$ is either -the value stored by $X$ or the value stored by a -\indextext{side effects}% -side effect $Y$ on $M$, -where $Y$ follows $X$ in the modification order of $M$. -\begin{note} -This requirement is known as read-read coherence. -\end{note} +\begin{example} +\begin{codeblock} +struct Node { + struct Node* Next; // OK, refers to injected-class-name \tcode{Node} + struct Data* Data; // OK, declares type \tcode{Data} at global scope and member \tcode{Data} +}; -\pnum -\indextext{coherence!read-write}% -If a -\indextext{value computation}% -value computation $A$ of an atomic object $M$ happens before an -operation $B$ that modifies $M$, then $A$ takes its value from a side -effect $X$ on $M$, where $X$ precedes $B$ in the -modification order of $M$. -\begin{note} -This requirement is known as -read-write coherence. -\end{note} +struct Data { + struct Node* Node; // OK, refers to \tcode{Node} at global scope + friend struct ::Glob; // error: \tcode{Glob} is not declared, cannot introduce a qualified type\iref{dcl.type.elab} + friend struct Glob; // OK, refers to (as yet) undeclared \tcode{Glob} at global scope. + @\commentellip@ +}; -\pnum -\indextext{coherence!write-read}% -If a -\indextext{side effects}% -side effect $X$ on an atomic object $M$ happens before a value -computation $B$ of $M$, then the evaluation $B$ takes its -value from $X$ or from a -\indextext{side effects}% -side effect $Y$ that follows $X$ in the modification order of $M$. -\begin{note} -This requirement is known as write-read coherence. -\end{note} +struct Base { + struct Data; // OK, declares nested \tcode{Data} + struct ::Data* thatData; // OK, refers to \tcode{::Data} + struct Base::Data* thisData; // OK, refers to nested \tcode{Data} + friend class ::Data; // OK, global \tcode{Data} is a friend + friend class Data; // OK, nested \tcode{Data} is a friend + struct Data { @\commentellip@ }; // Defines nested \tcode{Data} +}; -\pnum -\begin{note} -The four preceding coherence requirements effectively disallow -compiler reordering of atomic operations to a single object, even if both -operations are relaxed loads. This effectively makes the cache coherence -guarantee provided by most hardware available to \Cpp{} atomic operations. -\end{note} +struct Data; // OK, redeclares \tcode{Data} at global scope +struct ::Data; // error: cannot introduce a qualified type\iref{dcl.type.elab} +struct Base::Data; // error: cannot introduce a qualified type\iref{dcl.type.elab} +struct Base::Datum; // error: \tcode{Datum} undefined +struct Base::Data* pBase; // OK, refers to nested \tcode{Data} +\end{codeblock} +\end{example} +\indextext{lookup!elaborated type specifier|)}% -\pnum -\begin{note} -The value observed by a load of an atomic depends on the ``happens -before'' relation, which depends on the values observed by loads of atomics. -The intended reading is that there must exist an -association of atomic loads with modifications they observe that, together with -suitably chosen modification orders and the ``happens before'' relation derived -as described above, satisfy the resulting constraints as imposed here. -\end{note} +\rSec2[basic.lookup.udir]{Using-directives and namespace aliases} \pnum -Two actions are \defn{potentially concurrent} if -\begin{itemize} -\item they are performed by different threads, or -\item they are unsequenced, at least one is performed by a signal handler, and -they are not both performed by the same signal handler invocation. -\end{itemize} -The execution of a program contains a \defn{data race} if it contains two -potentially concurrent conflicting actions, at least one of which is not atomic, -and neither happens before the other, -except for the special case for signal handlers described below. -Any such data race results in undefined -behavior. -\begin{note} -It can be shown that programs that correctly use mutexes -and \tcode{memory_order::seq_cst} operations to prevent all data races and use no -other synchronization operations behave as if the operations executed by their -constituent threads were simply interleaved, with each -\indextext{value computation}% -value computation of an -object being taken from the last -\indextext{side effects}% -side effect on that object in that -interleaving. This is normally referred to as ``sequential consistency''. -However, this applies only to data-race-free programs, and data-race-free -programs cannot observe most program transformations that do not change -single-threaded program semantics. In fact, most single-threaded program -transformations remain possible, since any program that behaves -differently as a result has undefined behavior. -\end{note} +\indextext{lookup!using-directives and}% +\indextext{lookup!namespace aliases and}% +In a \grammarterm{using-directive} or \grammarterm{namespace-alias-definition}, +during the lookup for a \grammarterm{namespace-name} or for a name in a +\grammarterm{nested-name-specifier}{} +only namespace names are considered.% +\indextext{lookup!name|)}% -\pnum -Two accesses to the same object of type \tcode{\keyword{volatile} std::sig_atomic_t} 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 \tcode{\keyword{volatile} std::sig_atomic_t} 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$. +\rSec1[basic.def.odr]{One-definition rule}% +\indextext{object!definition}% +\indextext{function!definition}% +\indextext{class!definition}% +\indextext{enumerator!definition}% +\indextext{one-definition rule|(}% \pnum -\begin{note} -Compiler transformations that introduce assignments to a potentially -shared memory location that would not be modified by the abstract machine are -generally precluded by this document, since such an assignment might overwrite -another assignment by a different thread in cases in which an abstract machine -execution would not have encountered a data race. This includes implementations -of data member assignment that overwrite adjacent members in separate memory -locations. Reordering of atomic loads in cases in which the atomics in question -might alias is also generally precluded, since this could violate the coherence -rules. -\end{note} +Each of the following is termed a \defnadj{definable}{item}: +\begin{itemize} +\item a class type\iref{class}, +\item an enumeration type\iref{dcl.enum}, +\item a function\iref{dcl.fct}, +\item a variable\iref{basic.link}, +\item a templated entity\iref{temp.pre}, +\item a default argument for a parameter +(for a function in a given scope)\iref{dcl.fct.default}, or +\item a default template argument\iref{temp.param}. +\end{itemize} \pnum -\begin{note} -It is possible that transformations that introduce a speculative read of a potentially -shared memory location do not preserve the semantics of the \Cpp{} program as -defined in this document, since they potentially introduce a data race. However, -they are typically valid in the context of an optimizing compiler that targets a -specific machine with well-defined semantics for data races. They would be -invalid for a hypothetical machine that is not tolerant of races or provides -hardware race detection. -\end{note} - -\rSec3[intro.progress]{Forward progress} +No translation unit shall contain more than one definition of any +definable item. \pnum -The implementation may assume that any thread will eventually do one of the -following: +\indextext{expression!potentially evaluated}% +An expression or conversion is \defn{potentially evaluated} unless it is +an unevaluated operand\iref{expr.context}, +a subexpression thereof, or +a conversion in an initialization or conversion sequence in such a context. +The set of \defn{potential results} of an expression $E$ is +defined as follows: \begin{itemize} -\item terminate, -\item invoke the function \tcode{std::this_thread::yield}\iref{thread.thread.this}, -\item make a call to a library I/O function, -\item perform an access through a volatile glvalue, -\item perform a synchronization operation or an atomic operation, or -\item continue execution of a trivial infinite loop\iref{stmt.iter.general}. +\item If $E$ is an +\grammarterm{id-expression}\iref{expr.prim.id}, the set +contains only $E$. +\item If $E$ is a subscripting operation\iref{expr.sub} with +an array operand, the set contains the potential results of that operand. +\item If $E$ is a class member access +expression\iref{expr.ref} of the form +$E_1$ \tcode{.} \opt{\keyword{template}} $E_2$ +naming a non-static data member, +the set contains the potential results of $E_1$. +\item If $E$ is a class member access expression +naming a static data member, +the set contains the \grammarterm{id-expression} designating the data member. +\item If $E$ is a pointer-to-member +expression\iref{expr.mptr.oper} of the form +$E_1$ \tcode{.*} $E_2$, +the set contains the potential results of $E_1$. +\item If $E$ has the form \tcode{($E_1$)}, the set contains the +potential results of $E_1$. +\item If $E$ is a glvalue conditional +expression\iref{expr.cond}, the set is the union of the sets of +potential results of the second and third operands. +\item If $E$ is a comma expression\iref{expr.comma}, the set +contains the potential results of the right operand. +\item Otherwise, the set is empty. \end{itemize} \begin{note} -This is intended to allow compiler transformations -such as removal, merging, and reordering of empty loops, -even when termination cannot be proven. -An affordance is made for trivial infinite loops, -which cannot be removed nor reordered. +This set is a (possibly-empty) set of \grammarterm{id-expression}{s}, +each of which is either $E$ or a subexpression of $E$. +\begin{example} +In the following example, the set of potential results of the initializer +of \tcode{n} contains the first \tcode{S::x} subexpression, but not the second +\tcode{S::x} subexpression. +\begin{codeblock} +struct S { static const int x = 0; }; +const int &f(const int &r); +int n = b ? (1, S::x) // \tcode{S::x} is not odr-used here + : f(S::x); // \tcode{S::x} is odr-used here, so a definition is required +\end{codeblock} +\end{example} \end{note} \pnum -Executions of atomic functions -that are either defined to be lock-free\iref{atomics.flag} -or indicated as lock-free\iref{atomics.lockfree} -are \defnx{lock-free executions}{lock-free execution}. +A function is \defnx{named by}{function!named by expression or conversion} +an expression or conversion as follows: \begin{itemize} \item - If there is only one thread that is not blocked\iref{defns.block} - in a standard library function, - a lock-free execution in that thread shall complete. - \begin{note} - Concurrently executing threads - might prevent progress of a lock-free execution. - For example, - this situation can occur - with load-locked store-conditional implementations. - This property is sometimes termed obstruction-free. - \end{note} -\item - When one or more lock-free executions run concurrently, - at least one should complete. + A function is named by an expression or conversion + if it is the selected member + of an overload set\iref{basic.lookup,over.match,over.over} + in an overload resolution performed + as part of forming that expression or conversion, + unless it is a pure virtual function and either + the expression is not an \grammarterm{id-expression} naming the function with + an explicitly qualified name or + the expression forms a pointer to member\iref{expr.unary.op}. \begin{note} - It is difficult for some implementations - to provide absolute guarantees to this effect, - since repeated and particularly inopportune interference - from other threads - could prevent forward progress, - e.g., - by repeatedly stealing a cache line - for unrelated purposes - between load-locked and store-conditional instructions. - For implementations that follow this recommendation and - ensure that such effects cannot indefinitely delay progress - under expected operating conditions, - such anomalies - can therefore safely be ignored by programmers. - Outside this document, - this property is sometimes termed lock-free. - \end{note} +This covers + taking the address of functions\iref{conv.func,expr.unary.op}, + calls to named functions\iref{expr.call}, + operator overloading\iref{over}, + user-defined conversions\iref{class.conv.fct}, + allocation functions for \grammarterm{new-expression}{s}\iref{expr.new}, as well as + non-default initialization\iref{dcl.init}. + A constructor selected to copy or move an object of class type + is considered to be named by an expression or conversion + even if the call is actually elided by the implementation\iref{class.copy.elision}. +\end{note} +\item + A deallocation function for a class + is named by a \grammarterm{new-expression} + if it is the single matching deallocation function + for the allocation function selected by overload resolution, + as specified in~\ref{expr.new}. +\item + A deallocation function for a class + is named by a \grammarterm{delete-expression} + if it is the selected usual deallocation function + as specified in~\ref{expr.delete} and~\ref{class.free}. \end{itemize} \pnum -During the execution of a thread of execution, each of the following is termed -an \defn{execution step}: +\label{term.odr.use}% +A variable is named by an expression +if the expression is an \grammarterm{id-expression} that denotes it. +A variable \tcode{x} that is named by a +potentially-evaluated expression $E$ +is \defnx{odr-used}{odr-use} by $E$ unless \begin{itemize} -\item termination of the thread of execution, -\item performing an access through a volatile glvalue, or -\item completion of a call to a library I/O function, a - synchronization operation, or an atomic operation. +\item + \tcode{x} is a reference that is + usable in constant expressions\iref{expr.const}, or +\item + \tcode{x} is a variable of non-reference type that is + usable in constant expressions and has no mutable subobjects, and + $E$ is an element of the set of potential results of an expression + of non-volatile-qualified non-class type + to which the lvalue-to-rvalue conversion\iref{conv.lval} is applied, or +\item + \tcode{x} is a variable of non-reference type, and + $E$ is an element of the set of potential results + of a discarded-value expression\iref{expr.context} + to which the lvalue-to-rvalue conversion is not applied. \end{itemize} \pnum -An invocation of a standard library function that blocks\iref{defns.block} -is considered to continuously execute execution steps while waiting for the -condition that it blocks on to be satisfied. -\begin{example} -A library I/O function that blocks until the I/O operation is complete can -be considered to continuously check whether the operation is complete. Each -such check consists of one or more execution steps, for example using -observable behavior of the abstract machine. -\end{example} - -\pnum -\begin{note} -Because of this and the preceding requirement regarding what threads of execution -have to perform eventually, it follows that no thread of execution can execute -forever without an execution step occurring. -\end{note} - -\pnum -A thread of execution \defnx{makes progress}{make progress!thread} -when an execution step occurs or a -lock-free execution does not complete because there are other concurrent threads -that are not blocked in a standard library function (see above). - -\pnum -\indextext{forward progress guarantees!concurrent}% -For a thread of execution providing \defn{concurrent forward progress guarantees}, -the implementation ensures that the thread will eventually make progress for as -long as it has not terminated. -\begin{note} -This applies regardless of whether or not other threads of execution (if any) -have been or are making progress. To eventually fulfill this requirement means that -this will happen in an unspecified but finite amount of time. -\end{note} - -\pnum -It is \impldef{whether the thread that executes \tcode{main} and the threads created -by \tcode{std::thread} or \tcode{std::jthread} provide concurrent forward progress guarantees} whether the -implementation-created thread of execution that executes -\tcode{main}\iref{basic.start.main} and the threads of execution created by -\tcode{std::thread}\iref{thread.thread.class} -or \tcode{std::jthread}\iref{thread.jthread.class} -provide concurrent forward progress guarantees. -General-purpose implementations should provide these guarantees. +A structured binding is odr-used if it appears as a potentially-evaluated expression. \pnum -\indextext{forward progress guarantees!parallel}% -For a thread of execution providing \defn{parallel forward progress guarantees}, -the implementation is not required to ensure that the thread will eventually make -progress if it has not yet executed any execution step; once this thread has -executed a step, it provides concurrent forward progress guarantees. +\tcode{*\keyword{this}} is odr-used if \keyword{this} appears as a potentially-evaluated expression +(including as the result of any implicit transformation to +a class member access expression\iref{expr.prim.id.general}). \pnum -\begin{note} -This does not specify a requirement for when to start this thread of execution, -which will typically be specified by the entity that creates this thread of -execution. For example, a thread of execution that provides concurrent forward -progress guarantees and executes tasks from a set of tasks in an arbitrary order, -one after the other, satisfies the requirements of parallel forward progress for -these tasks. -\end{note} +A virtual member +function is odr-used if it is not pure. +A function is odr-used if it is named by +a potentially-evaluated expression or conversion. +A non-placement allocation or deallocation +function for a class is odr-used by the definition of a constructor of that +class. A non-placement deallocation function for a class is odr-used by the +definition of the destructor of that class, or by being selected by the +lookup at the point of definition of a virtual +destructor\iref{class.dtor}. +\begin{footnote} +An implementation is not required +to call allocation and +deallocation functions from constructors or destructors; however, this +is a permissible implementation technique. +\end{footnote} \pnum -\indextext{forward progress guarantees!weakly parallel}% -For a thread of execution providing \defn{weakly parallel forward progress -guarantees}, the implementation does not ensure that the thread will eventually -make progress. +An assignment operator function in a class is odr-used by an +implicitly-defined +copy assignment or move assignment function for another class as specified +in~\ref{class.copy.assign}. +A constructor for a class is odr-used as specified +in~\ref{dcl.init}. A destructor for a class is odr-used if it is potentially +invoked\iref{class.dtor}. \pnum -\begin{note} -Threads of execution providing weakly parallel forward progress guarantees cannot -be expected to make progress regardless of whether other threads make progress or -not; however, blocking with forward progress guarantee delegation, as defined below, -can be used to ensure that such threads of execution make progress eventually. -\end{note} +A \defnadj{local}{entity} is a variable with +automatic storage duration\iref{basic.stc.auto}, +a structured binding\iref{dcl.struct.bind} +whose corresponding variable is such an entity, +or the \tcode{*\keyword{this}} object\iref{expr.prim.this}. \pnum -Concurrent forward progress guarantees are stronger than parallel forward progress -guarantees, which in turn are stronger than weakly parallel forward progress -guarantees. -\begin{note} -For example, some kinds of synchronization between threads of execution might only -make progress if the respective threads of execution provide parallel forward progress -guarantees, but will fail to make progress under weakly parallel guarantees. -\end{note} +A local entity +is \defn{odr-usable} in a scope\iref{basic.scope.scope} if +\begin{itemize} +\item either the local entity is not \tcode{*\keyword{this}}, or +an enclosing class or non-lambda function parameter scope exists and, +if the innermost such scope is a function parameter scope, +it corresponds to a non-static member function, and +\item +for each intervening scope\iref{basic.scope.scope} +between the point at which the entity is introduced and the scope +(where \tcode{*\keyword{this}} is considered to be introduced +within the innermost enclosing class or non-lambda function definition scope), +either: +\begin{itemize} +\item the intervening scope is a block scope, or +\item the intervening scope is the function parameter scope of a \grammarterm{lambda-expression}, or +\item the intervening scope is the lambda scope of +a \grammarterm{lambda-expression} +that has a \grammarterm{simple-capture} +naming the entity or has a \grammarterm{capture-default}, and +the block scope of the \grammarterm{lambda-expression} +is also an intervening scope. +\end{itemize} +\end{itemize} -\pnum -\indextext{forward progress guarantees!delegation of}% -When a thread of execution $P$ is specified to -\defnx{block with forward progress guarantee delegation} -{block (execution)!with forward progress guarantee delegation} -on the completion of a set $S$ of threads of execution, -then throughout the whole time of $P$ being blocked on $S$, -the implementation shall ensure that the forward progress guarantees -provided by at least one thread of execution in $S$ -is at least as strong as $P$'s forward progress guarantees. -\begin{note} -It is unspecified which thread or threads of execution in $S$ are chosen -and for which number of execution steps. The strengthening is not permanent and -not necessarily in place for the rest of the lifetime of the affected thread of -execution. As long as $P$ is blocked, the implementation has to eventually -select and potentially strengthen a thread of execution in $S$. -\end{note} -Once a thread of execution in $S$ terminates, it is removed from $S$. -Once $S$ is empty, $P$ is unblocked. +If a local entity is odr-used +in a scope in which it is not odr-usable, +the program is ill-formed. +\begin{example} +\begin{codeblock} +void f(int n) { + [] { n = 1; }; // error: \tcode{n} is not odr-usable due to intervening lambda-expression + struct A { + void f() { n = 2; } // error: \tcode{n} is not odr-usable due to intervening function definition scope + }; + void g(int = n); // error: \tcode{n} is not odr-usable due to intervening function parameter scope + [=](int k = n) {}; // error: \tcode{n} is not odr-usable due to being + // outside the block scope of the \grammarterm{lambda-expression} + [&] { [n]{ return n; }; }; // OK +} +\end{codeblock} +\end{example} \pnum -\begin{note} -A thread of execution $B$ thus can temporarily provide an effectively -stronger forward progress guarantee for a certain amount of time, due to a -second thread of execution $A$ being blocked on it with forward -progress guarantee delegation. In turn, if $B$ then blocks with -forward progress guarantee delegation on $C$, this can also temporarily -provide a stronger forward progress guarantee to $C$. -\end{note} +\begin{example} +\begin{codeblock} +void g() { + constexpr int x = 1; + auto lambda = [] {}; // OK + lambda.operator()(); // OK, does not consider \tcode{x} at all + lambda.operator()(); // OK, does not odr-use \tcode{x} + lambda.operator()(); // error: odr-uses \tcode{x} from a context where \tcode{x} is not odr-usable +} -\pnum -\begin{note} -If all threads of execution in $S$ finish executing (e.g., they terminate -and do not use blocking synchronization incorrectly), then $P$'s execution -of the operation that blocks with forward progress guarantee delegation will not -result in $P$'s progress guarantee being effectively weakened. -\end{note} +void h() { + constexpr int x = 1; + auto lambda = [] { (T)x; }; // OK + lambda.operator()(); // OK, does not odr-use \tcode{x} + lambda.operator()(); // OK, does not odr-use \tcode{x} + lambda.operator()(); // error: odr-uses \tcode{x} from a context where \tcode{x} is not odr-usable +} +\end{codeblock} +\end{example} \pnum -\begin{note} -This does not remove any constraints regarding blocking synchronization for -threads of execution providing parallel or weakly parallel forward progress -guarantees because the implementation is not required to strengthen a particular -thread of execution whose too-weak progress guarantee is preventing overall progress. -\end{note} +Every program shall contain at least one definition of every +function or variable that is odr-used in that program +outside of a discarded statement\iref{stmt.if}; no diagnostic required. +The definition can appear explicitly in the program, it can be found in +the standard or a user-defined library, or (when appropriate) it is +implicitly defined (see~\ref{class.default.ctor}, \ref{class.copy.ctor}, +\ref{class.dtor}, and \ref{class.copy.assign}). +\begin{example} +\begin{codeblock} +auto f() { + struct A {}; + return A{}; +} +decltype(f()) g(); +auto x = g(); +\end{codeblock} +A program containing this translation unit is ill-formed +because \tcode{g} is odr-used but not defined, +and cannot be defined in any other translation unit +because the local class \tcode{A} cannot be named outside this +translation unit. +\end{example} \pnum -An implementation should ensure that the last value (in modification order) -assigned by an atomic or synchronization operation will become visible to all -other threads in a finite period of time.% -\indextext{atomic!operation|)}% -\indextext{threads!multiple|)} - -\rSec2[basic.start]{Start and termination} - -\rSec3[basic.start.main]{\tcode{main} function} -\indextext{\idxcode{main} function|(} +A \defn{definition domain} is +a \grammarterm{private-module-fragment} or +the portion of a translation unit +excluding its \grammarterm{private-module-fragment} (if any). +A definition of an inline function or variable shall be reachable +from the end of every definition domain +in which it is odr-used outside of a discarded statement. \pnum -\indextext{program!startup|(}% -A program shall contain exactly one function called \tcode{main} -that belongs to the global scope. -Executing a program starts a main thread of execution\iref{intro.multithread,thread.threads} -in which the \tcode{main} function is invoked. -\indextext{implementation!freestanding}% -It is \impldef{defining \tcode{main} in freestanding environment} -whether a program in a freestanding environment is required to define a \tcode{main} -function. +\indextext{type!incomplete}% +A definition of a class shall be reachable in every context in which +the class is used in a way that requires the class type to be complete. +\begin{example} +The following complete translation unit is well-formed, +even though it never defines \tcode{X}: +\begin{codeblock} +struct X; // declare \tcode{X} as a struct type +struct X* x1; // use \tcode{X} in pointer formation +X* x2; // use \tcode{X} in pointer formation +\end{codeblock} +\end{example} \begin{note} -In a freestanding environment, startup and termination is -\impldef{startup and termination in freestanding environment}; startup contains the -execution of constructors for non-local objects with static storage duration; -termination contains the execution of destructors for objects with static storage -duration. -\end{note} - -\pnum -An implementation shall not predefine the \tcode{main} function. -Its type shall have \Cpp{} language linkage -and it shall have a declared return type of type -\keyword{int}, but otherwise its type is \impldef{parameters to \tcode{main}}. -\indextext{\idxcode{main} function!implementation-defined parameters to}% -An implementation shall allow both +The rules for declarations and expressions +describe in which contexts complete class types are required. A class +type \tcode{T} must be complete if \begin{itemize} -\item a function of \tcode{()} returning \keyword{int} and -\item a function of \tcode{(\keyword{int}}, pointer to pointer to \tcode{\keyword{char})} returning \keyword{int} +\item an object of type \tcode{T} is defined\iref{basic.def}, or +\item a non-static class data member of type \tcode{T} is +declared\iref{class.mem}, or +\item \tcode{T} is used as the allocated type or array element type in a +\grammarterm{new-expression}\iref{expr.new}, or +\item an lvalue-to-rvalue conversion is applied to +a glvalue referring +to an object of type \tcode{T}\iref{conv.lval}, or +\item an expression is converted (either implicitly or explicitly) to +type \tcode{T}\iref{conv,expr.type.conv, +expr.dynamic.cast,expr.static.cast,expr.cast}, or +\item an expression that is not a null pointer constant, and has type +other than \cv{}~\tcode{\keyword{void}*}, is converted to the type pointer to \tcode{T} +or reference to \tcode{T} using a standard conversion\iref{conv}, +a \keyword{dynamic_cast}\iref{expr.dynamic.cast} or +a \keyword{static_cast}\iref{expr.static.cast}, or +\item a class member access operator is applied to an expression of type +\tcode{T}\iref{expr.ref}, or +\item the \keyword{typeid} operator\iref{expr.typeid} or the +\keyword{sizeof} operator\iref{expr.sizeof} is applied to an operand of +type \tcode{T}, or +\item a function with a return type or argument type of type \tcode{T} +is defined\iref{basic.def} or called\iref{expr.call}, or +\item a class with a base class of type \tcode{T} is +defined\iref{class.derived}, or +\item an lvalue of type \tcode{T} is assigned to\iref{expr.ass}, or +\item the type \tcode{T} is the subject of an +\keyword{alignof} expression\iref{expr.alignof}, or +\item an \grammarterm{exception-declaration} has type \tcode{T}, reference to +\tcode{T}, or pointer to \tcode{T}\iref{except.handle}. \end{itemize} -\indextext{\idxcode{argc}}% -\indextext{\idxcode{argv}}% -as the type of \tcode{main}\iref{dcl.fct}. -\indextext{\idxcode{main} function!parameters to}% -\indextext{environment!program}% -In the latter form, for purposes of exposition, the first function -parameter is called \tcode{argc} and the second function parameter is -called \tcode{argv}, where \tcode{argc} shall be the number of -arguments passed to the program from the environment in which the -program is run. If -\tcode{argc} is nonzero these arguments shall be supplied in -\tcode{argv[0]} through \tcode{argv[argc-1]} as pointers to the initial -characters of null-terminated multibyte strings (\ntmbs{}s)\iref{multibyte.strings} -and \tcode{argv[0]} shall be the pointer to -the initial character of an \ntmbs{} that represents the name used to -invoke the program or \tcode{""}. The value of \tcode{argc} shall be -non-negative. The value of \tcode{argv[argc]} shall be 0. +\end{note} -\recommended -Any further (optional) parameters should be added after \tcode{argv}. - -\pnum -The function \tcode{main} shall not be named by an expression. -\indextext{\idxcode{main} function!implementation-defined linkage of}% -The linkage\iref{basic.link} of \tcode{main} is -\impldef{linkage of \tcode{main}}. A program that defines \tcode{main} as -deleted or that declares \tcode{main} to be -\keyword{inline}, \keyword{static}, \keyword{constexpr}, or \keyword{consteval} is ill-formed. -The function \tcode{main} shall not be a coroutine\iref{dcl.fct.def.coroutine}. -The \tcode{main} function shall not be declared with a -\grammarterm{linkage-specification}\iref{dcl.link}. -A program that declares +\pnum +For any definable item \tcode{D} with definitions in multiple translation units, \begin{itemize} \item -a variable \tcode{main} that belongs to the global scope, or +if \tcode{D} is a non-inline non-templated function or variable, or \item -a function \tcode{main} that belongs to the global scope and -is attached to a named module, or +if the definitions in different translation units +do not satisfy the following requirements, +\end{itemize} +the program is ill-formed; +a diagnostic is required only +if the definable item is attached to a named module and +a prior definition is reachable at the point where a later definition occurs. +Given such an item, +for all definitions of \tcode{D}, or, +if \tcode{D} is an unnamed enumeration, +for all definitions of \tcode{D} that are reachable at any given program point, +the following requirements shall be satisfied. +\begin{itemize} +\item Each such definition +shall not be attached to a named module\iref{module.unit}. +\item Each such definition shall consist of +the same sequence of tokens, +where the definition of a closure type +is considered to consist of the sequence of tokens of +the corresponding \grammarterm{lambda-expression}. +\item In each such definition, corresponding names, looked up +according to~\ref{basic.lookup}, shall refer to the same entity, after +overload resolution\iref{over.match} and after matching of partial +template specialization\iref{temp.over}, except that a name can refer to +\begin{itemize} \item -a function template \tcode{main} that belongs to the global scope, or +a non-volatile const object with internal or no linkage if the object +\begin{itemize} +\item has the same literal type in all definitions of \tcode{D}, +\item is initialized with a constant expression\iref{expr.const}, +\item is not odr-used in any definition of \tcode{D}, and +\item has the same value in all definitions of \tcode{D}, +\end{itemize} +or \item -an entity named \tcode{main} -with C language linkage (in any namespace) +a reference with internal or no linkage +initialized with a constant expression such that +the reference refers to the same entity in all definitions of \tcode{D}. \end{itemize} -is ill-formed. -The name \tcode{main} is -not otherwise reserved. -\begin{example} -Member functions, classes, and -enumerations can be called \tcode{main}, as can entities in other -namespaces. -\end{example} -\pnum -\indextext{\idxcode{exit}}% -\indexlibraryglobal{exit}% -\indextext{termination!program}% -Terminating the program -without leaving the current block (e.g., by calling the function -\tcode{std::exit(int)}\iref{support.start.term}) does not destroy any -objects with automatic storage duration\iref{class.dtor}. If -\tcode{std::exit} is invoked during the destruction of -an object with static or thread storage duration, the program has undefined -behavior. - -\pnum -\indextext{termination!program}% -\indextext{\idxcode{main} function!return from}% -A \keyword{return} statement\iref{stmt.return} in \tcode{main} has the effect of leaving the main -function (destroying any objects with automatic storage duration) and -calling \tcode{std::exit} with the return value as the argument. -If control flows off the end of -the \grammarterm{compound-statement} of \tcode{main}, -the effect is equivalent to a \keyword{return} with operand \tcode{0} -(see also \ref{except.handle}). -\indextext{\idxcode{main} function|)} - -\rSec3[basic.start.static]{Static initialization} - -\pnum -\indextext{initialization}% -\indextext{initialization!static and thread}% -Variables with static storage duration -are initialized as a consequence of program initiation. Variables with -thread storage duration are initialized as a consequence of thread execution. -Within each of these phases of initiation, initialization occurs as follows. - -\pnum -\indextext{initialization!constant}% -\defnx{Constant initialization}{constant initialization} is performed -if a variable or temporary object with static or thread storage duration -is constant-initialized\iref{expr.const}. -\indextext{initialization!zero-initialization}% -If constant initialization is not performed, a variable with static -storage duration\iref{basic.stc.static} or thread storage -duration\iref{basic.stc.thread} is zero-initialized\iref{dcl.init}. -Together, zero-initialization and constant initialization are called -\defnadj{static}{initialization}; -all other initialization is \defnadj{dynamic}{initialization}. -All static initialization strongly happens before\iref{intro.races} -any dynamic initialization. -\begin{note} -The dynamic initialization of non-block variables is described -in~\ref{basic.start.dynamic}; that of static block variables is described -in~\ref{stmt.dcl}. -\end{note} +\item In each such definition, except within +the default arguments and default template arguments of \tcode{D}, +corresponding \grammarterm{lambda-expression}{s} shall have +the same closure type (see below). -\pnum -An implementation is permitted to perform the initialization of a -variable with static or thread storage duration as a static -initialization even if such initialization is not required to be done -statically, provided that -\begin{itemize} -\item -the dynamic version of the initialization does not change the -value of any other object of static or thread storage duration -prior to its initialization, and +\item In each such definition, corresponding entities shall have the +same language linkage. -\item -the static version of the initialization produces the same value -in the initialized variable as would be produced by the dynamic -initialization if all variables not required to be initialized statically -were initialized dynamically. -\end{itemize} -\begin{note} -As a consequence, if the initialization of an object \tcode{obj1} refers to an -object \tcode{obj2} potentially requiring dynamic initialization and defined -later in the same translation unit, it is unspecified whether the value of \tcode{obj2} used -will be the value of the fully initialized \tcode{obj2} (because \tcode{obj2} was statically -initialized) or will be the value of \tcode{obj2} merely zero-initialized. For example, -\begin{codeblock} -inline double fd() { return 1.0; } -extern double d1; -double d2 = d1; // unspecified: - // either statically initialized to \tcode{0.0} or - // dynamically initialized to \tcode{0.0} if \tcode{d1} is - // dynamically initialized, or \tcode{1.0} otherwise -double d1 = fd(); // either initialized statically or dynamically to \tcode{1.0} -\end{codeblock} -\end{note} +\item In each such definition, +const objects with static or thread storage duration +shall be constant-initialized if +the object is constant-initialized in any such definition. -\rSec3[basic.start.dynamic]{Dynamic initialization of non-block variables} +\item In each such definition, +corresponding manifestly constant-evaluated expressions +that are not value-dependent +shall have the same value\iref{expr.const,temp.dep.constexpr}. -\pnum -\indextext{initialization!dynamic non-block}% -\indextext{start!program}% -\indextext{initialization!order of}% -Dynamic initialization of a non-block variable with static storage duration is -unordered if the variable is an implicitly or explicitly instantiated -specialization, is partially-ordered if the variable -is an inline variable that is not an implicitly or explicitly instantiated -specialization, and otherwise is ordered. -\begin{note} -A non-inline explicit specialization of a templated variable -has ordered initialization. -\end{note} +\item In each such definition, the overloaded operators referred +to, the implicit calls to conversion functions, constructors, operator +new functions and operator delete functions, shall refer to the same +function. -\pnum -A declaration \tcode{D} is -\defn{appearance-ordered} before a declaration \tcode{E} if -\begin{itemize} -\item \tcode{D} appears in the same translation unit as \tcode{E}, or -\item the translation unit containing \tcode{E} -has an interface dependency on the translation unit containing \tcode{D}, +\item In each such definition, +a default argument used by an (implicit or explicit) function call or +a default template argument used by an (implicit or explicit) +\grammarterm{template-id} or \grammarterm{simple-template-id} +is treated as if its token sequence +were present in the definition of \tcode{D}; +that is, the default argument or default template argument +is subject to the requirements described in this paragraph (recursively). \end{itemize} -in either case prior to \tcode{E}. \pnum -Dynamic initialization of non-block variables \tcode{V} and \tcode{W} -with static storage duration are ordered as follows: -\begin{itemize} -\item -If \tcode{V} and \tcode{W} have ordered initialization and -the definition of \tcode{V} -is appearance-ordered before the definition of \tcode{W}, or -if \tcode{V} has partially-ordered initialization, -\tcode{W} does not have unordered initialization, and -for every definition \tcode{E} of \tcode{W} -there exists a definition \tcode{D} of \tcode{V} -such that \tcode{D} is appearance-ordered before \tcode{E}, then +For the purposes of the preceding requirements: + \begin{itemize} -\item -if the program does not start a thread\iref{intro.multithread} -other than the main thread\iref{basic.start.main} -or \tcode{V} and \tcode{W} have ordered initialization and -they are defined in the same translation unit, -the initialization of \tcode{V} -is sequenced before -the initialization of \tcode{W}; -\item -otherwise, -the initialization of \tcode{V} -strongly happens before -the initialization of \tcode{W}. -\end{itemize} +\item If \tcode{D} is a class with an implicitly-declared +constructor\iref{class.default.ctor,class.copy.ctor}, +it is as if the constructor was +implicitly defined in every translation unit where it is odr-used, and the +implicit definition in every translation unit shall call the same +constructor for a subobject of \tcode{D}. +\begin{example} +\begin{codeblock} +// translation unit 1: +struct X { + X(int, int); + X(int, int, int); +}; +X::X(int, int = 0) { } +class D { + X x = 0; +}; +D d1; // \tcode{X(int, int)} called by \tcode{D()} -\item -Otherwise, if the program starts a thread -other than the main thread -before either \tcode{V} or \tcode{W} is initialized, -it is unspecified in which threads -the initializations of \tcode{V} and \tcode{W} occur; -the initializations are unsequenced if they occur in the same thread. +// translation unit 2: +struct X { + X(int, int); + X(int, int, int); +}; +X::X(int, int = 0, int = 0) { } +class D { + X x = 0; +}; +D d2; // \tcode{X(int, int, int)} called by \tcode{D()}; + // \tcode{D()}'s implicit definition violates the ODR +\end{codeblock} +\end{example} + +\item If \tcode{D} is a class with +a defaulted three-way comparison operator function\iref{class.spaceship}, +it is as if the operator was +implicitly defined in every translation unit where it is odr-used, and the +implicit definition in every translation unit shall call the same +comparison operators for each subobject of \tcode{D}. \item -Otherwise, the initializations of \tcode{V} and \tcode{W} are indeterminately sequenced. +If \tcode{D} is a template and is defined in more than one +translation unit, the requirements +apply both to names from the template's enclosing scope used in the +template definition, and also to dependent names at +the point of instantiation\iref{temp.dep}. \end{itemize} -\begin{note} -This definition permits initialization of a sequence of -ordered variables concurrently with another sequence. -\end{note} \pnum -\indextext{non-initialization odr-use|see{odr-use, non-initialization}}% -A \defnx{non-initialization odr-use}{odr-use!non-initialization} -is an odr-use\iref{term.odr.use} not caused directly or indirectly by -the initialization of a non-block static or thread storage duration variable. +These requirements also apply to corresponding entities +defined within each definition of \tcode{D} +(including the closure types of \grammarterm{lambda-expression}{s}, +but excluding entities defined within default arguments or +default template arguments of either \tcode{D} or +an entity not defined within \tcode{D}). +For each such entity and for \tcode{D} itself, +the behavior is as if there is a single entity with a single definition, +including in the application of these requirements to other entities. +\begin{note} +The entity is still declared in multiple translation units, and \ref{basic.link} +still applies to these declarations. In particular, +\grammarterm{lambda-expression}{s}\iref{expr.prim.lambda} +appearing in the type of \tcode{D} can result +in the different declarations having distinct types, and +\grammarterm{lambda-expression}{s} appearing in a default argument of \tcode{D} +might still denote different types in different translation units. +\end{note} \pnum -\indextext{evaluation!unspecified order of}% -It is \impldef{dynamic initialization of static variables before \tcode{main}} -whether the dynamic initialization of a -non-block non-inline variable with static storage duration -is sequenced before the first statement of \tcode{main} or is deferred. -If it is deferred, it strongly happens before -any non-initialization odr-use -of any non-inline function or non-inline variable -defined in the same translation unit as the variable to be initialized. -\begin{footnote} -A non-block variable with static storage duration -having initialization -with side effects is initialized in this case, -even if it is not itself odr-used\iref{term.odr.use,basic.stc.static}. -\end{footnote} -It is \impldef{threads and program points at which deferred dynamic initialization is performed} -in which threads and at which points in the program such deferred dynamic initialization occurs. - -\recommended -An implementation should choose such points in a way -that allows the programmer to avoid deadlocks. \begin{example} \begin{codeblock} -// - File 1 - -#include "a.h" -#include "b.h" -B b; -A::A() { - b.Use(); +inline void f(bool cond, void (*p)()) { + if (cond) f(false, []{}); } - -// - File 2 - -#include "a.h" -A a; - -// - File 3 - -#include "a.h" -#include "b.h" -extern A a; -extern B b; - -int main() { - a.Use(); - b.Use(); +inline void g(bool cond, void (*p)() = []{}) { + if (cond) g(false); } +struct X { + void h(bool cond, void (*p)() = []{}) { + if (cond) h(false); + } +}; \end{codeblock} -It is \impldef{dynamic initialization of static variables before \tcode{main}} -whether either \tcode{a} or \tcode{b} is -initialized before \tcode{main} is entered or whether the -initializations are delayed until \tcode{a} is first odr-used in -\tcode{main}. In particular, if \tcode{a} is initialized before -\tcode{main} is entered, it is not guaranteed that \tcode{b} will be -initialized before it is odr-used by the initialization of \tcode{a}, that -is, before \tcode{A::A} is called. If, however, \tcode{a} is initialized -at some point after the first statement of \tcode{main}, \tcode{b} will -be initialized prior to its use in \tcode{A::A}. +If the definition of \tcode{f} appears in multiple translation units, +the behavior of the program is as if +there is only one definition of \tcode{f}. +If the definition of \tcode{g} appears in multiple translation units, +the program is ill-formed (no diagnostic required) because +each such definition uses a default argument that +refers to a distinct \grammarterm{lambda-expression} closure type. +The definition of \tcode{X} can appear +in multiple translation units of a valid program; +the \grammarterm{lambda-expression}{s} defined within +the default argument of \tcode{X::h} within the definition of \tcode{X} +denote the same closure type in each translation unit. \end{example} \pnum -It is \impldef{dynamic initialization of static inline variables before \tcode{main}} -whether the dynamic initialization of a -non-block inline variable with static storage duration -is sequenced before the first statement of \tcode{main} or is deferred. -If it is deferred, it strongly happens before -any non-initialization odr-use -of that variable. -It is \impldef{threads and program points at which deferred dynamic initialization is performed} -in which threads and at which points in the program such deferred dynamic initialization occurs. - -\pnum -It is \impldef{dynamic initialization of thread-local variables before entry} -whether the dynamic initialization of a -non-block non-inline variable with thread storage duration -is sequenced before the first statement of the initial function of a thread or is deferred. -If it is deferred, -the initialization associated with the entity for thread \placeholder{t} -is sequenced before the first non-initialization odr-use by \placeholder{t} -of any non-inline variable with thread storage duration -defined in the same translation unit as the variable to be initialized. -It is \impldef{threads and program points at which deferred dynamic initialization is performed} -in which threads and at which points in the program such deferred dynamic initialization occurs. - -\pnum -If the initialization of -a non-block variable with static or thread storage duration -exits via an exception, -the function \tcode{std::terminate} is called\iref{except.terminate}.% -\indextext{program!startup|)} - -\rSec3[basic.start.term]{Termination} - -\pnum -\indextext{program!termination|(}% -\indextext{object!destructor static}% -\indextext{\idxcode{main} function!return from}% -Constructed objects\iref{dcl.init} -with static storage duration are destroyed -and functions registered with \tcode{std::atexit} -are called as part of a call to -\indextext{\idxcode{exit}}% -\indexlibraryglobal{exit}% -\tcode{std::exit}\iref{support.start.term}. -The call to \tcode{std::exit} is sequenced before -the destructions and the registered functions. -\begin{note} -Returning from \tcode{main} invokes \tcode{std::exit}\iref{basic.start.main}. -\end{note} - -\pnum -Constructed objects with thread storage duration within a given thread -are destroyed as a result of returning from the initial function of that thread and as a -result of that thread calling \tcode{std::exit}. -The destruction of all constructed objects with thread storage -duration within that thread strongly happens before destroying -any object with static storage duration. - -\pnum -If the completion of the constructor or dynamic initialization of an object with static -storage duration strongly happens before that of another, the completion of the destructor -of the second is sequenced before the initiation of the destructor of the first. -If the completion of the constructor or dynamic initialization of an object with thread -storage duration is sequenced before that of another, the completion of the destructor -of the second is sequenced before the initiation of the destructor of the first. -If an object is -initialized statically, the object is destroyed in the same order as if -the object was dynamically initialized. For an object of array or class -type, all subobjects of that object are destroyed before any block -variable with static storage duration initialized during the construction -of the subobjects is destroyed. -If the destruction of an object with static or thread storage duration -exits via an exception, -the function \tcode{std::terminate} is called\iref{except.terminate}. - -\pnum -If a function contains a block variable of static or thread storage duration that has been -destroyed and the function is called during the destruction of an object with static or -thread storage duration, the program has undefined behavior if the flow of control -passes through the definition of the previously destroyed block variable. -\begin{note} -Likewise, the behavior is undefined -if the block variable is used indirectly (e.g., through a pointer) -after its destruction. -\end{note} - -\pnum -\indextext{\idxcode{atexit}}% -\indexlibraryglobal{atexit}% -If the completion of the initialization of an object with static storage -duration strongly happens before a call to \tcode{std::atexit}~(see -\libheader{cstdlib}, \ref{support.start.term}), the call to the function passed to -\tcode{std::atexit} is sequenced before the call to the destructor for the object. If a -call to \tcode{std::atexit} strongly happens before the completion of the initialization of -an object with static storage duration, the call to the destructor for the -object is sequenced before the call to the function passed to \tcode{std::atexit}. If a -call to \tcode{std::atexit} strongly happens before another call to \tcode{std::atexit}, the -call to the function passed to the second \tcode{std::atexit} call is sequenced before -the call to the function passed to the first \tcode{std::atexit} call. - -\pnum -If there is a use of a standard library object or function not permitted within signal -handlers\iref{support.runtime} that does not happen before\iref{intro.multithread} -completion of destruction of objects with static storage duration and execution of -\tcode{std::atexit} registered functions\iref{support.start.term}, the program has -undefined behavior. -\begin{note} -If there is a use of an object with static storage -duration that does not happen before the object's destruction, the program has undefined -behavior. Terminating every thread before a call to \tcode{std::exit} or the exit from -\tcode{main} is sufficient, but not necessary, to satisfy these requirements. These -requirements permit thread managers as static-storage-duration objects. -\end{note} - -\pnum -\indextext{\idxcode{abort}}% -\indexlibraryglobal{abort}% -\indextext{termination!program}% -Calling the function \tcode{std::abort()} declared in -\libheaderref{cstdlib} terminates the program without executing any destructors -and without calling -the functions passed to \tcode{std::atexit()} or \tcode{std::at_quick_exit()}.% -\indextext{program!termination|)} -\indextext{program execution|)} +If, at any point in the program, +there is more than one +reachable unnamed enumeration definition in the same scope +that have the same first enumerator name and +do not have typedef names for linkage purposes\iref{dcl.enum}, +those unnamed enumeration types shall be the same; no diagnostic required. +\indextext{one-definition rule|)} diff --git a/source/expressions.tex b/source/expressions.tex index 7a8ef724ec..227c9d9fbd 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -1514,7 +1514,7 @@ the \grammarterm{unqualified-id}\iref{basic.lookup.unqual}. If the \grammarterm{unqualified-id} appears in a \grammarterm{lambda-expression} at program point $P$ and -the entity is a local entity\iref{basic.pre} or a variable declared by +the entity is a local entity\iref{basic.def.odr} or a variable declared by an \grammarterm{init-capture}\iref{expr.prim.lambda.capture}, then let $S$ be the \grammarterm{compound-statement} of the innermost enclosing \grammarterm{lambda-expression} of $P$. @@ -2391,7 +2391,7 @@ \pnum The \grammarterm{identifier} in a \grammarterm{simple-capture} -shall denote a local entity\iref{basic.lookup.unqual,basic.pre}. +shall denote a local entity\iref{basic.lookup.unqual,basic.def.odr}. The \grammarterm{simple-capture}{s} \keyword{this} and \tcode{* \keyword{this}} denote the local entity \tcode{*\keyword{this}}. An entity that is designated by a diff --git a/source/lex.tex b/source/lex.tex index db46cd0ffe..497aae78ad 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -4305,4 +4305,1897 @@ \end{codeblock} \end{example} \indextext{literal|)}% + +\rSec1[basic.link]{Names and linkage}% +\indextext{linkage|(} + +\pnum +\indextext{type}% +\indextext{object}% +\indextext{storage class}% +\indextext{scope}% +\indextext{linkage}% +A \defn{name} is an \grammarterm{identifier}\iref{lex.name}, +\grammarterm{operator-function-id}\iref{over.oper}, +\grammarterm{literal-operator-id}\iref{over.literal}, or +\grammarterm{conversion-function-id}\iref{class.conv.fct}. + +\pnum +Two names are \defnx{the same}{name!same} if +\begin{itemize} +\item they are \grammarterm{identifier}{s} composed of the same character sequence, or +\item they are \grammarterm{operator-function-id}{s} formed with the same operator, or +\item they are \grammarterm{literal-operator-id}{s} formed with the same +literal suffix identifier, or +\item they are \grammarterm{conversion-function-id}{s} formed with +equivalent\iref{temp.over.link} types. +\end{itemize} + +\pnum +Every name is introduced by a \defn{declaration}, which is a +\begin{itemize} +\item +\grammarterm{name-declaration}, +\grammarterm{block-declaration}, or +\grammarterm{member-declaration}\iref{dcl.pre,class.mem}, +\item +\grammarterm{init-declarator}\iref{dcl.decl}, +\item +\grammarterm{identifier} +in a structured binding declaration\iref{dcl.struct.bind}, +\item +\grammarterm{init-capture}\iref{expr.prim.lambda.capture}, +\item +\grammarterm{condition} with a \grammarterm{declarator}\iref{stmt.pre}, +\item +\grammarterm{member-declarator}\iref{class.mem}, +\item +\grammarterm{using-declarator}\iref{namespace.udecl}, +\item +\grammarterm{parameter-declaration}\iref{dcl.fct}, +\item +\grammarterm{type-parameter}\iref{temp.param}, +\item +\grammarterm{elaborated-type-specifier} +that introduces a name\iref{dcl.type.elab}, +\item +\grammarterm{class-specifier}\iref{class.pre}, +\item +\grammarterm{enum-specifier} or +\grammarterm{enumerator-definition}\iref{dcl.enum}, +\item +\grammarterm{exception-declaration}\iref{except.pre}, or +\item +implicit declaration of an injected-class-name\iref{class.pre}. +\end{itemize} +\begin{note} +The interpretation of a \grammarterm{for-range-declaration} produces +one or more of the above\iref{stmt.ranged}. +\end{note} + +\pnum +An \defn{entity} is a value, object, reference, structured binding, function, +enumerator, type, class member, bit-field, template, template specialization, +namespace, or pack. An entity $E$ is denoted by the name (if any) that is +introduced by a declaration of $E$ or by a \grammarterm{typedef-name} +introduced by a declaration specifying $E$. + +\pnum +Some names denote types or templates. In general, whenever a name is +encountered it is necessary to determine whether that name denotes one of these +entities before continuing to parse the program that contains it. The process +that determines this is called +\defnx{name lookup}{lookup!name}\iref{basic.lookup}. + +\pnum +A \defn{variable} is introduced by the +declaration of +a reference other than a non-static data member or of +an object. The variable's name, if any, denotes the reference or object. + +\pnum +\indextext{translation unit!name and}% +\indextext{linkage}% +A name used in more than one translation unit can potentially +refer to the same entity in these translation units depending on the +linkage\iref{basic.link} of the name specified in each +translation unit. + +\pnum +A name can have +\defnadj{external}{linkage}, +\defnadj{module}{linkage}, +\defnadj{internal}{linkage}, or +\defnadj{no}{linkage}, +as determined by the rules below. +\begin{note} +All declarations of an entity with a name with internal linkage +appear in the same translation unit. +All declarations of an entity with module linkage +are attached to the same module. +\end{note} + +\pnum +\indextext{linkage!\idxcode{static} and}% +\indextext{\idxcode{static}!linkage of}% +\indextext{linkage!\idxcode{const} and}% +\indextext{\idxcode{const}!linkage of}% +\indextext{linkage!\idxcode{inline} and}% +\indextext{\idxcode{inline}!linkage of}% +The name of an entity +that belongs to a namespace scope\iref{basic.scope.namespace} +has internal linkage if it is the name of +\begin{itemize} +\item + a variable, variable template, function, or function template that is + explicitly declared \keyword{static}; or +\item + a non-template variable of non-volatile const-qualified type, unless + \begin{itemize} + \item it is declared in the purview of a module interface unit + (outside the \grammarterm{private-module-fragment}, if any) or + module partition, or + \item it is explicitly declared \keyword{extern}, or + \item it is inline, or + \item it was previously declared and the prior declaration did + not have internal linkage; or + \end{itemize} +\item + a data member of an anonymous union. +\end{itemize} +\begin{note} +An instantiated variable template that has const-qualified type +can have external or module linkage, even if not declared \keyword{extern}. +\end{note} + +\pnum +An unnamed namespace or a namespace declared directly or indirectly within an +unnamed namespace has internal linkage. All other namespaces have external linkage. +The name of an entity that belongs to a namespace scope +that has not been given internal linkage above +and that is the name of +\begin{itemize} +\item a variable; or +\item a function; or +\item +\indextext{class!linkage of}% +a named class\iref{class.pre}, or an unnamed class defined in a +typedef declaration in which the class has the typedef name for linkage +purposes\iref{dcl.typedef}; or +\item +\indextext{enumeration!linkage of}% +a named enumeration\iref{dcl.enum}, or an unnamed enumeration defined +in a typedef declaration in which the enumeration has the typedef name +for linkage purposes\iref{dcl.typedef}; or +\item an unnamed enumeration +that has an enumerator as a name for linkage purposes\iref{dcl.enum}; or +\item a template +\end{itemize} +has its linkage determined as follows: +\begin{itemize} +\item +\indextext{friend function!linkage of}% +if the entity is a function or function template +first declared in a friend declaration and +that declaration is a definition and +the enclosing class is defined within an \grammarterm{export-declaration}, +the name has the same linkage, if any, +as the name of the enclosing class\iref{class.friend}; +\item +otherwise, +\indextext{friend function!linkage of}% +if the entity is a function or function template +declared in a friend declaration and +a corresponding non-friend declaration is reachable, +%FIXME: Which declaration is "that prior declaration"? +%FIXME: "prior" with respect to what? And what about dependent lookup? +the name has the linkage determined from that prior declaration, +\item +otherwise, +if the enclosing namespace has internal linkage, +the name has internal linkage; +\item +otherwise, +if the declaration of the name is +attached to a named module\iref{module.unit} +and is not exported\iref{module.interface}, +the name has module linkage; +\item +otherwise, +the name has external linkage. +\end{itemize} + +\pnum +In addition, +a member function, +a static data member, +a named class or enumeration that inhabits a class scope, or +an unnamed class or enumeration defined in a typedef declaration +that inhabits a class scope +such that the class or enumeration +has the typedef name for linkage purposes\iref{dcl.typedef}, +has the same linkage, if any, as the name of the class of which it is a member. + +\pnum +\begin{example} +\begin{codeblock} +static void f(); +extern "C" void h(); +static int i = 0; // \#1 +void q() { + extern void f(); // internal linkage + extern void g(); // \tcode{::g}, external linkage + extern void h(); // C language linkage + int i; // \#2: \tcode{i} has no linkage + { + extern void f(); // internal linkage + extern int i; // \#3: internal linkage + } +} +\end{codeblock} +Even though the declaration at line \#2 hides the declaration at line \#1, +the declaration at line \#3 still redeclares \#1 and receives internal linkage. +\end{example} + +\pnum +\indextext{linkage!no}% +Names not covered by these rules have no linkage. Moreover, except as +noted, a name declared at block scope\iref{basic.scope.block} has no +linkage. + +\pnum +Two declarations of entities declare the same entity +if, considering declarations of unnamed types to introduce their names +for linkage purposes, if any\iref{dcl.typedef,dcl.enum}, +they correspond\iref{basic.scope.scope}, +have the same target scope that is not a function or template parameter scope, +neither is a name-independent declaration, +and either +\begin{itemize} +\item +they appear in the same translation unit, or +\item +they both declare names with module linkage and are attached to the same module, or +\item +they both declare names with external linkage. +\end{itemize} +\begin{note} +There are other circumstances in which declarations declare the same entity% +\iref{dcl.link,temp.type,temp.spec.partial}. +\end{note} + +\pnum +If a declaration $H$ that declares a name with internal linkage +precedes a declaration $D$ in another translation unit $U$ and +would declare the same entity as $D$ if it appeared in $U$, +the program is ill-formed. +\begin{note} +Such an $H$ can appear only in a header unit. +\end{note} + +\pnum +If two declarations of an entity are +attached to different modules, the program is ill-formed; +no diagnostic is required if neither is reachable from the other. +\begin{example} +\begin{codeblocktu}{\tcode{"decls.h"}} +int f(); // \#1, attached to the global module +int g(); // \#2, attached to the global module +\end{codeblocktu} + +\begin{codeblocktu}{Module interface of \tcode{M}} +module; +#include "decls.h" +export module M; +export using ::f; // OK, does not declare an entity, exports \#1 +int g(); // error: matches \#2, but attached to \tcode{M} +export int h(); // \#3 +export int k(); // \#4 +\end{codeblocktu} + +\begin{codeblocktu}{Other translation unit} +import M; +static int h(); // error: matches \#3 +int k(); // error: matches \#4 +\end{codeblocktu} +\end{example} +As a consequence of these rules, +all declarations of an entity are attached to the same module; +the entity is said to be \defnx{attached}{attached!entity} to that module. + +\pnum +\indextext{consistency!type declaration}% +\indextext{declaration!multiple}% +For any two declarations of an entity $E$: +\begin{itemize} +\item +If one declares $E$ to be a variable or function, +the other shall declare $E$ as one of the same type. +\item +If one declares $E$ to be an enumerator, the other shall do so. +\item +If one declares $E$ to be a namespace, the other shall do so. +\item +If one declares $E$ to be a type, +the other shall declare $E$ to be a type of the same kind\iref{dcl.type.elab}. +\item +If one declares $E$ to be a class template, +the other shall do so with the same kind and +an equivalent \grammarterm{template-head}\iref{temp.over.link}. +\begin{note} +The declarations can supply different default template arguments. +\end{note} +\item +If one declares $E$ to be a function template or +a (partial specialization of a) variable template, +the other shall declare $E$ to be one +with an equivalent \grammarterm{template-head} and type. +\item +If one declares $E$ to be an alias template, +the other shall declare $E$ to be one with +an equivalent \grammarterm{template-head} and \grammarterm{defining-type-id}. +\item +If one declares $E$ to be a concept, the other shall do so. +\end{itemize} +Types are compared after all adjustments of types (during which +typedefs\iref{dcl.typedef} are replaced by their definitions); +declarations for an array +object can specify array types that differ by the presence or absence of +a major array bound\iref{dcl.array}. +No diagnostic is required if neither declaration is reachable from the other. +\begin{example} +\begin{codeblock} +int f(int x, int x); // error: different entities for \tcode{x} +void g(); // \#1 +void g(int); // OK, different entity from \#1 +int g(); // error: same entity as \#1 with different type +void h(); // \#2 +namespace h {} // error: same entity as \#2, but not a function +\end{codeblock} +\end{example} + +\pnum +\begin{note} +Linkage to non-\Cpp{} declarations can be achieved using a +\grammarterm{linkage-specification}\iref{dcl.link}. +\end{note} +\indextext{linkage|)} + +\pnum +A declaration $D$ \defnx{names}{name} an entity $E$ if +\begin{itemize} +\item +$D$ contains a \grammarterm{lambda-expression} whose closure type is $E$, +\item +$E$ is not a function or function template and $D$ contains an +\grammarterm{id-expression}, +\grammarterm{type-specifier}, +\grammarterm{nested-name-specifier}, +\grammarterm{template-name}, or +\grammarterm{concept-name} +denoting $E$, or +\item +$E$ is a function or function template and +$D$ contains an expression that names $E$\iref{basic.def.odr} or +an \grammarterm{id-expression} +that refers to a set of overloads that contains $E$. +\begin{note} +Non-dependent names in an instantiated declaration +do not refer to a set of overloads\iref{temp.res}. +\end{note} +\end{itemize} + +\pnum +A declaration is an \defn{exposure} +if it either names a TU-local entity (defined below), ignoring +\begin{itemize} +\item +the \grammarterm{function-body} +for a non-inline function or function template +(but not the deduced return type +for a (possibly instantiated) definition of a function +with a declared return type that uses a placeholder type\iref{dcl.spec.auto}), +\item +the \grammarterm{initializer} +for a variable or variable template (but not the variable's type), +\item +friend declarations in a class definition, and +\item +any reference to a non-volatile const object or reference +with internal or no linkage initialized with a constant expression +that is not an odr-use\iref{term.odr.use}, +\end{itemize} +or defines a constexpr variable initialized to a TU-local value (defined below). +\begin{note} +An inline function template can be an exposure even though +certain explicit specializations of it would be usable in other translation units. +\end{note} + +\pnum +An entity is \defnx{TU-local}{TU-local!entity} if it is +\begin{itemize} +\item +a type, function, variable, or template that +\begin{itemize} +\item +has a name with internal linkage, or +\item +does not have a name with linkage and is declared, +or introduced by a \grammarterm{lambda-expression}, +within the definition of a TU-local entity, +\end{itemize} +\item +a type with no name that is defined outside a +\grammarterm{class-specifier}, +function body, or +\grammarterm{initializer} +or is introduced by a \grammarterm{defining-type-specifier} +that is used to declare only TU-local entities, +\item +a specialization of a TU-local template, +\item +a specialization of a template with any TU-local template argument, or +\item +a specialization of a template +whose (possibly instantiated) declaration is an exposure. +\begin{note} +A specialization can be produced by implicit or explicit instantiation. +\end{note} +\end{itemize} + +\pnum +A value or object is \defnx{TU-local}{TU-local!value or object} if either +\begin{itemize} +\item +it is, or is a pointer to, +a TU-local function or the object associated with a TU-local variable, or +\item +it is an object of class or array type and +any of its subobjects or +any of the objects or functions +to which its non-static data members of reference type refer +is TU-local and is usable in constant expressions. +\end{itemize} + +\pnum +If a (possibly instantiated) declaration of, or a deduction guide for, +a non-TU-local entity in a module interface unit +(outside the \grammarterm{private-module-fragment}, if any) or +module partition\iref{module.unit} is an exposure, +the program is ill-formed. +Such a declaration in any other context is deprecated\iref{depr.local}. + +\pnum +If a declaration that appears in one translation unit +names a TU-local entity declared +in another translation unit that is not a header unit, +the program is ill-formed. +A declaration instantiated for a template specialization\iref{temp.spec} +appears at the point of instantiation of the specialization\iref{temp.point}. + +\pnum +\begin{example} +\begin{codeblocktu}{Translation unit \#1} +export module A; +static void f() {} +inline void it() { f(); } // error: is an exposure of \tcode{f} +static inline void its() { f(); } // OK +template void g() { its(); } // OK +template void g<0>(); + +decltype(f) *fp; // error: \tcode{f} (though not its type) is TU-local +auto &fr = f; // OK +constexpr auto &fr2 = fr; // error: is an exposure of \tcode{f} +constexpr static auto fp2 = fr; // OK + +struct S { void (&ref)(); } s{f}; // OK, value is TU-local +constexpr extern struct W { S &s; } wrap{s}; // OK, value is not TU-local + +static auto x = []{f();}; // OK +auto x2 = x; // error: the closure type is TU-local +int y = ([]{f();}(),0); // error: the closure type is not TU-local +int y2 = (x,0); // OK + +namespace N { + struct A {}; + void adl(A); + static void adl(int); +} +void adl(double); + +inline void h(auto x) { adl(x); } // OK, but certain specializations are exposures +\end{codeblocktu} +\begin{codeblocktu}{Translation unit \#2} +module A; +void other() { + g<0>(); // OK, specialization is explicitly instantiated + g<1>(); // error: instantiation uses TU-local \tcode{its} + h(N::A{}); // error: overload set contains TU-local \tcode{N::adl(int)} + h(0); // OK, calls \tcode{adl(double)} + adl(N::A{}); // OK; \tcode{N::adl(int)} not found, calls \tcode{N::adl(N::A)} + fr(); // OK, calls \tcode{f} + constexpr auto ptr = fr; // error: \tcode{fr} is not usable in constant expressions here +} +\end{codeblocktu} +\end{example} + +\rSec1[basic.exec]{Program execution} + +\rSec2[intro.execution]{Sequential execution} +\indextext{program execution|(} + +\pnum +An instance of each object with automatic storage +duration\iref{basic.stc.auto} is associated with each entry into its +block. Such an object exists and retains its last-stored value during +the execution of the block and while the block is suspended (by a call +of a function, suspension of a coroutine\iref{expr.await}, or receipt of a signal). + +\pnum +A \defn{constituent expression} is defined as follows: +\begin{itemize} +\item +The constituent expression of an expression is that expression. +\item +The constituent expression of a conversion is +the corresponding implicit function call, if any, or +the converted expression otherwise. +\item +The constituent expressions of a \grammarterm{braced-init-list} or +of a (possibly parenthesized) \grammarterm{expression-list} +are the constituent expressions of the elements of the respective list. +\item +The constituent expressions of a \grammarterm{brace-or-equal-initializer} +of the form \tcode{=}~\grammarterm{initializer-clause} +are the constituent expressions of the \grammarterm{initializer-clause}. +\end{itemize} +\begin{example} +\begin{codeblock} +struct A { int x; }; +struct B { int y; struct A a; }; +B b = { 5, { 1+1 } }; +\end{codeblock} +The constituent expressions of the \grammarterm{initializer} +used for the initialization of \tcode{b} are \tcode{5} and \tcode{1+1}. +\end{example} + +\pnum +The \defnx{immediate subexpressions}{immediate subexpression} of an expression $E$ are +\begin{itemize} +\item +the constituent expressions of $E$'s operands\iref{expr.prop}, +\item +any function call that $E$ implicitly invokes, +\item +if $E$ is a \grammarterm{lambda-expression}\iref{expr.prim.lambda}, +the initialization of the entities captured by copy and +the constituent expressions of the \grammarterm{initializer} of the \grammarterm{init-capture}{s}, +\item +if $E$ is a function call\iref{expr.call} or implicitly invokes a function, +the constituent expressions of each default argument\iref{dcl.fct.default} +used in the call, or +\item +if $E$ creates an aggregate object\iref{dcl.init.aggr}, +the constituent expressions of each default member initializer\iref{class.mem} +used in the initialization. +\end{itemize} + +\pnum +A \defn{subexpression} of an expression $E$ is +an immediate subexpression of $E$ or +a subexpression of an immediate subexpression of $E$. +\begin{note} +Expressions appearing in the \grammarterm{compound-statement} of a \grammarterm{lambda-expression} +are not subexpressions of the \grammarterm{lambda-expression}. +\end{note} +The \defnadjx{potentially-evaluated}{subexpressions}{subexpression} of +an expression, conversion, or \grammarterm{initializer} $E$ are +\begin{itemize} +\item +the constituent expressions of $E$ and +\item +the subexpressions thereof that +are not subexpressions of a nested unevaluated operand\iref{term.unevaluated.operand}. +\end{itemize} + +\pnum +A \defn{full-expression} is +\begin{itemize} +\item +an unevaluated operand\iref{expr.context}, +\item +a \grammarterm{constant-expression}\iref{expr.const}, +\item +an immediate invocation\iref{expr.const}, +\item +an \grammarterm{init-declarator}\iref{dcl.decl} +(including such introduced by a structured binding\iref{dcl.struct.bind}) or +a \grammarterm{mem-initializer}\iref{class.base.init}, +including the constituent expressions of the initializer, +\item +an invocation of a destructor generated at the end of the lifetime +of an object other than a temporary object\iref{class.temporary} +whose lifetime has not been extended, or +\item +an expression that is not a subexpression of another expression and +that is not otherwise part of a full-expression. +\end{itemize} +If a language construct is defined to produce an implicit call of a function, +a use of the language construct is considered to be an expression +for the purposes of this definition. +Conversions applied to the result of an expression in order to satisfy the requirements +of the language construct in which the expression appears +are also considered to be part of the full-expression. +For an initializer, performing the initialization of the entity +(including evaluating default member initializers of an aggregate) +is also considered part of the full-expression. +\begin{example} +\begin{codeblock} +struct S { + S(int i): I(i) { } // full-expression is initialization of \tcode{I} + int& v() { return I; } + ~S() noexcept(false) { } +private: + int I; +}; + +S s1(1); // full-expression comprises call of \tcode{S::S(int)} +void f() { + S s2 = 2; // full-expression comprises call of \tcode{S::S(int)} + if (S(3).v()) // full-expression includes lvalue-to-rvalue and \tcode{int} to \tcode{bool} conversions, + // performed before temporary is deleted at end of full-expression + { } + bool b = noexcept(S(4)); // exception specification of destructor of \tcode{S} considered for \keyword{noexcept} + + // full-expression is destruction of \tcode{s2} at end of block +} +struct B { + B(S = S(0)); +}; +B b[2] = { B(), B() }; // full-expression is the entire initialization + // including the destruction of temporaries +\end{codeblock} +\end{example} + +\pnum +\begin{note} +The evaluation of a full-expression can include the +evaluation of subexpressions that are not lexically part of the +full-expression. For example, subexpressions involved in evaluating +default arguments\iref{dcl.fct.default} are considered to +be created in the expression that calls the function, not the expression +that defines the default argument. +\end{note} + +\pnum +\indextext{value computation|(}% +Reading an object designated by a \keyword{volatile} +glvalue\iref{basic.lval}, modifying an object, calling a library I/O +function, or calling a function that does any of those operations are +all +\defn{side effects}, which are changes in the state of the execution +environment. \defnx{Evaluation}{evaluation} 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 volatile 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 \keyword{volatile} access +may not have completed yet. + +\pnum +\defnx{Sequenced before}{sequenced before} is an asymmetric, transitive, pair-wise relation between +evaluations executed by a single thread\iref{intro.multithread}, which induces +a partial order among those evaluations. Given any two evaluations \placeholder{A} and +\placeholder{B}, if \placeholder{A} is sequenced before \placeholder{B} +(or, equivalently, \placeholder{B} is \defn{sequenced after} \placeholder{A}), +then the execution of +\placeholder{A} shall precede the execution of \placeholder{B}. If \placeholder{A} is not sequenced +before \placeholder{B} and \placeholder{B} is not sequenced before \placeholder{A}, then \placeholder{A} and +\placeholder{B} are \defn{unsequenced}. +\begin{note} +The execution of unsequenced +evaluations can overlap. +\end{note} +Evaluations \placeholder{A} and \placeholder{B} are +\defn{indeterminately sequenced} when either \placeholder{A} is sequenced before +\placeholder{B} or \placeholder{B} is sequenced before \placeholder{A}, but it is unspecified which. +\begin{note} +Indeterminately sequenced evaluations cannot overlap, but either +can be executed first. +\end{note} +An expression \placeholder{X} +is said to be sequenced before +an expression \placeholder{Y} if +every value computation and every side effect +associated with the expression \placeholder{X} +is sequenced before +every value computation and every side effect +associated with the expression \placeholder{Y}. + +\pnum +Every +\indextext{value computation}% +value computation and +\indextext{side effects}% +side effect associated with a full-expression is +sequenced before every value computation and side effect associated with the +next full-expression to be evaluated. +\begin{footnote} +As specified +in~\ref{class.temporary}, after a full-expression is evaluated, a sequence of +zero or more invocations of destructor functions for temporary objects takes +place, usually in reverse order of the construction of each temporary object. +\end{footnote} + +\pnum +\indextext{evaluation!unspecified order of}% +Except where noted, evaluations of operands of individual operators and +of subexpressions of individual expressions are unsequenced. +\begin{note} +In an expression that is evaluated more than once during the execution +of a program, unsequenced and indeterminately sequenced evaluations of +its subexpressions need not be performed consistently in different +evaluations. +\end{note} +The value computations of the operands of an +operator are sequenced before the value computation of the result of the +operator. If a +\indextext{side effects}% +side effect on a memory location\iref{intro.memory} is unsequenced +relative to either another side effect on the same memory location or +a value computation using the value of any object in the same memory location, +and they are not potentially concurrent\iref{intro.multithread}, +the behavior is undefined. +\begin{note} +The next subclause imposes similar, but more complex restrictions on +potentially concurrent computations. +\end{note} + +\begin{example} +\begin{codeblock} +void g(int i) { + i = 7, i++, i++; // \tcode{i} becomes \tcode{9} + + i = i++ + 1; // the value of \tcode{i} is incremented + i = i++ + i; // undefined behavior + i = i + 1; // the value of \tcode{i} is incremented +} +\end{codeblock} +\end{example} + +\pnum +When invoking a function (whether or not the function is inline), +every argument expression and +the postfix expression designating the called function +are sequenced before every expression or statement +in the body of the called function. +For each function invocation or +evaluation of an \grammarterm{await-expression} \placeholder{F}, +each evaluation that does not occur within \placeholder{F} but +is evaluated on the same thread and as part of the same signal handler (if any) +is either sequenced before all evaluations that occur within \placeholder{F} +or sequenced after all evaluations that occur within \placeholder{F}; +\begin{footnote} +In other words, +function executions do not interleave with each other. +\end{footnote} +if \placeholder{F} invokes or resumes a coroutine\iref{expr.await}, +only evaluations +subsequent to the previous suspension (if any) and +prior to the next suspension (if any) +are considered to occur within \placeholder{F}. + +Several contexts in \Cpp{} cause evaluation of a function call, even +though no corresponding function call syntax appears in the translation +unit. +\begin{example} +Evaluation of a \grammarterm{new-expression} invokes one or more allocation +and constructor functions; see~\ref{expr.new}. For another example, +invocation of a conversion function\iref{class.conv.fct} can arise in +contexts in which no function call syntax appears. +\end{example} +The sequencing constraints on the execution of the called function (as +described above) are features of the function calls as evaluated, +regardless of the syntax of the expression that calls the function.% +\indextext{value computation|)}% + +\indextext{behavior!on receipt of signal}% +\indextext{signal}% +\pnum +If a signal handler is executed as a result of a call to the \tcode{std::raise} +function, then the execution of the handler is sequenced after the invocation +of the \tcode{std::raise} function and before its return. +\begin{note} +When a signal is received for another reason, the execution of the +signal handler is usually unsequenced with respect to the rest of the program. +\end{note} + +\rSec2[intro.multithread]{Multi-threaded executions and data races} + +\rSec3[intro.multithread.general]{General} + +\pnum +\indextext{threads!multiple|(}% +\indextext{atomic!operation|(}% +A \defn{thread of execution} (also known as a \defn{thread}) is a single flow of +control within a program, including the initial invocation of a specific +top-level function, and recursively including every function invocation +subsequently executed by the thread. +\begin{note} +When one thread creates another, +the initial call to the top-level function of the new thread is executed by the +new thread, not by the creating thread. +\end{note} +Every thread in a program can +potentially access every object and function in a program. +\begin{footnote} +An object +with automatic or thread storage duration\iref{basic.stc} is associated with +one specific thread, and can be accessed by a different thread only indirectly +through a pointer or reference\iref{basic.compound}. +\end{footnote} +Under a hosted +implementation, a \Cpp{} program can have more than one thread running +concurrently. The execution of each thread proceeds as defined by the remainder +of this document. The execution of the entire program consists of an execution +of all of its threads. +\begin{note} +Usually the execution can be viewed as an +interleaving of all its threads. However, some kinds of atomic operations, for +example, allow executions inconsistent with a simple interleaving, as described +below. +\end{note} +\indextext{implementation!freestanding}% +Under a freestanding implementation, it is \impldef{number of +threads in a program under a freestanding implementation} whether a program can +have more than one thread of execution. + +\pnum +For a signal handler that is not executed as a result of a call to the +\tcode{std::raise} function, it is unspecified which thread of execution +contains the signal handler invocation. + +\rSec3[intro.races]{Data races} + +\pnum +The value of an object visible to a thread $T$ at a particular point is the +initial value of the object, a value assigned to the object by $T$, or a +value assigned to the object by another thread, according to the rules below. +\begin{note} +In some cases, there might instead be undefined behavior. Much of this +subclause is motivated by the desire to support atomic operations with explicit +and detailed visibility constraints. However, it also implicitly supports a +simpler view for more restricted programs. +\end{note} + +\pnum +Two expression evaluations \defn{conflict} if one of them modifies a memory +location\iref{intro.memory} and the other one reads or modifies the same +memory location. + +\pnum +The library defines a number of atomic operations\iref{atomics} and +operations on mutexes\iref{thread} that are specially identified as +synchronization operations. These operations play a special role in making +assignments in one thread visible to another. A synchronization operation on one +or more memory locations is either a consume operation, an acquire operation, a +release operation, or both an acquire and release operation. A synchronization +operation without an associated memory location is a fence and can be either an +acquire fence, a release fence, or both an acquire and release fence. In +addition, there are relaxed atomic operations, which are not synchronization +operations, and atomic read-modify-write operations, which have special +characteristics. +\begin{note} +For example, a call that acquires a mutex will +perform an acquire operation on the locations comprising the mutex. +Correspondingly, a call that releases the same mutex will perform a release +operation on those same locations. Informally, performing a release operation on +$A$ forces prior +\indextext{side effects}% +side effects on other memory locations to become visible +to other threads that later perform a consume or an acquire operation on +$A$. ``Relaxed'' atomic operations are not synchronization operations even +though, like synchronization operations, they cannot contribute to data races. +\end{note} + +\pnum +All modifications to a particular atomic object $M$ occur in some +particular total order, called the \defn{modification order} of $M$. +\begin{note} +There is a separate order for each +atomic object. There is no requirement that these can be combined into a single +total order for all objects. In general this will be impossible since different +threads can observe modifications to different objects in inconsistent orders. +\end{note} + +\pnum +A \defn{release sequence} headed +by a release operation $A$ on an atomic object $M$ +is a maximal contiguous sub-sequence of +\indextext{side effects}% +side effects in the modification order of $M$, +where the first operation is $A$, and +every subsequent operation is an atomic read-modify-write operation. + +\pnum +Certain library calls \defn{synchronize with} other library calls performed by +another thread. For example, an atomic store-release synchronizes with a +load-acquire that takes its value from the store\iref{atomics.order}. +\begin{note} +Except in the specified cases, reading a later value does not +necessarily ensure visibility as described below. Such a requirement would +sometimes interfere with efficient implementation. +\end{note} +\begin{note} +The +specifications of the synchronization operations define when one reads the value +written by another. For atomic objects, the definition is clear. All operations +on a given mutex occur in a single total order. Each mutex acquisition ``reads +the value written'' by the last mutex release. +\end{note} + +\pnum +An evaluation $A$ \defn{carries a dependency} to an evaluation $B$ if +\begin{itemize} +\item +the value of $A$ is used as an operand of $B$, unless: +\begin{itemize} +\item +$B$ is an invocation of any specialization of +\tcode{std::kill_dependency}\iref{atomics.order}, or +\item +$A$ is the left operand of a built-in logical \logop{and} (\tcode{\&\&}, +see~\ref{expr.log.and}) or logical \logop{or} (\tcode{||}, see~\ref{expr.log.or}) +operator, or +\item +$A$ is the left operand of a conditional (\tcode{?:}, see~\ref{expr.cond}) +operator, or +\item +$A$ is the left operand of the built-in comma (\tcode{,}) +operator\iref{expr.comma}; \end{itemize} or +\item +$A$ writes a scalar object or bit-field $M$, $B$ reads the value +written by $A$ from $M$, and $A$ is sequenced before $B$, or +\item +for some evaluation $X$, $A$ carries a dependency to $X$, and +$X$ carries a dependency to $B$. +\end{itemize} +\begin{note} +``Carries a dependency to'' is a subset of ``is sequenced before'', +and is similarly strictly intra-thread. +\end{note} + +\pnum +An evaluation $A$ is \defn{dependency-ordered before} an evaluation +$B$ if +\begin{itemize} +\item +$A$ performs a release operation on an atomic object $M$, and, in +another thread, $B$ performs a consume operation on $M$ and reads +the value written by $A$, or + +\item +for some evaluation $X$, $A$ is dependency-ordered before $X$ and +$X$ carries a dependency to $B$. + +\end{itemize} +\begin{note} +The relation ``is dependency-ordered before'' is analogous to +``synchronizes with'', but uses release/consume in place of release/acquire. +\end{note} + +\pnum +An evaluation $A$ \defn{inter-thread happens before} an evaluation $B$ +if +\begin{itemize} +\item + $A$ synchronizes with $B$, or +\item + $A$ is dependency-ordered before $B$, or +\item + for some evaluation $X$ + \begin{itemize} + \item + $A$ synchronizes with $X$ and $X$ + is sequenced before $B$, or + \item + $A$ is sequenced before $X$ and $X$ + inter-thread happens before $B$, or + \item + $A$ inter-thread happens before $X$ and $X$ + inter-thread happens before $B$. + \end{itemize} +\end{itemize} +\begin{note} +The ``inter-thread happens before'' relation describes arbitrary +concatenations of ``sequenced before'', ``synchronizes with'' and +``dependency-ordered before'' relationships, with two exceptions. The first +exception is that a concatenation never ends with +``dependency-ordered before'' followed by ``sequenced before''. The reason for +this limitation is that a consume operation participating in a +``dependency-ordered before'' relationship provides ordering only with respect +to operations to which this consume operation actually carries a dependency. The +reason that this limitation applies only to the end of such a concatenation is +that any subsequent release operation will provide the required ordering for a +prior consume operation. The second exception is that a concatenation never +consist entirely of ``sequenced before''. The reasons for this +limitation are (1) to permit ``inter-thread happens before'' to be transitively +closed and (2) the ``happens before'' relation, defined below, provides for +relationships consisting entirely of ``sequenced before''. +\end{note} + +\pnum +An evaluation $A$ \defn{happens before} an evaluation $B$ +(or, equivalently, $B$ \defn{happens after} $A$) if +\begin{itemize} +\item $A$ is sequenced before $B$, or +\item $A$ inter-thread happens before $B$. +\end{itemize} +The implementation shall ensure that no program execution demonstrates a cycle +in the ``happens before'' relation. +\begin{note} +This cycle would otherwise be +possible only through the use of consume operations. +\end{note} + +\pnum +An evaluation $A$ \defn{simply happens before} an evaluation $B$ +if either +\begin{itemize} +\item $A$ is sequenced before $B$, or +\item $A$ synchronizes with $B$, or +\item $A$ simply happens before $X$ and +$X$ simply happens before $B$. +\end{itemize} +\begin{note} +In the absence of consume operations, +the happens before and simply happens before relations are identical. +\end{note} + +\pnum +An evaluation $A$ \defn{strongly happens before} +an evaluation $D$ if, either +\begin{itemize} +\item $A$ is sequenced before $D$, or +\item $A$ synchronizes with $D$, and +both $A$ and $D$ are +sequentially consistent atomic operations\iref{atomics.order}, or +\item there are evaluations $B$ and $C$ +such that $A$ is sequenced before $B$, +$B$ simply happens before $C$, and +$C$ is sequenced before $D$, or +\item there is an evaluation $B$ such that +$A$ strongly happens before $B$, and +$B$ strongly happens before $D$. +\end{itemize} +\begin{note} +Informally, if $A$ strongly happens before $B$, +then $A$ appears to be evaluated before $B$ +in all contexts. Strongly happens before excludes consume operations. +\end{note} + +\pnum +A \defnadjx{visible}{side effect}{side effects} $A$ on a scalar object or bit-field $M$ +with respect to a value computation $B$ of $M$ satisfies the +conditions: +\begin{itemize} +\item $A$ happens before $B$ and +\item there is no other +\indextext{side effects}% +side effect $X$ to $M$ such that $A$ +happens before $X$ and $X$ happens before $B$. +\end{itemize} + +The value of a non-atomic scalar object or bit-field $M$, as determined by +evaluation $B$, is the value stored by the +\indextext{side effects!visible}% +visible side effect $A$. +\begin{note} +If there is ambiguity about which side effect to a +non-atomic object or bit-field is visible, then the behavior is either +unspecified or undefined. +\end{note} +\begin{note} +This states that operations on +ordinary objects are not visibly reordered. This is not actually detectable +without data races, but is needed to ensure that data races, as defined +below, and with suitable restrictions on the use of atomics, correspond to data +races in a simple interleaved (sequentially consistent) execution. +\end{note} + +\pnum +The value of an +atomic object $M$, as determined by evaluation $B$, is the value +stored by some unspecified +side effect $A$ that modifies $M$, where $B$ does not happen +before $A$. +\begin{note} +The set of such side effects is also restricted by the rest of the rules +described here, and in particular, by the coherence requirements below. +\end{note} + +\pnum +\indextext{coherence!write-write}% +If an operation $A$ that modifies an atomic object $M$ happens before +an operation $B$ that modifies $M$, then $A$ is earlier +than $B$ in the modification order of $M$. +\begin{note} +This requirement is known as write-write coherence. +\end{note} + +\pnum +\indextext{coherence!read-read}% +If a +\indextext{value computation}% +value computation $A$ of an atomic object $M$ happens before a +value computation $B$ of $M$, and $A$ takes its value from a side +effect $X$ on $M$, then the value computed by $B$ is either +the value stored by $X$ or the value stored by a +\indextext{side effects}% +side effect $Y$ on $M$, +where $Y$ follows $X$ in the modification order of $M$. +\begin{note} +This requirement is known as read-read coherence. +\end{note} + +\pnum +\indextext{coherence!read-write}% +If a +\indextext{value computation}% +value computation $A$ of an atomic object $M$ happens before an +operation $B$ that modifies $M$, then $A$ takes its value from a side +effect $X$ on $M$, where $X$ precedes $B$ in the +modification order of $M$. +\begin{note} +This requirement is known as +read-write coherence. +\end{note} + +\pnum +\indextext{coherence!write-read}% +If a +\indextext{side effects}% +side effect $X$ on an atomic object $M$ happens before a value +computation $B$ of $M$, then the evaluation $B$ takes its +value from $X$ or from a +\indextext{side effects}% +side effect $Y$ that follows $X$ in the modification order of $M$. +\begin{note} +This requirement is known as write-read coherence. +\end{note} + +\pnum +\begin{note} +The four preceding coherence requirements effectively disallow +compiler reordering of atomic operations to a single object, even if both +operations are relaxed loads. This effectively makes the cache coherence +guarantee provided by most hardware available to \Cpp{} atomic operations. +\end{note} + +\pnum +\begin{note} +The value observed by a load of an atomic depends on the ``happens +before'' relation, which depends on the values observed by loads of atomics. +The intended reading is that there must exist an +association of atomic loads with modifications they observe that, together with +suitably chosen modification orders and the ``happens before'' relation derived +as described above, satisfy the resulting constraints as imposed here. +\end{note} + +\pnum +Two actions are \defn{potentially concurrent} if +\begin{itemize} +\item they are performed by different threads, or +\item they are unsequenced, at least one is performed by a signal handler, and +they are not both performed by the same signal handler invocation. +\end{itemize} +The execution of a program contains a \defn{data race} if it contains two +potentially concurrent conflicting actions, at least one of which is not atomic, +and neither happens before the other, +except for the special case for signal handlers described below. +Any such data race results in undefined +behavior. +\begin{note} +It can be shown that programs that correctly use mutexes +and \tcode{memory_order::seq_cst} operations to prevent all data races and use no +other synchronization operations behave as if the operations executed by their +constituent threads were simply interleaved, with each +\indextext{value computation}% +value computation of an +object being taken from the last +\indextext{side effects}% +side effect on that object in that +interleaving. This is normally referred to as ``sequential consistency''. +However, this applies only to data-race-free programs, and data-race-free +programs cannot observe most program transformations that do not change +single-threaded program semantics. In fact, most single-threaded program +transformations remain possible, since any program that behaves +differently as a result has undefined behavior. +\end{note} + +\pnum +Two accesses to the same object of type \tcode{\keyword{volatile} std::sig_atomic_t} 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 \tcode{\keyword{volatile} std::sig_atomic_t} 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$. + +\pnum +\begin{note} +Compiler transformations that introduce assignments to a potentially +shared memory location that would not be modified by the abstract machine are +generally precluded by this document, since such an assignment might overwrite +another assignment by a different thread in cases in which an abstract machine +execution would not have encountered a data race. This includes implementations +of data member assignment that overwrite adjacent members in separate memory +locations. Reordering of atomic loads in cases in which the atomics in question +might alias is also generally precluded, since this could violate the coherence +rules. +\end{note} + +\pnum +\begin{note} +It is possible that transformations that introduce a speculative read of a potentially +shared memory location do not preserve the semantics of the \Cpp{} program as +defined in this document, since they potentially introduce a data race. However, +they are typically valid in the context of an optimizing compiler that targets a +specific machine with well-defined semantics for data races. They would be +invalid for a hypothetical machine that is not tolerant of races or provides +hardware race detection. +\end{note} + +\rSec3[intro.progress]{Forward progress} + +\pnum +The implementation may assume that any thread will eventually do one of the +following: +\begin{itemize} +\item terminate, +\item invoke the function \tcode{std::this_thread::yield}\iref{thread.thread.this}, +\item make a call to a library I/O function, +\item perform an access through a volatile glvalue, +\item perform a synchronization operation or an atomic operation, or +\item continue execution of a trivial infinite loop\iref{stmt.iter.general}. +\end{itemize} +\begin{note} +This is intended to allow compiler transformations +such as removal, merging, and reordering of empty loops, +even when termination cannot be proven. +An affordance is made for trivial infinite loops, +which cannot be removed nor reordered. +\end{note} + +\pnum +Executions of atomic functions +that are either defined to be lock-free\iref{atomics.flag} +or indicated as lock-free\iref{atomics.lockfree} +are \defnx{lock-free executions}{lock-free execution}. +\begin{itemize} +\item + If there is only one thread that is not blocked\iref{defns.block} + in a standard library function, + a lock-free execution in that thread shall complete. + \begin{note} + Concurrently executing threads + might prevent progress of a lock-free execution. + For example, + this situation can occur + with load-locked store-conditional implementations. + This property is sometimes termed obstruction-free. + \end{note} +\item + When one or more lock-free executions run concurrently, + at least one should complete. + \begin{note} + It is difficult for some implementations + to provide absolute guarantees to this effect, + since repeated and particularly inopportune interference + from other threads + could prevent forward progress, + e.g., + by repeatedly stealing a cache line + for unrelated purposes + between load-locked and store-conditional instructions. + For implementations that follow this recommendation and + ensure that such effects cannot indefinitely delay progress + under expected operating conditions, + such anomalies + can therefore safely be ignored by programmers. + Outside this document, + this property is sometimes termed lock-free. + \end{note} +\end{itemize} + +\pnum +During the execution of a thread of execution, each of the following is termed +an \defn{execution step}: +\begin{itemize} +\item termination of the thread of execution, +\item performing an access through a volatile glvalue, or +\item completion of a call to a library I/O function, a + synchronization operation, or an atomic operation. +\end{itemize} + +\pnum +An invocation of a standard library function that blocks\iref{defns.block} +is considered to continuously execute execution steps while waiting for the +condition that it blocks on to be satisfied. +\begin{example} +A library I/O function that blocks until the I/O operation is complete can +be considered to continuously check whether the operation is complete. Each +such check consists of one or more execution steps, for example using +observable behavior of the abstract machine. +\end{example} + +\pnum +\begin{note} +Because of this and the preceding requirement regarding what threads of execution +have to perform eventually, it follows that no thread of execution can execute +forever without an execution step occurring. +\end{note} + +\pnum +A thread of execution \defnx{makes progress}{make progress!thread} +when an execution step occurs or a +lock-free execution does not complete because there are other concurrent threads +that are not blocked in a standard library function (see above). + +\pnum +\indextext{forward progress guarantees!concurrent}% +For a thread of execution providing \defn{concurrent forward progress guarantees}, +the implementation ensures that the thread will eventually make progress for as +long as it has not terminated. +\begin{note} +This applies regardless of whether or not other threads of execution (if any) +have been or are making progress. To eventually fulfill this requirement means that +this will happen in an unspecified but finite amount of time. +\end{note} + +\pnum +It is \impldef{whether the thread that executes \tcode{main} and the threads created +by \tcode{std::thread} or \tcode{std::jthread} provide concurrent forward progress guarantees} whether the +implementation-created thread of execution that executes +\tcode{main}\iref{basic.start.main} and the threads of execution created by +\tcode{std::thread}\iref{thread.thread.class} +or \tcode{std::jthread}\iref{thread.jthread.class} +provide concurrent forward progress guarantees. +General-purpose implementations should provide these guarantees. + +\pnum +\indextext{forward progress guarantees!parallel}% +For a thread of execution providing \defn{parallel forward progress guarantees}, +the implementation is not required to ensure that the thread will eventually make +progress if it has not yet executed any execution step; once this thread has +executed a step, it provides concurrent forward progress guarantees. + +\pnum +\begin{note} +This does not specify a requirement for when to start this thread of execution, +which will typically be specified by the entity that creates this thread of +execution. For example, a thread of execution that provides concurrent forward +progress guarantees and executes tasks from a set of tasks in an arbitrary order, +one after the other, satisfies the requirements of parallel forward progress for +these tasks. +\end{note} + +\pnum +\indextext{forward progress guarantees!weakly parallel}% +For a thread of execution providing \defn{weakly parallel forward progress +guarantees}, the implementation does not ensure that the thread will eventually +make progress. + +\pnum +\begin{note} +Threads of execution providing weakly parallel forward progress guarantees cannot +be expected to make progress regardless of whether other threads make progress or +not; however, blocking with forward progress guarantee delegation, as defined below, +can be used to ensure that such threads of execution make progress eventually. +\end{note} + +\pnum +Concurrent forward progress guarantees are stronger than parallel forward progress +guarantees, which in turn are stronger than weakly parallel forward progress +guarantees. +\begin{note} +For example, some kinds of synchronization between threads of execution might only +make progress if the respective threads of execution provide parallel forward progress +guarantees, but will fail to make progress under weakly parallel guarantees. +\end{note} + +\pnum +\indextext{forward progress guarantees!delegation of}% +When a thread of execution $P$ is specified to +\defnx{block with forward progress guarantee delegation} +{block (execution)!with forward progress guarantee delegation} +on the completion of a set $S$ of threads of execution, +then throughout the whole time of $P$ being blocked on $S$, +the implementation shall ensure that the forward progress guarantees +provided by at least one thread of execution in $S$ +is at least as strong as $P$'s forward progress guarantees. +\begin{note} +It is unspecified which thread or threads of execution in $S$ are chosen +and for which number of execution steps. The strengthening is not permanent and +not necessarily in place for the rest of the lifetime of the affected thread of +execution. As long as $P$ is blocked, the implementation has to eventually +select and potentially strengthen a thread of execution in $S$. +\end{note} +Once a thread of execution in $S$ terminates, it is removed from $S$. +Once $S$ is empty, $P$ is unblocked. + +\pnum +\begin{note} +A thread of execution $B$ thus can temporarily provide an effectively +stronger forward progress guarantee for a certain amount of time, due to a +second thread of execution $A$ being blocked on it with forward +progress guarantee delegation. In turn, if $B$ then blocks with +forward progress guarantee delegation on $C$, this can also temporarily +provide a stronger forward progress guarantee to $C$. +\end{note} + +\pnum +\begin{note} +If all threads of execution in $S$ finish executing (e.g., they terminate +and do not use blocking synchronization incorrectly), then $P$'s execution +of the operation that blocks with forward progress guarantee delegation will not +result in $P$'s progress guarantee being effectively weakened. +\end{note} + +\pnum +\begin{note} +This does not remove any constraints regarding blocking synchronization for +threads of execution providing parallel or weakly parallel forward progress +guarantees because the implementation is not required to strengthen a particular +thread of execution whose too-weak progress guarantee is preventing overall progress. +\end{note} + +\pnum +An implementation should ensure that the last value (in modification order) +assigned by an atomic or synchronization operation will become visible to all +other threads in a finite period of time.% +\indextext{atomic!operation|)}% +\indextext{threads!multiple|)} + +\rSec2[basic.start]{Start and termination} + +\rSec3[basic.start.main]{\tcode{main} function} +\indextext{\idxcode{main} function|(} + +\pnum +\indextext{program!startup|(}% +A program shall contain exactly one function called \tcode{main} +that belongs to the global scope. +Executing a program starts a main thread of execution\iref{intro.multithread,thread.threads} +in which the \tcode{main} function is invoked. +\indextext{implementation!freestanding}% +It is \impldef{defining \tcode{main} in freestanding environment} +whether a program in a freestanding environment is required to define a \tcode{main} +function. +\begin{note} +In a freestanding environment, startup and termination is +\impldef{startup and termination in freestanding environment}; startup contains the +execution of constructors for non-local objects with static storage duration; +termination contains the execution of destructors for objects with static storage +duration. +\end{note} + +\pnum +An implementation shall not predefine the \tcode{main} function. +Its type shall have \Cpp{} language linkage +and it shall have a declared return type of type +\keyword{int}, but otherwise its type is \impldef{parameters to \tcode{main}}. +\indextext{\idxcode{main} function!implementation-defined parameters to}% +An implementation shall allow both +\begin{itemize} +\item a function of \tcode{()} returning \keyword{int} and +\item a function of \tcode{(\keyword{int}}, pointer to pointer to \tcode{\keyword{char})} returning \keyword{int} +\end{itemize} +\indextext{\idxcode{argc}}% +\indextext{\idxcode{argv}}% +as the type of \tcode{main}\iref{dcl.fct}. +\indextext{\idxcode{main} function!parameters to}% +\indextext{environment!program}% +In the latter form, for purposes of exposition, the first function +parameter is called \tcode{argc} and the second function parameter is +called \tcode{argv}, where \tcode{argc} shall be the number of +arguments passed to the program from the environment in which the +program is run. If +\tcode{argc} is nonzero these arguments shall be supplied in +\tcode{argv[0]} through \tcode{argv[argc-1]} as pointers to the initial +characters of null-terminated multibyte strings (\ntmbs{}s)\iref{multibyte.strings} +and \tcode{argv[0]} shall be the pointer to +the initial character of an \ntmbs{} that represents the name used to +invoke the program or \tcode{""}. The value of \tcode{argc} shall be +non-negative. The value of \tcode{argv[argc]} shall be 0. + +\recommended +Any further (optional) parameters should be added after \tcode{argv}. + +\pnum +The function \tcode{main} shall not be named by an expression. +\indextext{\idxcode{main} function!implementation-defined linkage of}% +The linkage\iref{basic.link} of \tcode{main} is +\impldef{linkage of \tcode{main}}. A program that defines \tcode{main} as +deleted or that declares \tcode{main} to be +\keyword{inline}, \keyword{static}, \keyword{constexpr}, or \keyword{consteval} is ill-formed. +The function \tcode{main} shall not be a coroutine\iref{dcl.fct.def.coroutine}. +The \tcode{main} function shall not be declared with a +\grammarterm{linkage-specification}\iref{dcl.link}. +A program that declares +\begin{itemize} +\item +a variable \tcode{main} that belongs to the global scope, or +\item +a function \tcode{main} that belongs to the global scope and +is attached to a named module, or +\item +a function template \tcode{main} that belongs to the global scope, or +\item +an entity named \tcode{main} +with C language linkage (in any namespace) +\end{itemize} +is ill-formed. +The name \tcode{main} is +not otherwise reserved. +\begin{example} +Member functions, classes, and +enumerations can be called \tcode{main}, as can entities in other +namespaces. +\end{example} + +\pnum +\indextext{\idxcode{exit}}% +\indexlibraryglobal{exit}% +\indextext{termination!program}% +Terminating the program +without leaving the current block (e.g., by calling the function +\tcode{std::exit(int)}\iref{support.start.term}) does not destroy any +objects with automatic storage duration\iref{class.dtor}. If +\tcode{std::exit} is invoked during the destruction of +an object with static or thread storage duration, the program has undefined +behavior. + +\pnum +\indextext{termination!program}% +\indextext{\idxcode{main} function!return from}% +A \keyword{return} statement\iref{stmt.return} in \tcode{main} has the effect of leaving the main +function (destroying any objects with automatic storage duration) and +calling \tcode{std::exit} with the return value as the argument. +If control flows off the end of +the \grammarterm{compound-statement} of \tcode{main}, +the effect is equivalent to a \keyword{return} with operand \tcode{0} +(see also \ref{except.handle}). +\indextext{\idxcode{main} function|)} + +\rSec3[basic.start.static]{Static initialization} + +\pnum +\indextext{initialization}% +\indextext{initialization!static and thread}% +Variables with static storage duration +are initialized as a consequence of program initiation. Variables with +thread storage duration are initialized as a consequence of thread execution. +Within each of these phases of initiation, initialization occurs as follows. + +\pnum +\indextext{initialization!constant}% +\defnx{Constant initialization}{constant initialization} is performed +if a variable or temporary object with static or thread storage duration +is constant-initialized\iref{expr.const}. +\indextext{initialization!zero-initialization}% +If constant initialization is not performed, a variable with static +storage duration\iref{basic.stc.static} or thread storage +duration\iref{basic.stc.thread} is zero-initialized\iref{dcl.init}. +Together, zero-initialization and constant initialization are called +\defnadj{static}{initialization}; +all other initialization is \defnadj{dynamic}{initialization}. +All static initialization strongly happens before\iref{intro.races} +any dynamic initialization. +\begin{note} +The dynamic initialization of non-block variables is described +in~\ref{basic.start.dynamic}; that of static block variables is described +in~\ref{stmt.dcl}. +\end{note} + +\pnum +An implementation is permitted to perform the initialization of a +variable with static or thread storage duration as a static +initialization even if such initialization is not required to be done +statically, provided that +\begin{itemize} +\item +the dynamic version of the initialization does not change the +value of any other object of static or thread storage duration +prior to its initialization, and + +\item +the static version of the initialization produces the same value +in the initialized variable as would be produced by the dynamic +initialization if all variables not required to be initialized statically +were initialized dynamically. +\end{itemize} +\begin{note} +As a consequence, if the initialization of an object \tcode{obj1} refers to an +object \tcode{obj2} potentially requiring dynamic initialization and defined +later in the same translation unit, it is unspecified whether the value of \tcode{obj2} used +will be the value of the fully initialized \tcode{obj2} (because \tcode{obj2} was statically +initialized) or will be the value of \tcode{obj2} merely zero-initialized. For example, +\begin{codeblock} +inline double fd() { return 1.0; } +extern double d1; +double d2 = d1; // unspecified: + // either statically initialized to \tcode{0.0} or + // dynamically initialized to \tcode{0.0} if \tcode{d1} is + // dynamically initialized, or \tcode{1.0} otherwise +double d1 = fd(); // either initialized statically or dynamically to \tcode{1.0} +\end{codeblock} +\end{note} + +\rSec3[basic.start.dynamic]{Dynamic initialization of non-block variables} + +\pnum +\indextext{initialization!dynamic non-block}% +\indextext{start!program}% +\indextext{initialization!order of}% +Dynamic initialization of a non-block variable with static storage duration is +unordered if the variable is an implicitly or explicitly instantiated +specialization, is partially-ordered if the variable +is an inline variable that is not an implicitly or explicitly instantiated +specialization, and otherwise is ordered. +\begin{note} +A non-inline explicit specialization of a templated variable +has ordered initialization. +\end{note} + +\pnum +A declaration \tcode{D} is +\defn{appearance-ordered} before a declaration \tcode{E} if +\begin{itemize} +\item \tcode{D} appears in the same translation unit as \tcode{E}, or +\item the translation unit containing \tcode{E} +has an interface dependency on the translation unit containing \tcode{D}, +\end{itemize} +in either case prior to \tcode{E}. + +\pnum +Dynamic initialization of non-block variables \tcode{V} and \tcode{W} +with static storage duration are ordered as follows: +\begin{itemize} +\item +If \tcode{V} and \tcode{W} have ordered initialization and +the definition of \tcode{V} +is appearance-ordered before the definition of \tcode{W}, or +if \tcode{V} has partially-ordered initialization, +\tcode{W} does not have unordered initialization, and +for every definition \tcode{E} of \tcode{W} +there exists a definition \tcode{D} of \tcode{V} +such that \tcode{D} is appearance-ordered before \tcode{E}, then +\begin{itemize} +\item +if the program does not start a thread\iref{intro.multithread} +other than the main thread\iref{basic.start.main} +or \tcode{V} and \tcode{W} have ordered initialization and +they are defined in the same translation unit, +the initialization of \tcode{V} +is sequenced before +the initialization of \tcode{W}; +\item +otherwise, +the initialization of \tcode{V} +strongly happens before +the initialization of \tcode{W}. +\end{itemize} + +\item +Otherwise, if the program starts a thread +other than the main thread +before either \tcode{V} or \tcode{W} is initialized, +it is unspecified in which threads +the initializations of \tcode{V} and \tcode{W} occur; +the initializations are unsequenced if they occur in the same thread. + +\item +Otherwise, the initializations of \tcode{V} and \tcode{W} are indeterminately sequenced. +\end{itemize} +\begin{note} +This definition permits initialization of a sequence of +ordered variables concurrently with another sequence. +\end{note} + +\pnum +\indextext{non-initialization odr-use|see{odr-use, non-initialization}}% +A \defnx{non-initialization odr-use}{odr-use!non-initialization} +is an odr-use\iref{term.odr.use} not caused directly or indirectly by +the initialization of a non-block static or thread storage duration variable. + +\pnum +\indextext{evaluation!unspecified order of}% +It is \impldef{dynamic initialization of static variables before \tcode{main}} +whether the dynamic initialization of a +non-block non-inline variable with static storage duration +is sequenced before the first statement of \tcode{main} or is deferred. +If it is deferred, it strongly happens before +any non-initialization odr-use +of any non-inline function or non-inline variable +defined in the same translation unit as the variable to be initialized. +\begin{footnote} +A non-block variable with static storage duration +having initialization +with side effects is initialized in this case, +even if it is not itself odr-used\iref{term.odr.use,basic.stc.static}. +\end{footnote} +It is \impldef{threads and program points at which deferred dynamic initialization is performed} +in which threads and at which points in the program such deferred dynamic initialization occurs. + +\recommended +An implementation should choose such points in a way +that allows the programmer to avoid deadlocks. +\begin{example} +\begin{codeblock} +// - File 1 - +#include "a.h" +#include "b.h" +B b; +A::A() { + b.Use(); +} + +// - File 2 - +#include "a.h" +A a; + +// - File 3 - +#include "a.h" +#include "b.h" +extern A a; +extern B b; + +int main() { + a.Use(); + b.Use(); +} +\end{codeblock} + +It is \impldef{dynamic initialization of static variables before \tcode{main}} +whether either \tcode{a} or \tcode{b} is +initialized before \tcode{main} is entered or whether the +initializations are delayed until \tcode{a} is first odr-used in +\tcode{main}. In particular, if \tcode{a} is initialized before +\tcode{main} is entered, it is not guaranteed that \tcode{b} will be +initialized before it is odr-used by the initialization of \tcode{a}, that +is, before \tcode{A::A} is called. If, however, \tcode{a} is initialized +at some point after the first statement of \tcode{main}, \tcode{b} will +be initialized prior to its use in \tcode{A::A}. +\end{example} + +\pnum +It is \impldef{dynamic initialization of static inline variables before \tcode{main}} +whether the dynamic initialization of a +non-block inline variable with static storage duration +is sequenced before the first statement of \tcode{main} or is deferred. +If it is deferred, it strongly happens before +any non-initialization odr-use +of that variable. +It is \impldef{threads and program points at which deferred dynamic initialization is performed} +in which threads and at which points in the program such deferred dynamic initialization occurs. + +\pnum +It is \impldef{dynamic initialization of thread-local variables before entry} +whether the dynamic initialization of a +non-block non-inline variable with thread storage duration +is sequenced before the first statement of the initial function of a thread or is deferred. +If it is deferred, +the initialization associated with the entity for thread \placeholder{t} +is sequenced before the first non-initialization odr-use by \placeholder{t} +of any non-inline variable with thread storage duration +defined in the same translation unit as the variable to be initialized. +It is \impldef{threads and program points at which deferred dynamic initialization is performed} +in which threads and at which points in the program such deferred dynamic initialization occurs. + +\pnum +If the initialization of +a non-block variable with static or thread storage duration +exits via an exception, +the function \tcode{std::terminate} is called\iref{except.terminate}.% +\indextext{program!startup|)} + +\rSec3[basic.start.term]{Termination} + +\pnum +\indextext{program!termination|(}% +\indextext{object!destructor static}% +\indextext{\idxcode{main} function!return from}% +Constructed objects\iref{dcl.init} +with static storage duration are destroyed +and functions registered with \tcode{std::atexit} +are called as part of a call to +\indextext{\idxcode{exit}}% +\indexlibraryglobal{exit}% +\tcode{std::exit}\iref{support.start.term}. +The call to \tcode{std::exit} is sequenced before +the destructions and the registered functions. +\begin{note} +Returning from \tcode{main} invokes \tcode{std::exit}\iref{basic.start.main}. +\end{note} + +\pnum +Constructed objects with thread storage duration within a given thread +are destroyed as a result of returning from the initial function of that thread and as a +result of that thread calling \tcode{std::exit}. +The destruction of all constructed objects with thread storage +duration within that thread strongly happens before destroying +any object with static storage duration. + +\pnum +If the completion of the constructor or dynamic initialization of an object with static +storage duration strongly happens before that of another, the completion of the destructor +of the second is sequenced before the initiation of the destructor of the first. +If the completion of the constructor or dynamic initialization of an object with thread +storage duration is sequenced before that of another, the completion of the destructor +of the second is sequenced before the initiation of the destructor of the first. +If an object is +initialized statically, the object is destroyed in the same order as if +the object was dynamically initialized. For an object of array or class +type, all subobjects of that object are destroyed before any block +variable with static storage duration initialized during the construction +of the subobjects is destroyed. +If the destruction of an object with static or thread storage duration +exits via an exception, +the function \tcode{std::terminate} is called\iref{except.terminate}. + +\pnum +If a function contains a block variable of static or thread storage duration that has been +destroyed and the function is called during the destruction of an object with static or +thread storage duration, the program has undefined behavior if the flow of control +passes through the definition of the previously destroyed block variable. +\begin{note} +Likewise, the behavior is undefined +if the block variable is used indirectly (e.g., through a pointer) +after its destruction. +\end{note} + +\pnum +\indextext{\idxcode{atexit}}% +\indexlibraryglobal{atexit}% +If the completion of the initialization of an object with static storage +duration strongly happens before a call to \tcode{std::atexit}~(see +\libheader{cstdlib}, \ref{support.start.term}), the call to the function passed to +\tcode{std::atexit} is sequenced before the call to the destructor for the object. If a +call to \tcode{std::atexit} strongly happens before the completion of the initialization of +an object with static storage duration, the call to the destructor for the +object is sequenced before the call to the function passed to \tcode{std::atexit}. If a +call to \tcode{std::atexit} strongly happens before another call to \tcode{std::atexit}, the +call to the function passed to the second \tcode{std::atexit} call is sequenced before +the call to the function passed to the first \tcode{std::atexit} call. + +\pnum +If there is a use of a standard library object or function not permitted within signal +handlers\iref{support.runtime} that does not happen before\iref{intro.multithread} +completion of destruction of objects with static storage duration and execution of +\tcode{std::atexit} registered functions\iref{support.start.term}, the program has +undefined behavior. +\begin{note} +If there is a use of an object with static storage +duration that does not happen before the object's destruction, the program has undefined +behavior. Terminating every thread before a call to \tcode{std::exit} or the exit from +\tcode{main} is sufficient, but not necessary, to satisfy these requirements. These +requirements permit thread managers as static-storage-duration objects. +\end{note} + +\pnum +\indextext{\idxcode{abort}}% +\indexlibraryglobal{abort}% +\indextext{termination!program}% +Calling the function \tcode{std::abort()} declared in +\libheaderref{cstdlib} terminates the program without executing any destructors +and without calling +the functions passed to \tcode{std::atexit()} or \tcode{std::at_quick_exit()}.% +\indextext{program!termination|)} +\indextext{program execution|)} \indextext{conventions!lexical|)} diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index 1aba8e649d..e39699f8c6 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -100,8 +100,10 @@ \movedxref{stmt.stmt}{stmt} % Lexing reorganization -\movedxref{lex.digraph}{lex.operators} +\movedxref{basic.stc.inherit}{basic.stc.general} \movedxref{gram.basic}{gram.module} +\movedxref{lex.digraph}{lex.operators} + %%% Deprecated features. %%% Example: From 19c9172f6ff75f2627982228e9607266aa3502b5 Mon Sep 17 00:00:00 2001 From: Alisdair Meredith Date: Mon, 30 Sep 2024 15:47:46 -0400 Subject: [PATCH 14/18] [basic] Reorganize subclauses for locality of reference --- source/basic.tex | 717 +++++++++++++++++++++++------------------------ 1 file changed, 356 insertions(+), 361 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index bd97d83581..64d4116763 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -6,13 +6,10 @@ \pnum \begin{note} This Clause presents the basic concepts of the \Cpp{} language. -It explains the difference between an object and a -name and how they relate to the value categories for expressions. It introduces the concepts of a declaration and a definition and presents \Cpp{}'s -notion of type, scope, linkage, and -storage duration. The mechanisms for starting and -terminating a program are discussed. Finally, this Clause presents the +notion of type, scope, and +storage duration. Finally, this Clause presents the fundamental types of the language and lists the ways of constructing compound types from these. \end{note} @@ -396,6 +393,100 @@ \end{note} \indextext{object model|)} +\rSec2[basic.align]{Alignment} + +\pnum +Object types have \defnx{alignment requirements}{alignment requirement!implementation-defined}\iref{basic.fundamental,basic.compound} +which place restrictions on the addresses at which an object of that type +may be allocated. An \defn{alignment} is an \impldef{alignment} +integer value representing the number of bytes between successive addresses +at which a given object can be allocated. An object type imposes an alignment +requirement on every object of that type; stricter alignment can be requested +using the alignment specifier\iref{dcl.align}. +Attempting to create an object\iref{intro.object} in storage that +does not meet the alignment requirements of the object's type +is undefined behavior. + +\pnum +A \defnadj{fundamental}{alignment} is represented by an alignment +less than or equal to the greatest alignment supported by the implementation in +all contexts, which is equal to +\tcode{\keyword{alignof}(std::max_align_t)}\iref{support.types}. +The alignment required for a type may be different when it is used as the type +of a complete object and when it is used as the type of a subobject. +\begin{example} +\begin{codeblock} +struct B { long double d; }; +struct D : virtual B { char c; }; +\end{codeblock} + +When \tcode{D} is the type of a complete object, it will have a subobject of +type \tcode{B}, so it must be aligned appropriately for a \tcode{\keyword{long} \keyword{double}}. +If \tcode{D} appears as a subobject of another object that also has \tcode{B} +as a virtual base class, the \tcode{B} subobject might be part of a different +subobject, reducing the alignment requirements on the \tcode{D} subobject. +\end{example} +The result of the \keyword{alignof} operator reflects the alignment +requirement of the type in the complete-object case. + +\pnum +An \defnadj{extended}{alignment} is represented by an alignment +greater than \tcode{\keyword{alignof}(std::max_align_t)}. It is \impldef{support for extended alignments} +whether any extended alignments are supported and the contexts in which they are +supported\iref{dcl.align}. A type having an extended alignment +requirement is an \defnadj{over-aligned}{type}. +\begin{note} +Every over-aligned type is or contains a class type +to which extended alignment applies (possibly through a non-static data member). +\end{note} +A \defnadj{new-extended}{alignment} is represented by +an alignment greater than \mname{STDCPP_DEFAULT_NEW_ALIGNMENT}\iref{cpp.predefined}. + +\pnum +Alignments are represented as values of the type \tcode{std::size_t}. +Valid alignments include only those values returned by an \keyword{alignof} +expression for the fundamental types plus an additional \impldef{alignment additional +values} +set of values, which may be empty. +Every alignment value shall be a non-negative integral power of two. + +\pnum +Alignments have an order from \defnx{weaker}{alignment!weaker} to +\defnx{stronger}{alignment!stronger} or \defnx{stricter}{alignment!stricter} alignments. Stricter +alignments have larger alignment values. An address that satisfies an alignment +requirement also satisfies any weaker valid alignment requirement. + +\pnum +The alignment requirement of a complete type can be queried using an +\keyword{alignof} expression\iref{expr.alignof}. Furthermore, +the narrow character types\iref{basic.fundamental} shall have the weakest +alignment requirement. +\begin{note} +This enables the ordinary character types to be used as the +underlying type for an aligned memory area\iref{dcl.align}. +\end{note} + +\pnum +Comparing alignments is meaningful and provides the obvious results: + +\begin{itemize} +\item Two alignments are equal when their numeric values are equal. +\item Two alignments are different when their numeric values are not equal. +\item When an alignment is larger than another it represents a stricter alignment. +\end{itemize} + +\pnum +\begin{note} +The runtime pointer alignment function\iref{ptr.align} +can be used to obtain an aligned pointer within a buffer; +an \grammarterm{alignment-specifier}\iref{dcl.align} +can be used to align storage explicitly. +\end{note} + +\pnum +If a request for a specific extended alignment in a specific context is not +supported by an implementation, the program is ill-formed. + \rSec2[basic.life]{Lifetime} \pnum @@ -854,8 +945,6 @@ \pnum The storage duration categories apply to references as well. -\rSec3[basic.stc.inherit]{Duration of subobjects} - \pnum \indextext{storage duration!class member}% The storage duration of subobjects and reference members @@ -1194,100 +1283,6 @@ deallocation function shall deallocate the storage referenced by the pointer, ending the duration of the region of storage. -\rSec2[basic.align]{Alignment} - -\pnum -Object types have \defnx{alignment requirements}{alignment requirement!implementation-defined}\iref{basic.fundamental,basic.compound} -which place restrictions on the addresses at which an object of that type -may be allocated. An \defn{alignment} is an \impldef{alignment} -integer value representing the number of bytes between successive addresses -at which a given object can be allocated. An object type imposes an alignment -requirement on every object of that type; stricter alignment can be requested -using the alignment specifier\iref{dcl.align}. -Attempting to create an object\iref{intro.object} in storage that -does not meet the alignment requirements of the object's type -is undefined behavior. - -\pnum -A \defnadj{fundamental}{alignment} is represented by an alignment -less than or equal to the greatest alignment supported by the implementation in -all contexts, which is equal to -\tcode{\keyword{alignof}(std::max_align_t)}\iref{support.types}. -The alignment required for a type may be different when it is used as the type -of a complete object and when it is used as the type of a subobject. -\begin{example} -\begin{codeblock} -struct B { long double d; }; -struct D : virtual B { char c; }; -\end{codeblock} - -When \tcode{D} is the type of a complete object, it will have a subobject of -type \tcode{B}, so it must be aligned appropriately for a \tcode{\keyword{long} \keyword{double}}. -If \tcode{D} appears as a subobject of another object that also has \tcode{B} -as a virtual base class, the \tcode{B} subobject might be part of a different -subobject, reducing the alignment requirements on the \tcode{D} subobject. -\end{example} -The result of the \keyword{alignof} operator reflects the alignment -requirement of the type in the complete-object case. - -\pnum -An \defnadj{extended}{alignment} is represented by an alignment -greater than \tcode{\keyword{alignof}(std::max_align_t)}. It is \impldef{support for extended alignments} -whether any extended alignments are supported and the contexts in which they are -supported\iref{dcl.align}. A type having an extended alignment -requirement is an \defnadj{over-aligned}{type}. -\begin{note} -Every over-aligned type is or contains a class type -to which extended alignment applies (possibly through a non-static data member). -\end{note} -A \defnadj{new-extended}{alignment} is represented by -an alignment greater than \mname{STDCPP_DEFAULT_NEW_ALIGNMENT}\iref{cpp.predefined}. - -\pnum -Alignments are represented as values of the type \tcode{std::size_t}. -Valid alignments include only those values returned by an \keyword{alignof} -expression for the fundamental types plus an additional \impldef{alignment additional -values} -set of values, which may be empty. -Every alignment value shall be a non-negative integral power of two. - -\pnum -Alignments have an order from \defnx{weaker}{alignment!weaker} to -\defnx{stronger}{alignment!stronger} or \defnx{stricter}{alignment!stricter} alignments. Stricter -alignments have larger alignment values. An address that satisfies an alignment -requirement also satisfies any weaker valid alignment requirement. - -\pnum -The alignment requirement of a complete type can be queried using an -\keyword{alignof} expression\iref{expr.alignof}. Furthermore, -the narrow character types\iref{basic.fundamental} shall have the weakest -alignment requirement. -\begin{note} -This enables the ordinary character types to be used as the -underlying type for an aligned memory area\iref{dcl.align}. -\end{note} - -\pnum -Comparing alignments is meaningful and provides the obvious results: - -\begin{itemize} -\item Two alignments are equal when their numeric values are equal. -\item Two alignments are different when their numeric values are not equal. -\item When an alignment is larger than another it represents a stricter alignment. -\end{itemize} - -\pnum -\begin{note} -The runtime pointer alignment function\iref{ptr.align} -can be used to obtain an aligned pointer within a buffer; -an \grammarterm{alignment-specifier}\iref{dcl.align} -can be used to align storage explicitly. -\end{note} - -\pnum -If a request for a specific extended alignment in a specific context is not -supported by an implementation, the program is ill-formed. - \rSec2[class.temporary]{Temporary objects} \pnum @@ -1925,40 +1920,155 @@ layout-compatible enumerations\iref{dcl.enum}, or layout-compatible standard-layout class types\iref{class.mem}. -\rSec2[basic.fundamental]{Fundamental types} +\rSec2[basic.type.qualifier]{CV-qualifiers} \pnum -\indextext{type!implementation-defined \tcode{sizeof}}% -There are five \defnadjx{standard signed integer}{types}{type}: -\indextext{type!\idxcode{signed char}}% -\indextext{type!\idxcode{short}}% -\indextext{type!\idxcode{int}}% -\indextext{type!\idxcode{long}}% -\indextext{type!\idxcode{long long}}% -``\tcode{\keyword{signed} \keyword{char}}'', ``\tcode{\keyword{short} \keyword{int}}'', ``\keyword{int}'', -``\tcode{\keyword{long} \keyword{int}}'', and ``\tcode{\keyword{long} \keyword{long} \keyword{int}}''. In -this list, each type provides at least as much storage as those -preceding it in the list. -There may also be \impldef{extended signed integer types} -\defnadjx{extended signed integer}{types}{type}. -The standard and extended signed integer types are collectively called -\defnadjx{signed integer}{types}{type}. -The range of representable values for a signed integer type is -$-2^{N-1}$ to $2^{N-1}-1$ (inclusive), -where \placeholder{N} is called the \defn{width} of the type. -\indextext{integral type!implementation-defined \tcode{sizeof}}% +\indextext{cv-qualifier}% +\indextext{\idxcode{const}}% +\indextext{\idxcode{volatile}}% +Each type other than a function or reference type +is part of a group of four distinct, but related, types: +a \defn{cv-unqualified} version, +a \defn{const-qualified} version, +a \defn{volatile-qualified} version, and +a \defn{const-volatile-qualified} version. +The types in each such group shall have +the same representation and alignment requirements\iref{basic.align}. +\begin{footnote} +The same representation and alignment requirements +are meant to imply interchangeability as +arguments to functions, +return values from functions, and +non-static data members of unions. +\end{footnote} +A function or reference type is always cv-unqualified. +\begin{itemize} +\item A \defnadj{const}{object} is an object of type \tcode{\keyword{const} T} or a + non-mutable subobject of a const object. + +\item A \defnadj{volatile}{object} is an object of type + \tcode{\keyword{volatile} T} or a subobject of a volatile object. + +\item A \defnadj{const volatile}{object} is an object of type + \tcode{\keyword{const} \keyword{volatile} T}, a non-mutable subobject of a const volatile object, + a const subobject of a volatile object, or a non-mutable volatile + subobject of a const object. +\end{itemize} \begin{note} -Plain \tcode{int}s are intended to have -the natural width suggested by the architecture of the execution environment; -the other signed integer types are provided to meet special needs. +The type of an object\iref{intro.object} includes +the \grammarterm{cv-qualifier}s specified in the +\grammarterm{decl-specifier-seq}\iref{dcl.spec}, +\grammarterm{declarator}\iref{dcl.decl}, +\grammarterm{type-id}\iref{dcl.name}, or +\grammarterm{new-type-id}\iref{expr.new} +when the object is created. \end{note} \pnum -\indextext{type!\idxcode{unsigned}}% -For each of the standard signed integer types, -there exists a corresponding (but different) -\defnadj{standard unsigned integer}{type}: -\indextext{type!\idxcode{unsigned char}}% +Except for array types, a compound type\iref{basic.compound} is not cv-qualified by the +cv-qualifiers (if any) of the types from which it is compounded. + +\pnum +\indextext{array!\idxcode{const}}% +An array type whose elements are cv-qualified +is also considered to have the same cv-qualifications +as its elements. +\begin{note} +Cv-qualifiers applied to an array +type attach to the underlying element type, so the notation +``\cv{}~\tcode{T}'', where \tcode{T} is an array type, refers to +an array whose elements are so-qualified\iref{dcl.array}. +\end{note} +\begin{example} +\begin{codeblock} +typedef char CA[5]; +typedef const char CC; +CC arr1[5] = { 0 }; +const CA arr2 = { 0 }; +\end{codeblock} +The type of both \tcode{arr1} and \tcode{arr2} is ``array of 5 +\tcode{\keyword{const} \keyword{char}}'', and the array type is considered to be +const-qualified. +\end{example} +\indextext{type|)} + +\pnum +\begin{note} +See~\ref{dcl.fct} and~\ref{over.match.funcs} regarding function +types that have \grammarterm{cv-qualifier}{s}. +\end{note} + +\pnum +There is a partial ordering on cv-qualifiers, so that a type can be +said to be \defn{more cv-qualified} than another. +\tref{basic.type.qualifier.rel} shows the relations that +constitute this ordering. + +\begin{floattable}{Relations on \keyword{const} and \keyword{volatile}}{basic.type.qualifier.rel} +{ccc} +\topline +\cvqual{no cv-qualifier} &<& \keyword{const} \\ +\cvqual{no cv-qualifier} &<& \keyword{volatile} \\ +\cvqual{no cv-qualifier} &<& \tcode{\keyword{const} \keyword{volatile}} \\ +\keyword{const} &<& \tcode{\keyword{const} \keyword{volatile}} \\ +\keyword{volatile} &<& \tcode{\keyword{const} \keyword{volatile}} \\ +\end{floattable} + +\pnum +In this document, the notation \cv{} (or +\cvqual{cv1}, \cvqual{cv2}, etc.), used in the description of types, +represents an arbitrary set of cv-qualifiers, i.e., one of +\{\keyword{const}\}, \{\keyword{volatile}\}, \{\keyword{const}, +\keyword{volatile}\}, or the empty set. +For a type \cv{}~\tcode{T}, the \defnx{top-level cv-qualifiers}{cv-qualifier!top-level} +of that type are those denoted by \cv. +\begin{example} +The type corresponding to the \grammarterm{type-id} +\tcode{\keyword{const} \keyword{int}\&} +has no top-level cv-qualifiers. +The type corresponding to the \grammarterm{type-id} +\tcode{\keyword{volatile} \keyword{int} * \keyword{const}} +has the top-level cv-qualifier \keyword{const}. +For a class type \tcode{C}, +the type corresponding to the \grammarterm{type-id} +\tcode{\keyword{void} (C::* \keyword{volatile})(\keyword{int}) \keyword{const}} +has the top-level cv-qualifier \keyword{volatile}. +\end{example} + +\rSec2[basic.fundamental]{Fundamental types} + +\pnum +\indextext{type!implementation-defined \tcode{sizeof}}% +There are five \defnadjx{standard signed integer}{types}{type}: +\indextext{type!\idxcode{signed char}}% +\indextext{type!\idxcode{short}}% +\indextext{type!\idxcode{int}}% +\indextext{type!\idxcode{long}}% +\indextext{type!\idxcode{long long}}% +``\tcode{\keyword{signed} \keyword{char}}'', ``\tcode{\keyword{short} \keyword{int}}'', ``\keyword{int}'', +``\tcode{\keyword{long} \keyword{int}}'', and ``\tcode{\keyword{long} \keyword{long} \keyword{int}}''. In +this list, each type provides at least as much storage as those +preceding it in the list. +There may also be \impldef{extended signed integer types} +\defnadjx{extended signed integer}{types}{type}. +The standard and extended signed integer types are collectively called +\defnadjx{signed integer}{types}{type}. +The range of representable values for a signed integer type is +$-2^{N-1}$ to $2^{N-1}-1$ (inclusive), +where \placeholder{N} is called the \defn{width} of the type. +\indextext{integral type!implementation-defined \tcode{sizeof}}% +\begin{note} +Plain \tcode{int}s are intended to have +the natural width suggested by the architecture of the execution environment; +the other signed integer types are provided to meet special needs. +\end{note} + +\pnum +\indextext{type!\idxcode{unsigned}}% +For each of the standard signed integer types, +there exists a corresponding (but different) +\defnadj{standard unsigned integer}{type}: +\indextext{type!\idxcode{unsigned char}}% \indextext{type!\idxcode{unsigned short}}% \indextext{type!\idxcode{unsigned int}}% \indextext{type!\idxcode{unsigned long}}% @@ -2324,6 +2434,123 @@ \tcode{_Float16}, \tcode{_Float32}, \tcode{_Float64}, and \tcode{_Float128} defined in ISO/IEC TS 18661-3 and with future versions of \IsoCUndated{}. +\rSec2[conv.rank]{Conversion ranks}% +\indextext{conversion!integer rank} + +\pnum +Every integer type has an \term{integer conversion rank} defined as follows: + +\begin{itemize} +\item No two signed integer types other than \keyword{char} and \tcode{\keyword{signed} +\keyword{char}} (if \keyword{char} is signed) have the same rank, even if they have +the same representation. + +\item The rank of a signed integer type is greater than the rank +of any signed integer type with a smaller width. + +\item The rank of \tcode{\keyword{long} \keyword{long} \keyword{int}} is greater +than the rank of \tcode{\keyword{long} \keyword{int}}, which is greater than +the rank of \keyword{int}, which is greater than the rank of +\tcode{\keyword{short} \keyword{int}}, which is greater than the rank of +\tcode{\keyword{signed} \keyword{char}}. + +\item The rank of any unsigned integer type equals the rank of the +corresponding signed integer type. + +\item The rank of any standard integer type is greater than the +rank of any extended integer type with the same width. + +\item The rank of \keyword{char} equals the rank of \tcode{\keyword{signed} \keyword{char}} +and \tcode{\keyword{unsigned} \keyword{char}}. + +\item The rank of \tcode{bool} is less than the rank of all +standard integer types. + +\item +\indextext{type!\idxcode{wchar_t}}% +\indextext{type!\idxcode{char16_t}}% +\indextext{type!\idxcode{char32_t}}% +The ranks of \keyword{char8_t}, \keyword{char16_t}, \keyword{char32_t}, and +\keyword{wchar_t} equal the ranks of their underlying +types\iref{basic.fundamental}. + +\item The rank of any extended signed integer type relative to another +extended signed integer type with the same width is \impldef{rank of extended signed +integer type}, but still subject to the other rules for determining the integer +conversion rank. + +\item For all integer types \tcode{T1}, \tcode{T2}, and \tcode{T3}, if +\tcode{T1} has greater rank than \tcode{T2} and \tcode{T2} has greater +rank than \tcode{T3}, then \tcode{T1} has greater rank than +\tcode{T3}. +\end{itemize} + +\begin{note} +The integer conversion rank is used in the definition of the integral +promotions\iref{conv.prom} and the usual arithmetic +conversions\iref{expr.arith.conv}. +\end{note} + +\pnum +Every floating-point type has a \defnadj{floating-point}{conversion rank} +defined as follows: +\begin{itemize} +\item +The rank of a floating point type \tcode{T} is greater than +the rank of any floating-point type +whose set of values is a proper subset of the set of values of \tcode{T}. +\item +The rank of \tcode{\keyword{long} \keyword{double}} is greater than +the rank of \keyword{double}, +which is greater than the rank of \keyword{float}. +\item +Two extended floating-point types with the same set of values have equal ranks. +\item +An extended floating-point type with the same set of values as +exactly one cv-unqualified standard floating-point type +has a rank equal to the rank of that standard floating-point type. +\item +An extended floating-point type with the same set of values as +more than one cv-unqualified standard floating-point type +has a rank equal to the rank of \keyword{double}. +\begin{tailnote} +The treatment of \tcode{std::float64_t} differs from +that of the analoguous \tcode{_Float64} in C, +for example on platforms where all of +\tcode{\keyword{long} \keyword{double}}, +\keyword{double}, and +\tcode{std::float64_t} +have the same set of values (see \IsoCUndated{}:2024 H.4.2). +\end{tailnote} +\end{itemize} +\begin{note} +The conversion ranks of floating-point types \tcode{T1} and \tcode{T2} +are unordered if the set of values of \tcode{T1} is +neither a subset nor a superset of the set of values of \tcode{T2}. +This can happen when one type has both a larger range and a lower precision +than the other. +\end{note} + +\pnum +Floating-point types that have equal floating-point conversion ranks +are ordered by floating-point conversion subrank. +The subrank forms a total order among types with equal ranks. +The types +\tcode{std::float16_t}, +\tcode{std::float32_t}, +\tcode{std::float64_t}, and +\tcode{std::float128_t}\iref{stdfloat.syn} +have a greater conversion subrank than any standard floating-point type +with equal conversion rank. +Otherwise, the conversion subrank order is +\impldef{floating-point conversion subrank}. + +\pnum +\begin{note} +The floating-point conversion rank and subrank are used in +the definition of the usual arithmetic conversions\iref{expr.arith.conv}. +\end{note} + \rSec2[basic.compound]{Compound types} \pnum @@ -2527,238 +2754,6 @@ shall have the same representation and alignment requirements as an object of type ``pointer to \cv{}~\keyword{char}''. -\rSec2[basic.type.qualifier]{CV-qualifiers} - -\pnum -\indextext{cv-qualifier}% -\indextext{\idxcode{const}}% -\indextext{\idxcode{volatile}}% -Each type other than a function or reference type -is part of a group of four distinct, but related, types: -a \defn{cv-unqualified} version, -a \defn{const-qualified} version, -a \defn{volatile-qualified} version, and -a \defn{const-volatile-qualified} version. -The types in each such group shall have -the same representation and alignment requirements\iref{basic.align}. -\begin{footnote} -The same representation and alignment requirements -are meant to imply interchangeability as -arguments to functions, -return values from functions, and -non-static data members of unions. -\end{footnote} -A function or reference type is always cv-unqualified. -\begin{itemize} -\item A \defnadj{const}{object} is an object of type \tcode{\keyword{const} T} or a - non-mutable subobject of a const object. - -\item A \defnadj{volatile}{object} is an object of type - \tcode{\keyword{volatile} T} or a subobject of a volatile object. - -\item A \defnadj{const volatile}{object} is an object of type - \tcode{\keyword{const} \keyword{volatile} T}, a non-mutable subobject of a const volatile object, - a const subobject of a volatile object, or a non-mutable volatile - subobject of a const object. -\end{itemize} -\begin{note} -The type of an object\iref{intro.object} includes -the \grammarterm{cv-qualifier}s specified in the -\grammarterm{decl-specifier-seq}\iref{dcl.spec}, -\grammarterm{declarator}\iref{dcl.decl}, -\grammarterm{type-id}\iref{dcl.name}, or -\grammarterm{new-type-id}\iref{expr.new} -when the object is created. -\end{note} - -\pnum -Except for array types, a compound type\iref{basic.compound} is not cv-qualified by the -cv-qualifiers (if any) of the types from which it is compounded. - -\pnum -\indextext{array!\idxcode{const}}% -An array type whose elements are cv-qualified -is also considered to have the same cv-qualifications -as its elements. -\begin{note} -Cv-qualifiers applied to an array -type attach to the underlying element type, so the notation -``\cv{}~\tcode{T}'', where \tcode{T} is an array type, refers to -an array whose elements are so-qualified\iref{dcl.array}. -\end{note} -\begin{example} -\begin{codeblock} -typedef char CA[5]; -typedef const char CC; -CC arr1[5] = { 0 }; -const CA arr2 = { 0 }; -\end{codeblock} -The type of both \tcode{arr1} and \tcode{arr2} is ``array of 5 -\tcode{\keyword{const} \keyword{char}}'', and the array type is considered to be -const-qualified. -\end{example} -\indextext{type|)} - -\pnum -\begin{note} -See~\ref{dcl.fct} and~\ref{over.match.funcs} regarding function -types that have \grammarterm{cv-qualifier}{s}. -\end{note} - -\pnum -There is a partial ordering on cv-qualifiers, so that a type can be -said to be \defn{more cv-qualified} than another. -\tref{basic.type.qualifier.rel} shows the relations that -constitute this ordering. - -\begin{floattable}{Relations on \keyword{const} and \keyword{volatile}}{basic.type.qualifier.rel} -{ccc} -\topline -\cvqual{no cv-qualifier} &<& \keyword{const} \\ -\cvqual{no cv-qualifier} &<& \keyword{volatile} \\ -\cvqual{no cv-qualifier} &<& \tcode{\keyword{const} \keyword{volatile}} \\ -\keyword{const} &<& \tcode{\keyword{const} \keyword{volatile}} \\ -\keyword{volatile} &<& \tcode{\keyword{const} \keyword{volatile}} \\ -\end{floattable} - -\pnum -In this document, the notation \cv{} (or -\cvqual{cv1}, \cvqual{cv2}, etc.), used in the description of types, -represents an arbitrary set of cv-qualifiers, i.e., one of -\{\keyword{const}\}, \{\keyword{volatile}\}, \{\keyword{const}, -\keyword{volatile}\}, or the empty set. -For a type \cv{}~\tcode{T}, the \defnx{top-level cv-qualifiers}{cv-qualifier!top-level} -of that type are those denoted by \cv. -\begin{example} -The type corresponding to the \grammarterm{type-id} -\tcode{\keyword{const} \keyword{int}\&} -has no top-level cv-qualifiers. -The type corresponding to the \grammarterm{type-id} -\tcode{\keyword{volatile} \keyword{int} * \keyword{const}} -has the top-level cv-qualifier \keyword{const}. -For a class type \tcode{C}, -the type corresponding to the \grammarterm{type-id} -\tcode{\keyword{void} (C::* \keyword{volatile})(\keyword{int}) \keyword{const}} -has the top-level cv-qualifier \keyword{volatile}. -\end{example} - -\rSec2[conv.rank]{Conversion ranks}% -\indextext{conversion!integer rank} - -\pnum -Every integer type has an \term{integer conversion rank} defined as follows: - -\begin{itemize} -\item No two signed integer types other than \keyword{char} and \tcode{\keyword{signed} -\keyword{char}} (if \keyword{char} is signed) have the same rank, even if they have -the same representation. - -\item The rank of a signed integer type is greater than the rank -of any signed integer type with a smaller width. - -\item The rank of \tcode{\keyword{long} \keyword{long} \keyword{int}} is greater -than the rank of \tcode{\keyword{long} \keyword{int}}, which is greater than -the rank of \keyword{int}, which is greater than the rank of -\tcode{\keyword{short} \keyword{int}}, which is greater than the rank of -\tcode{\keyword{signed} \keyword{char}}. - -\item The rank of any unsigned integer type equals the rank of the -corresponding signed integer type. - -\item The rank of any standard integer type is greater than the -rank of any extended integer type with the same width. - -\item The rank of \keyword{char} equals the rank of \tcode{\keyword{signed} \keyword{char}} -and \tcode{\keyword{unsigned} \keyword{char}}. - -\item The rank of \tcode{bool} is less than the rank of all -standard integer types. - -\item -\indextext{type!\idxcode{wchar_t}}% -\indextext{type!\idxcode{char16_t}}% -\indextext{type!\idxcode{char32_t}}% -The ranks of \keyword{char8_t}, \keyword{char16_t}, \keyword{char32_t}, and -\keyword{wchar_t} equal the ranks of their underlying -types\iref{basic.fundamental}. - -\item The rank of any extended signed integer type relative to another -extended signed integer type with the same width is \impldef{rank of extended signed -integer type}, but still subject to the other rules for determining the integer -conversion rank. - -\item For all integer types \tcode{T1}, \tcode{T2}, and \tcode{T3}, if -\tcode{T1} has greater rank than \tcode{T2} and \tcode{T2} has greater -rank than \tcode{T3}, then \tcode{T1} has greater rank than -\tcode{T3}. -\end{itemize} - -\begin{note} -The integer conversion rank is used in the definition of the integral -promotions\iref{conv.prom} and the usual arithmetic -conversions\iref{expr.arith.conv}. -\end{note} - -\pnum -Every floating-point type has a \defnadj{floating-point}{conversion rank} -defined as follows: -\begin{itemize} -\item -The rank of a floating point type \tcode{T} is greater than -the rank of any floating-point type -whose set of values is a proper subset of the set of values of \tcode{T}. -\item -The rank of \tcode{\keyword{long} \keyword{double}} is greater than -the rank of \keyword{double}, -which is greater than the rank of \keyword{float}. -\item -Two extended floating-point types with the same set of values have equal ranks. -\item -An extended floating-point type with the same set of values as -exactly one cv-unqualified standard floating-point type -has a rank equal to the rank of that standard floating-point type. -\item -An extended floating-point type with the same set of values as -more than one cv-unqualified standard floating-point type -has a rank equal to the rank of \keyword{double}. -\begin{tailnote} -The treatment of \tcode{std::float64_t} differs from -that of the analoguous \tcode{_Float64} in C, -for example on platforms where all of -\tcode{\keyword{long} \keyword{double}}, -\keyword{double}, and -\tcode{std::float64_t} -have the same set of values (see \IsoCUndated{}:2024 H.4.2). -\end{tailnote} -\end{itemize} -\begin{note} -The conversion ranks of floating-point types \tcode{T1} and \tcode{T2} -are unordered if the set of values of \tcode{T1} is -neither a subset nor a superset of the set of values of \tcode{T2}. -This can happen when one type has both a larger range and a lower precision -than the other. -\end{note} - -\pnum -Floating-point types that have equal floating-point conversion ranks -are ordered by floating-point conversion subrank. -The subrank forms a total order among types with equal ranks. -The types -\tcode{std::float16_t}, -\tcode{std::float32_t}, -\tcode{std::float64_t}, and -\tcode{std::float128_t}\iref{stdfloat.syn} -have a greater conversion subrank than any standard floating-point type -with equal conversion rank. -Otherwise, the conversion subrank order is -\impldef{floating-point conversion subrank}. - -\pnum -\begin{note} -The floating-point conversion rank and subrank are used in -the definition of the usual arithmetic conversions\iref{expr.arith.conv}. -\end{note} - \rSec1[basic.def]{Declarations and definitions} \pnum From 3e2ddc472031fb4c561d512e9fdb09a412d92a8e Mon Sep 17 00:00:00 2001 From: Alisdair Meredith Date: Tue, 1 Oct 2024 08:12:17 -0400 Subject: [PATCH 15/18] Reorder several lists to be by clause number --- source/basic.tex | 89 +++++++++++++++++++++++----------------------- source/lex.tex | 45 ++++++++++++----------- source/modules.tex | 7 ++-- 3 files changed, 71 insertions(+), 70 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 64d4116763..0e1fb2ea4b 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -492,11 +492,6 @@ \pnum In this subclause, ``before'' and ``after'' refer to the ``happens before'' relation\iref{intro.multithread}. -\begin{note} -Therefore, undefined behavior results -if an object that is being constructed in one thread is referenced from another -thread without adequate synchronization. -\end{note} \pnum \indextext{object lifetime|(}% @@ -673,6 +668,12 @@ \keyword{typeid}. \end{itemize} +\begin{note} +Therefore, undefined behavior results +if an object that is being constructed in one thread is referenced from another +thread without adequate synchronization. +\end{note} + \pnum An object $o_1$ is \defn{transparently replaceable} by an object $o_2$ if \begin{itemize} @@ -2770,11 +2771,11 @@ if another declaration of $X$ is reachable from it\iref{module.reach}. A declaration may also have effects including: \begin{itemize} +\item nothing (in the case of an \grammarterm{empty-declaration}), \item a static assertion\iref{dcl.pre}, -\item controlling template instantiation\iref{temp.explicit}, -\item guiding template argument deduction for constructors\iref{temp.deduct.guide}, -\item use of attributes\iref{dcl.attr}, and -\item nothing (in the case of an \grammarterm{empty-declaration}). +\item use of attributes\iref{dcl.attr}, +\item guiding template argument deduction for constructors\iref{temp.deduct.guide}, and +\item controlling template instantiation\iref{temp.explicit}. \end{itemize} \pnum @@ -2783,9 +2784,14 @@ Each entity declared by a \grammarterm{declaration} is also \defnx{defined}{define} by that declaration unless: \begin{itemize} +\item it is +a \grammarterm{static_assert-declaration}\iref{dcl.pre}, \item -it declares a function -without specifying the function's body\iref{dcl.fct.def}, +it is an +\grammarterm{attribute-declaration}\iref{dcl.pre}, +\item +it is an +\grammarterm{empty-declaration}\iref{dcl.pre}, \item it contains the @@ -2801,24 +2807,11 @@ and neither an \grammarterm{initializer} nor a \grammarterm{function-body}, \item -\indextext{declaration!static member@\tcode{static} member}% -it declares a non-inline static data member in a class -definition\iref{class.mem,class.static}, -\item -it declares a static data member outside a class definition -and the variable was defined within the class with the \keyword{constexpr} -specifier\iref{class.static.data} (this usage is deprecated; see \ref{depr.static.constexpr}), -\item -\indextext{declaration!class name}% -it is an \grammarterm{elaborated-type-specifier}\iref{class.name}, -\item -it is an -\indextext{declaration!opaque enum}% -\grammarterm{opaque-enum-declaration}\iref{dcl.enum}, -\item it is a -\indextext{parameter!template}\indextext{template parameter}% -\grammarterm{template-parameter}\iref{temp.param}, +\indextext{declaration!\idxcode{typedef}}% +\keyword{typedef} declaration\iref{dcl.typedef}, +\item it is +an \grammarterm{alias-declaration}\iref{dcl.typedef}, \item it is a \indextext{declaration!parameter}\indextext{parameter declaration}% @@ -2827,33 +2820,41 @@ declarator that is not the \grammarterm{declarator} of a \grammarterm{function-definition}, \item -it is a -\indextext{declaration!\idxcode{typedef}}% -\keyword{typedef} declaration\iref{dcl.typedef}, +it declares a function +without specifying the function's body\iref{dcl.fct.def}, +\item +it is an +\indextext{declaration!opaque enum}% +\grammarterm{opaque-enum-declaration}\iref{dcl.enum}, \item it is -an \grammarterm{alias-declaration}\iref{dcl.typedef}, +a \grammarterm{using-enum-declaration}\iref{enum.udecl}, +\item it is +a \grammarterm{using-directive}\iref{namespace.udir}, \item it is a \grammarterm{using-declaration}\iref{namespace.udecl}, -\item it is -a \grammarterm{deduction-guide}\iref{temp.deduct.guide}, -\item it is -a \grammarterm{static_assert-declaration}\iref{dcl.pre}, \item -it is an -\grammarterm{attribute-declaration}\iref{dcl.pre}, +\indextext{declaration!class name}% +it is an \grammarterm{elaborated-type-specifier}\iref{class.name}, \item -it is an -\grammarterm{empty-declaration}\iref{dcl.pre}, -\item it is -a \grammarterm{using-directive}\iref{namespace.udir}, -\item it is -a \grammarterm{using-enum-declaration}\iref{enum.udecl}, +\indextext{declaration!static member@\tcode{static} member}% +it declares a non-inline static data member in a class +definition\iref{class.mem,class.static}, +\item +it declares a static data member outside a class definition +and the variable was defined within the class with the \keyword{constexpr} +specifier\iref{class.static.data} (this usage is deprecated; see \ref{depr.static.constexpr}), \item it is a \grammarterm{template-declaration}\iref{temp.pre} whose \grammarterm{template-head} is not followed by either a \grammarterm{concept-definition} or a \grammarterm{declaration} that defines a function, a class, a variable, or a static data member, +\item +it is a +\indextext{parameter!template}\indextext{template parameter}% +\grammarterm{template-parameter}\iref{temp.param}, +\item it is +a \grammarterm{deduction-guide}\iref{temp.deduct.guide}, \item it is an explicit instantiation declaration\iref{temp.explicit}, or \item it is diff --git a/source/lex.tex b/source/lex.tex index 497aae78ad..4bb3e228d1 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -4339,34 +4339,34 @@ \grammarterm{block-declaration}, or \grammarterm{member-declaration}\iref{dcl.pre,class.mem}, \item -\grammarterm{init-declarator}\iref{dcl.decl}, -\item -\grammarterm{identifier} -in a structured binding declaration\iref{dcl.struct.bind}, -\item \grammarterm{init-capture}\iref{expr.prim.lambda.capture}, \item \grammarterm{condition} with a \grammarterm{declarator}\iref{stmt.pre}, \item -\grammarterm{member-declarator}\iref{class.mem}, +\grammarterm{elaborated-type-specifier} +that introduces a name\iref{dcl.type.elab}, \item -\grammarterm{using-declarator}\iref{namespace.udecl}, +\grammarterm{init-declarator}\iref{dcl.decl}, \item \grammarterm{parameter-declaration}\iref{dcl.fct}, \item -\grammarterm{type-parameter}\iref{temp.param}, +\grammarterm{identifier} +in a structured binding declaration\iref{dcl.struct.bind}, \item -\grammarterm{elaborated-type-specifier} -that introduces a name\iref{dcl.type.elab}, +\grammarterm{enum-specifier} or +\grammarterm{enumerator-definition}\iref{dcl.enum}, +\item +\grammarterm{using-declarator}\iref{namespace.udecl}, +\item +\grammarterm{exception-declaration}\iref{except.pre}, \item \grammarterm{class-specifier}\iref{class.pre}, \item -\grammarterm{enum-specifier} or -\grammarterm{enumerator-definition}\iref{dcl.enum}, +implicit declaration of an injected-class-name\iref{class.pre}, \item -\grammarterm{exception-declaration}\iref{except.pre}, or +\grammarterm{member-declarator}\iref{class.mem}, or \item -implicit declaration of an injected-class-name\iref{class.pre}. +\grammarterm{type-parameter}\iref{temp.param}. \end{itemize} \begin{note} The interpretation of a \grammarterm{for-range-declaration} produces @@ -4393,14 +4393,6 @@ a reference other than a non-static data member or of an object. The variable's name, if any, denotes the reference or object. -\pnum -\indextext{translation unit!name and}% -\indextext{linkage}% -A name used in more than one translation unit can potentially -refer to the same entity in these translation units depending on the -linkage\iref{basic.link} of the name specified in each -translation unit. - \pnum A name can have \defnadj{external}{linkage}, @@ -4543,6 +4535,13 @@ noted, a name declared at block scope\iref{basic.scope.block} has no linkage. +\pnum +\indextext{translation unit!name and}% +\indextext{linkage}% +A name used in more than one translation unit can potentially +refer to the same entity in these translation units depending on the +linkage of the name specified in each translation unit. + \pnum Two declarations of entities declare the same entity if, considering declarations of unnamed types to introduce their names @@ -4827,7 +4826,7 @@ \pnum An instance of each object with automatic storage duration\iref{basic.stc.auto} is associated with each entry into its -block. Such an object exists and retains its last-stored value during +block\iref{defns.block.stmt}. Such an object exists and retains its last-stored value during the execution of the block and while the block is suspended (by a call of a function, suspension of a coroutine\iref{expr.await}, or receipt of a signal). diff --git a/source/modules.tex b/source/modules.tex index a1d5b003a0..38ecafe6fa 100644 --- a/source/modules.tex +++ b/source/modules.tex @@ -32,7 +32,7 @@ \pnum \indextext{translation unit}% -A translation unit\iref{lex.phases} consists of a sequence of declarations. +A translation unit\iref{lex.phases} consists of a sequence of declarations\iref{dcl.pre}. \pnum A \defn{module unit} is a translation unit that contains @@ -335,8 +335,9 @@ \begin{note} Names introduced by exported declarations have either external linkage or no linkage; see \ref{basic.link}. -Namespace-scope declarations exported by a module can be found by name lookup -in any translation unit importing that module\iref{basic.lookup}. +Namespace-scope declarations exported by a module can be found by +name lookup\iref{basic.lookup} +in any translation unit importing that module. Class and enumeration member names can be found by name lookup in any context in which a definition of the type is reachable. \end{note} From 5d34bf2f36c7081b7ef6393ff710c8510933f73a Mon Sep 17 00:00:00 2001 From: Alisdair Meredith Date: Tue, 1 Oct 2024 13:46:59 -0400 Subject: [PATCH 16/18] Merge exception handling into statements --- source/exceptions.tex | 1152 ---------------------------------------- source/statements.tex | 1158 ++++++++++++++++++++++++++++++++++++++++- source/std.tex | 3 +- source/support.tex | 2 +- source/xrefdelta.tex | 1 + 5 files changed, 1159 insertions(+), 1157 deletions(-) delete mode 100644 source/exceptions.tex diff --git a/source/exceptions.tex b/source/exceptions.tex deleted file mode 100644 index 67e052c476..0000000000 --- a/source/exceptions.tex +++ /dev/null @@ -1,1152 +0,0 @@ -%!TEX root = std.tex -\rSec0[except]{Exception handling}% -\indextext{exception handling|(} - -\gramSec[gram.except]{Exception handling} - -\indextext{exception object|see{exception handling, exception object}}% -\indextext{object!exception|see{exception handling, exception object}} - -\rSec1[except.pre]{Preamble} - -\pnum -Exception handling provides a way of transferring control and information -from a point in the execution of a thread to an exception handler -associated with a point previously passed by the execution. -A handler will be invoked only by throwing an exception -in code executed in the handler's try block -or in functions called from the handler's try block. - -\indextext{\idxcode{try}}% -% -\begin{bnf} -\nontermdef{try-block}\br - \keyword{try} compound-statement handler-seq -\end{bnf} - -\indextext{\idxcode{try}}% -% -\begin{bnf} -\nontermdef{function-try-block}\br - \keyword{try} \opt{ctor-initializer} compound-statement handler-seq -\end{bnf} - -\begin{bnf} -\nontermdef{handler-seq}\br - handler \opt{handler-seq} -\end{bnf} - -\indextext{\idxcode{catch}}% -% -\begin{bnf} -\nontermdef{handler}\br - \keyword{catch} \terminal{(} exception-declaration \terminal{)} compound-statement -\end{bnf} - -\begin{bnf} -\nontermdef{exception-declaration}\br - \opt{attribute-specifier-seq} type-specifier-seq declarator\br - \opt{attribute-specifier-seq} type-specifier-seq \opt{abstract-declarator}\br - \terminal{...} -\end{bnf} - -The optional \grammarterm{attribute-specifier-seq} in an \grammarterm{exception-declaration} -appertains to the parameter of the catch clause\iref{except.handle}. - -\pnum -\indextext{exception handling!try block}% -\indextext{exception handling!handler}% -\indextext{try block|see{exception handling, try block}}% -\indextext{handler|see{exception handling, handler}}% -A \grammarterm{try-block} is a \grammarterm{statement}\iref{stmt.pre}. -\begin{note} -Within this Clause -``try block'' is taken to mean both \grammarterm{try-block} and -\grammarterm{function-try-block}. -\end{note} - -\pnum -\indextext{exception handling!\idxcode{goto}}% -\indextext{exception handling!\idxcode{switch}}% -\indextext{\idxcode{goto}!and try block}% -\indextext{\idxcode{switch}!and try block}% -\indextext{\idxcode{goto}!and handler}% -\indextext{\idxcode{switch}!and handler}% -The \grammarterm{compound-statement} of a try block or of a handler is a -control-flow-limited statement\iref{stmt.label}. -\begin{example} -\begin{codeblock} -void f() { - goto l1; // error - goto l2; // error - try { - goto l1; // OK - goto l2; // error - l1: ; - } catch (...) { - l2: ; - goto l1; // error - goto l2; // OK - } -} - -\end{codeblock} -\end{example} -\indextext{\idxcode{goto}!and try block}% -\indextext{\idxcode{switch}!and try block}% -\indextext{\idxcode{return}!and try block}% -\indextext{\idxcode{continue}!and try block}% -\indextext{\idxcode{goto}!and handler}% -\indextext{\idxcode{switch}!and handler}% -\indextext{\idxcode{return}!and handler}% -\indextext{\idxcode{continue}!and handler}% -A -\keyword{goto}, -\keyword{break}, -\keyword{return}, -or -\keyword{continue} -statement can be used to transfer control out of -a try block or handler. -When this happens, each variable declared in the try block -will be destroyed in the context that -directly contains its declaration. -\begin{example} -\begin{codeblock} -lab: try { - T1 t1; - try { - T2 t2; - if (@\grammarterm{condition}@) - goto lab; - } catch(...) { @\tcode{/* handler 2 */}@ } - } catch(...) { @\tcode{/* handler 1 */}@ } -\end{codeblock} - -Here, executing -\tcode{goto lab;} -will destroy first -\tcode{t2}, -then -\tcode{t1}, -assuming the -\grammarterm{condition} -does not declare a variable. -Any exception thrown while destroying -\tcode{t2} -will result in executing -\tcode{handler 2}; -any exception thrown while destroying -\tcode{t1} -will result in executing -\tcode{handler 1}. -\end{example} - -\pnum -\indextext{function try block|see{exception handling, function try block}}% -\indextext{exception handling!function try block}% -A -\grammarterm{function-try-block} -associates a -\grammarterm{handler-seq} -with the -\grammarterm{ctor-initializer}, -if present, and the -\grammarterm{compound-statement}. -An exception -thrown during the execution of the -\grammarterm{compound-statement} -or, for constructors and destructors, during the initialization or -destruction, respectively, of the class's subobjects, -transfers control to a handler in a -\grammarterm{function-try-block} -in the same way as an exception thrown during the execution of a -\grammarterm{try-block} -transfers control to other handlers. -\begin{example} -\begin{codeblock} -int f(int); -class C { - int i; - double d; -public: - C(int, double); -}; - -C::C(int ii, double id) -try : i(f(ii)), d(id) { - // constructor statements -} catch (...) { - // handles exceptions thrown from the ctor-initializer and from the constructor statements -} -\end{codeblock} -\end{example} - -\pnum -In this Clause, ``before'' and ``after'' refer to the -``sequenced before'' relation\iref{intro.execution}. - -\rSec1[except.throw]{Throwing an exception}% -\indextext{exception handling!throwing}% -\indextext{throwing|see{exception handling, throwing}} - -\pnum -Throwing an exception transfers control to a handler. -\begin{note} -An exception can be thrown from one of the following contexts: -\grammarterm{throw-expression}{s}\iref{expr.throw}, -allocation functions\iref{basic.stc.dynamic.allocation}, -\keyword{dynamic_cast}\iref{expr.dynamic.cast}, -\keyword{typeid}\iref{expr.typeid}, -\grammarterm{new-expression}{s}\iref{expr.new}, and standard library -functions\iref{structure.specifications}. -\end{note} -An object is passed and the type of that object determines which handlers -can catch it. -\begin{example} -\begin{codeblock} -throw "Help!"; -\end{codeblock} -can be caught by a -\grammarterm{handler} -of -\keyword{const} -\tcode{\keyword{char}*} -type: -\begin{codeblock} -try { - // ... -} catch(const char* p) { - // handle character string exceptions here -} -\end{codeblock} -and -\begin{codeblock} -class Overflow { -public: - Overflow(char,double,double); -}; - -void f(double x) { - throw Overflow('+',x,3.45e107); -} -\end{codeblock} -can be caught by a handler for exceptions of type -\tcode{Overflow}: -\begin{codeblock} -try { - f(1.2); -} catch(Overflow& oo) { - // handle exceptions of type \tcode{Overflow} here -} -\end{codeblock} -\end{example} - -\pnum -\indextext{exception handling!throwing}% -\indextext{exception handling!handler}% -\indextext{exception handling!nearest handler}% -When an exception is thrown, control is transferred to the nearest handler with -a matching type\iref{except.handle}; ``nearest'' means the handler -for which the -\grammarterm{compound-statement} or -\grammarterm{ctor-initializer} -following the -\keyword{try} -keyword was most recently entered by the thread of control and not yet exited. - -\pnum -Throwing an exception -initializes an object with dynamic storage duration, -called the -\defnx{exception object}{exception handling!exception object}. -If the type of the exception object would be -an incomplete type\iref{basic.types.general}, -an abstract class type\iref{class.abstract}, -or a pointer to an incomplete type other than -\cv{}~\keyword{void}\iref{basic.compound}, -the program is ill-formed. - -\pnum -\indextext{exception handling!memory}% -\indextext{exception handling!rethrowing}% -\indextext{exception handling!exception object}% -The memory for the exception object is -allocated in an unspecified way, except as noted in~\ref{basic.stc.dynamic.allocation}. -If a handler exits by rethrowing, control is passed to another handler for -the same exception object. -The points of potential destruction for the exception object are: -\begin{itemize} -\item -when an active handler for the exception exits by -any means other than -rethrowing, -immediately after the destruction of the object (if any) -declared in the \grammarterm{exception-declaration} in the handler; - -\item -when an object of type \tcode{std::exception_ptr}\iref{propagation} -that refers to the exception object is destroyed, -before the destructor of \tcode{std::exception_ptr} returns. -\end{itemize} - -Among all points of potential destruction for the exception object, -there is an unspecified last one -where the exception object is destroyed. -All other points happen before that last one\iref{intro.races}. -\begin{note} -No other thread synchronization is implied in exception handling. -\end{note} -The implementation may then -deallocate the memory for the exception object; any such deallocation -is done in an unspecified way. -\begin{note} -A thrown exception does not -propagate to other threads unless caught, stored, and rethrown using -appropriate library functions; see~\ref{propagation} and~\ref{futures}. -\end{note} - -\pnum -\indextext{exception handling!exception object!constructor}% -\indextext{exception handling!exception object!destructor}% -Let \tcode{T} denote the type of the exception object. -Copy-initialization of an object of type \tcode{T} from -an lvalue of type \tcode{const T} in a context unrelated to \tcode{T} -shall be well-formed. -If \tcode{T} is a class type, -the selected constructor is odr-used\iref{basic.def.odr} and -the destructor of \tcode{T} is potentially invoked\iref{class.dtor}. - -\pnum -\indextext{exception handling!rethrow}% -\indextext{rethrow|see{exception handling, rethrow}}% -An exception is considered caught when a handler for that exception -becomes active\iref{except.handle}. -\begin{note} -An exception can have active handlers and still be considered uncaught if -it is rethrown. -\end{note} - -\pnum -\indextext{exception handling!terminate called@\tcode{terminate} called}% -\indextext{\idxcode{terminate}!called}% -If the exception handling mechanism -handling an uncaught exception\iref{except.uncaught} -directly invokes a function that exits via an -exception, the function \tcode{std::terminate} is invoked\iref{except.terminate}. -\begin{example} -\begin{codeblock} -struct C { - C() { } - C(const C&) { - if (std::uncaught_exceptions()) { - throw 0; // throw during copy to handler's \grammarterm{exception-declaration} object\iref{except.handle} - } - } -}; - -int main() { - try { - throw C(); // calls \tcode{std::terminate} if construction of the handler's - // \grammarterm{exception-declaration} object is not elided\iref{class.copy.elision} - } catch(C) { } -} -\end{codeblock} -\end{example} -\begin{note} -If a destructor directly invoked by stack unwinding exits via an exception, -\tcode{std::terminate} is invoked. -\end{note} - - -\rSec1[except.ctor]{Constructors and destructors}% -\indextext{exception handling!constructors and destructors}% -\indextext{constructor!exception handling|see{exception handling, constructors and destructors}}% -\indextext{destructor!exception handling|see{exception handling, constructors and destructors}} - -\pnum -\indextext{unwinding!stack}% -As control passes from the point where an exception is thrown -to a handler, -objects are destroyed by a process, -specified in this subclause, called \defn{stack unwinding}. - -\pnum -Each object with automatic storage duration is destroyed if it has been -constructed, but not yet destroyed, -since the try block was entered. -If an exception is thrown during the destruction of temporaries or -local variables for a \keyword{return} statement\iref{stmt.return}, -the destructor for the returned object (if any) is also invoked. -The objects are destroyed in the reverse order of the completion -of their construction. -\begin{example} -\begin{codeblock} -struct A { }; - -struct Y { ~Y() noexcept(false) { throw 0; } }; - -A f() { - try { - A a; - Y y; - A b; - return {}; // \#1 - } catch (...) { - } - return {}; // \#2 -} -\end{codeblock} -At \#1, the returned object of type \tcode{A} is constructed. -Then, the local variable \tcode{b} is destroyed\iref{stmt.jump}. -Next, the local variable \tcode{y} is destroyed, -causing stack unwinding, -resulting in the destruction of the returned object, -followed by the destruction of the local variable \tcode{a}. -Finally, the returned object is constructed again at \#2. -\end{example} - -\pnum -If the initialization of an object -other than by delegating constructor -is terminated by an exception, -the destructor is invoked for -each of the object's subobjects -that were known to be initialized by the object's initialization and -whose initialization has completed\iref{dcl.init}. -\begin{note} -If such an object has a reference member -that extends the lifetime of a temporary object, -this ends the lifetime of the reference member, -so the lifetime of the temporary object is effectively not extended. -\end{note} -\indextext{subobject!initialized, known to be}% -A subobject is \defn{known to be initialized} -if it is not an anonymous union member and -its initialization is specified -\begin{itemize} -\item in \ref{class.base.init} for initialization by constructor, -\item in \ref{class.copy.ctor} for initialization by defaulted copy/move constructor, -\item in \ref{class.inhctor.init} for initialization by inherited constructor, -\item in \ref{dcl.init.aggr} for aggregate initialization, -\item in \ref{expr.prim.lambda.capture} for the initialization of -the closure object when evaluating a \grammarterm{lambda-expression}, -\item in \ref{dcl.init.general} for -default-initialization, value-initialization, or direct-initialization -of an array. -\end{itemize} -\begin{note} -This includes virtual base class subobjects -if the initialization -is for a complete object, and -can include variant members -that were nominated explicitly by -a \grammarterm{mem-initializer} or \grammarterm{designated-initializer-clause} or -that have a default member initializer. -\end{note} -If the destructor of an object is terminated by an exception, -each destructor invocation -that would be performed after executing the body of the destructor\iref{class.dtor} and -that has not yet begun execution -is performed. -\begin{note} -This includes virtual base class subobjects if -the destructor was invoked for a complete object. -\end{note} -The subobjects are destroyed in the reverse order of the completion of -their construction. Such destruction is sequenced before entering a -handler of the \grammarterm{function-try-block} of the constructor or destructor, -if any. - -\pnum -If the \grammarterm{compound-statement} -of the \grammarterm{function-body} -of a delegating constructor -for an object exits via -an exception, the object's destructor is invoked. -Such destruction is sequenced before entering a handler of the -\grammarterm{function-try-block} of a delegating constructor for that object, if any. - -\pnum -\begin{note} -If the object was allocated by a \grammarterm{new-expression}\iref{expr.new}, -the matching deallocation function\iref{basic.stc.dynamic.deallocation}, -if any, is called to free the storage occupied by the object. -\end{note} - - -\rSec1[except.handle]{Handling an exception} -\indextext{exception handling!handler|(}% - -\pnum -The -\grammarterm{exception-declaration} -in a -\grammarterm{handler} -describes the type(s) of exceptions that can cause -that -\grammarterm{handler} -to be entered. -\indextext{exception handling!handler!incomplete type in}% -\indextext{exception handling!handler!rvalue reference in}% -\indextext{exception handling!handler!array in}% -\indextext{exception handling!handler!pointer to function in}% -The -\grammarterm{exception-declaration} -shall not denote an incomplete type, an abstract class type, or an rvalue reference type. -The -\grammarterm{exception-declaration} -shall not denote a pointer or reference to an -incomplete type, other than ``pointer to \cv{}~\keyword{void}''. - -\pnum -A handler of type -\indextext{array!handler of type}% -``array of \tcode{T}'' or -\indextext{function!handler of type}% -function type \tcode{T} -is adjusted to be of type -``pointer to \tcode{T}''. - -\pnum -\indextext{exception handling!handler!match|(}% -A -\grammarterm{handler} -is a match for -an exception object -of type -\tcode{E} -if -\begin{itemize} -\item% -The \grammarterm{handler} is of type \cv{}~\tcode{T} or -\cv{}~\tcode{T\&} and -\tcode{E} and \tcode{T} -are the same type (ignoring the top-level \grammarterm{cv-qualifier}{s}), or -\item% -the \grammarterm{handler} is of type \cv{}~\tcode{T} or -\cv{}~\tcode{T\&} and -\tcode{T} is an unambiguous public base class of \tcode{E}, or -\item% -the \grammarterm{handler} is of type \cv{}~\tcode{T} or \tcode{const T\&} -where \tcode{T} is a pointer or pointer-to-member type and -\tcode{E} is a pointer or pointer-to-member type -that can be converted to \tcode{T} by one or more of -\begin{itemize} - -\item% -a standard pointer conversion\iref{conv.ptr} not involving conversions -to pointers to private or protected or ambiguous classes -\item% -a function pointer conversion\iref{conv.fctptr} -\item% -a qualification conversion\iref{conv.qual}, or - -\end{itemize} - -\item -the \grammarterm{handler} is of type \cv{}~\tcode{T} or \tcode{const T\&} where \tcode{T} is a pointer or pointer-to-member type and \tcode{E} is \tcode{std::nullptr_t}. - -\end{itemize} - -\begin{note} -A -\grammarterm{throw-expression} -whose operand is an integer literal with value zero does not match a handler of -pointer or pointer-to-member type. -A handler of reference to array or function type -is never a match for any exception object\iref{expr.throw}. -\end{note} - -\begin{example} -\begin{codeblock} -class Matherr { @\commentellip@ virtual void vf(); }; -class Overflow: public Matherr { @\commentellip@ }; -class Underflow: public Matherr { @\commentellip@ }; -class Zerodivide: public Matherr { @\commentellip@ }; - -void f() { - try { - g(); - } catch (Overflow oo) { - // ... - } catch (Matherr mm) { - // ... - } -} -\end{codeblock} -Here, the -\tcode{Overflow} -handler will catch exceptions of type -\tcode{Overflow} -and the -\tcode{Matherr} -handler will catch exceptions of type -\tcode{Matherr} -and of all types publicly derived from -\tcode{Matherr} -including exceptions of type -\tcode{Underflow} -and -\tcode{Zerodivide}. -\end{example} - -\pnum -The handlers for a try block are tried in order of appearance. -\begin{note} -This makes it possible to write handlers that can never be -executed, for example by placing a handler for a final derived class after -a handler for a corresponding unambiguous public base class. -\end{note} - -\pnum -A -\tcode{...} -in a handler's -\grammarterm{exception-declaration} -functions similarly to -\tcode{...} -in a function parameter declaration; -it specifies a match for any exception. -If present, a -\tcode{...} -handler shall be the last handler for its try block. - -\pnum -If no match is found among the handlers for a try block, -the search for a matching -handler continues in a dynamically surrounding try block -of the same thread. - -\pnum -A handler is considered \defnx{active}{exception handling!handler!active} when -initialization is complete for the parameter (if any) of the catch clause. -\begin{note} -The stack will have been unwound at that point. -\end{note} -Also, an implicit handler is considered active when -the function \tcode{std::terminate} -is entered due to a throw. A handler is no longer considered active when the -catch clause exits. - -\pnum -\indextext{currently handled exception|see{exception handling, currently handled exception}}% -The exception with the most recently activated handler that is -still active is called the -\defnx{currently handled exception}{exception handling!currently handled exception}. - -\pnum -If no matching handler is found, -the function \tcode{std::terminate} is invoked; -whether or not the stack is unwound before this invocation of -\tcode{std::terminate} -is \impldef{stack unwinding before invocation of -\tcode{std::terminate}}\iref{except.terminate}. - -\pnum -Referring to any non-static member or base class of an object -in the handler for a -\grammarterm{function-try-block} -of a constructor or destructor for that object results in undefined behavior. - -\pnum -Exceptions thrown in destructors of objects with static storage duration or in -constructors of objects associated with non-block variables with static storage duration are not caught by a -\grammarterm{function-try-block} -on -the \tcode{main} function\iref{basic.start.main}. -Exceptions thrown in destructors of objects with thread storage duration or in constructors of objects associated with non-block variables with thread storage duration are not caught by a -\grammarterm{function-try-block} -on the initial function of the thread. - -\pnum -If a \keyword{return} statement\iref{stmt.return} appears in a handler of the -\grammarterm{function-try-block} -of a -constructor, the program is ill-formed. - -\pnum -The currently handled exception -is rethrown if control reaches the end of a handler of the -\grammarterm{function-try-block} -of a constructor or destructor. -Otherwise, flowing off the end of -the \grammarterm{compound-statement} -of a \grammarterm{handler} -of a \grammarterm{function-try-block} -is equivalent to flowing off the end of -the \grammarterm{compound-statement} -of that function (see \ref{stmt.return}). - -\pnum -The variable declared by the \grammarterm{exception-declaration}, of type -\cv{}~\tcode{T} or \cv{}~\tcode{T\&}, is initialized from the exception object, -of type \tcode{E}, as follows: -\begin{itemize} -\item -if \tcode{T} is a base class of \tcode{E}, -the variable is copy-initialized\iref{dcl.init} -from an lvalue of type \tcode{T} designating the corresponding base class subobject -of the exception object; -\item otherwise, the variable is copy-initialized\iref{dcl.init} -from an lvalue of type \tcode{E} designating the exception object. -\end{itemize} - -The lifetime of the variable ends -when the handler exits, after the -destruction of any objects with automatic storage duration initialized -within the handler. - -\pnum -When the handler declares an object, -any changes to that object will not affect the exception object. -When the handler declares a reference to an object, -any changes to the referenced object are changes to the -exception object and will have effect should that object be rethrown.% -\indextext{exception handling!handler!match|)}% -\indextext{exception handling!handler|)} - -\rSec1[except.spec]{Exception specifications}% -\indextext{exception specification|(} - -\pnum -The predicate indicating whether a function cannot exit via an exception -is called the \defn{exception specification} of the function. -If the predicate is false, -the function has a -\indextext{exception specification!potentially-throwing}% -\defnx{potentially-throwing exception specification}% -{potentially-throwing!exception specification}, -otherwise it has a -\indextext{exception specification!non-throwing}% -\defn{non-throwing exception specification}. -The exception specification is either defined implicitly, -or defined explicitly -by using a \grammarterm{noexcept-specifier} -as a suffix of a function declarator\iref{dcl.fct}. - -\begin{bnf} -\nontermdef{noexcept-specifier}\br - \keyword{noexcept} \terminal{(} constant-expression \terminal{)}\br - \keyword{noexcept}\br -\end{bnf} - -\pnum -\indextext{exception specification!noexcept!constant expression and}% -In a \grammarterm{noexcept-specifier}, the \grammarterm{constant-expression}, -if supplied, shall be a contextually converted constant expression -of type \keyword{bool}\iref{expr.const}; -that constant expression is the exception specification of -the function type in which the \grammarterm{noexcept-specifier} appears. -A \tcode{(} token that follows \keyword{noexcept} is part of the -\grammarterm{noexcept-specifier} and does not commence an -initializer\iref{dcl.init}. -The \grammarterm{noexcept-specifier} \keyword{noexcept} -without a \grammarterm{constant-expression} -is -equivalent to the \grammarterm{noexcept-specifier} -\tcode{\keyword{noexcept}(\keyword{true})}. -\begin{example} -\begin{codeblock} -void f() noexcept(sizeof(char[2])); // error: narrowing conversion of value 2 to type \keyword{bool} -void g() noexcept(sizeof(char)); // OK, conversion of value 1 to type \keyword{bool} is non-narrowing -\end{codeblock} -\end{example} - -\pnum -If a declaration of a function -does not have a \grammarterm{noexcept-specifier}, -the declaration has a potentially throwing exception specification -unless it is a destructor or a deallocation function -or is defaulted on its first declaration, -in which cases the exception specification -is as specified below -and no other declaration for that function -shall have a \grammarterm{noexcept-specifier}. -In an explicit instantiation\iref{temp.explicit} -a \grammarterm{noexcept-specifier} may be specified, -but is not required. -If a \grammarterm{noexcept-specifier} is specified -in an explicit instantiation, -the exception specification shall be the same as -the exception specification of all other declarations of that function. -A diagnostic is required only if the -exception specifications are not the same -within a single translation unit. - -\pnum -\indextext{exception specification!virtual function and}% -If a virtual function has a -non-throwing exception specification, -all declarations, including the definition, of any function -that overrides that virtual function in any derived class -shall have a non-throwing -exception specification, -unless the overriding function is defined as deleted. -\begin{example} -\begin{codeblock} -struct B { - virtual void f() noexcept; - virtual void g(); - virtual void h() noexcept = delete; -}; - -struct D: B { - void f(); // error - void g() noexcept; // OK - void h() = delete; // OK -}; -\end{codeblock} - -The declaration of -\tcode{D::f} -is ill-formed because it -has a potentially-throwing exception specification, -whereas -\tcode{B::f} -has a non-throwing exception specification. -\end{example} - -\pnum -\indextext{exception handling!terminate called@\tcode{terminate} called}% -\indextext{\idxcode{terminate}!called}% -Whenever an exception is thrown -and the search for a handler\iref{except.handle} -encounters the outermost block of a function with a -non-throwing exception specification, -the function \tcode{std::terminate} is invoked\iref{except.terminate}. -\begin{note} -An implementation is not permitted to reject an expression merely because, when -executed, it throws or might -throw an exception from a function with a non-throwing exception specification. -\end{note} -\begin{example} -\begin{codeblock} -extern void f(); // potentially-throwing - -void g() noexcept { - f(); // valid, even if \tcode{f} throws - throw 42; // valid, effectively a call to \tcode{std::terminate} -} -\end{codeblock} -The call to -\tcode{f} -is well-formed despite the possibility for it to throw an exception. -\end{example} - -\pnum -An expression $E$ is -\defnx{potentially-throwing}{potentially-throwing!expression} if -\begin{itemize} -\item -$E$ is a function call\iref{expr.call} -whose \grammarterm{postfix-expression} -has a function type, -or a pointer-to-function type, -with a potentially-throwing exception specification, -or -\item -$E$ implicitly invokes a function -(such as an overloaded operator, -an allocation function in a \grammarterm{new-expression}, -a constructor for a function argument, -or a destructor if $E$ is a full-expression\iref{intro.execution}) -that has a potentially-throwing exception specification, -or -\item -$E$ is a \grammarterm{throw-expression}\iref{expr.throw}, -or -\item -$E$ is a \keyword{dynamic_cast} expression that casts to a reference type and -requires a runtime check\iref{expr.dynamic.cast}, -or -\item -$E$ is a \keyword{typeid} expression applied to a -(possibly parenthesized) built-in unary \tcode{*} operator -applied to a pointer to a -polymorphic class type\iref{expr.typeid}, -or -\item -any of the immediate subexpressions\iref{intro.execution} -of $E$ is potentially-throwing. -\end{itemize} - -\pnum -An implicitly-declared constructor for a class \tcode{X}, -or a constructor without a \grammarterm{noexcept-specifier} -that is defaulted on its first declaration, -has a potentially-throwing exception specification -if and only if -any of the following constructs is potentially-throwing: -\begin{itemize} -\item -the invocation of a constructor selected by overload resolution -in the implicit definition of the constructor -for class \tcode{X} -to initialize a potentially constructed subobject, or -\item -a subexpression of such an initialization, -such as a default argument expression, or, -\item -for a default constructor, a default member initializer. -\end{itemize} -\begin{note} -Even though destructors for fully-constructed subobjects -are invoked when an exception is thrown -during the execution of a constructor\iref{except.ctor}, -their exception specifications do not contribute -to the exception specification of the constructor, -because an exception thrown from such a destructor -would call the function \tcode{std::terminate} -rather than escape the constructor\iref{except.throw,except.terminate}. -\end{note} - -\pnum -The exception specification for an implicitly-declared destructor, -or a destructor without a \grammarterm{noexcept-specifier}, -is potentially-throwing if and only if -any of the destructors -for any of its potentially constructed subobjects -has a potentially-throwing exception specification or -the destructor is virtual and the destructor of any virtual base class -has a potentially-throwing exception specification. - -\pnum -The exception specification for an implicitly-declared assignment operator, -or an assignment-operator without a \grammarterm{noexcept-specifier} -that is defaulted on its first declaration, -is potentially-throwing if and only if -the invocation of any assignment operator -in the implicit definition is potentially-throwing. - -\pnum -A deallocation function\iref{basic.stc.dynamic.deallocation} -with no explicit \grammarterm{noexcept-specifier} -has a non-throwing exception specification. - -\pnum -The exception specification for a comparison operator function\iref{over.binary} -without a \grammarterm{noexcept-specifier} -that is defaulted on its first declaration -is potentially-throwing if and only if -any expression -in the implicit definition is potentially-throwing. - -\pnum -\begin{example} -\begin{codeblock} -struct A { - A(int = (A(5), 0)) noexcept; - A(const A&) noexcept; - A(A&&) noexcept; - ~A(); -}; -struct B { - B() noexcept; - B(const B&) = default; // implicit exception specification is \tcode{\keyword{noexcept}(\keyword{true})} - B(B&&, int = (throw 42, 0)) noexcept; - ~B() noexcept(false); -}; -int n = 7; -struct D : public A, public B { - int * p = new int[n]; - // \tcode{D::D()} potentially-throwing, as the \keyword{new} operator may throw \tcode{bad_alloc} or \tcode{bad_array_new_length} - // \tcode{D::D(const D\&)} non-throwing - // \tcode{D::D(D\&\&)} potentially-throwing, as the default argument for \tcode{B}'s constructor may throw - // \tcode{D::\~D()} potentially-throwing -}; -\end{codeblock} -Furthermore, if -\tcode{A::\~{}A()} -were virtual, -the program would be ill-formed since a function that overrides a virtual -function from a base class -shall not have a potentially-throwing exception specification -if the base class function has a non-throwing exception specification. -\end{example} - -\pnum -An exception specification is considered to be \defnx{needed}{needed!exception specification} when: -\begin{itemize} -\item in an expression, the function is selected by -overload resolution\iref{over.match,over.over}; - -\item the function is odr-used\iref{term.odr.use} or, if it appears in an -unevaluated operand, would be odr-used if the expression were -potentially-evaluated; - -\item the exception specification is compared to that of another -declaration (e.g., an explicit specialization or an overriding virtual -function); - -\item the function is defined; or - -\item the exception specification is needed for a defaulted -function that calls the function. -\begin{note} -A defaulted declaration does not require the -exception specification of a base member function to be evaluated -until the implicit exception specification of the derived -function is needed, but an explicit \grammarterm{noexcept-specifier} needs -the implicit exception specification to compare against. -\end{note} -\end{itemize} -The exception specification of a defaulted -function is evaluated as described above only when needed; similarly, the -\grammarterm{noexcept-specifier} of a specialization of a function -template or member function of a class template is instantiated only when -needed. -% -\indextext{exception specification|)} - -\rSec1[except.special]{Special functions} - -\rSec2[except.special.general]{General} - -\pnum -The function \tcode{std::terminate}\iref{except.terminate} -is used by the exception -handling mechanism for coping with errors related to the exception handling -mechanism itself. The function -\tcode{std::current_exception()}\iref{propagation} and the class -\tcode{std::nested_exception}\iref{except.nested} can be used by a program to -capture the currently handled exception. - -\rSec2[except.terminate]{The \tcode{std::terminate} function} - -\pnum -\indextext{\idxcode{terminate}}% -% FIXME: What does it mean to abandon exception handling? -In some situations, exception handling is abandoned -for less subtle error handling techniques. -\begin{note} -These situations are: -\indextext{\idxcode{terminate}!called}% -\begin{itemize} -\item% -when the exception handling mechanism, after completing -the initialization of the exception object -but before -activation of a handler for the exception\iref{except.throw}, -calls a function that exits -via an exception, or - -\item% -when the exception handling mechanism cannot find a handler for a thrown exception\iref{except.handle}, or - -\item when the search for a handler\iref{except.handle} encounters the -outermost block of a function -with a non-throwing exception specification\iref{except.spec}, or - -\item% -when the destruction of an object during stack unwinding\iref{except.ctor} -terminates by throwing an exception, or - -\item% -when initialization of a non-block -variable with static or thread storage duration\iref{basic.start.dynamic} -exits via an exception, or - -\item% -when destruction of an object with static or thread storage duration exits -via an exception\iref{basic.start.term}, or - -\item% -when execution of a function registered with -\tcode{std::atexit} or \tcode{std::at_quick_exit} -exits via an exception\iref{support.start.term}, or - -\item% -when a -\grammarterm{throw-expression}\iref{expr.throw} -with no operand attempts to rethrow an exception and no exception is being -handled\iref{except.throw}, or - -\item% -when the function \tcode{std::nested_exception::rethrow_nested} is called for an object -that has captured no exception\iref{except.nested}, or - -\item% -when execution of the initial function of a thread exits via -an exception\iref{thread.thread.constr}, or - -\item% -for a parallel algorithm whose \tcode{ExecutionPolicy} specifies such -behavior\iref{execpol.seq,execpol.par,execpol.parunseq}, -when execution of an element access function\iref{algorithms.parallel.defns} -of the parallel algorithm exits via an exception\iref{algorithms.parallel.exceptions}, or - -\item% -when the destructor or the move assignment operator is invoked on an object -of type \tcode{std::thread} that refers to -a joinable thread\iref{thread.thread.destr,thread.thread.assign}, or - -\item% -when a call to a \tcode{wait()}, \tcode{wait_until()}, or \tcode{wait_for()} -function on a condition variable\iref{thread.condition.condvar,thread.condition.condvarany} -fails to meet a postcondition, or - -\item% -when a callback invocation exits via an exception -when requesting stop on -a \tcode{std::stop_source} or -a \tcode{std::in\-place_stop_source}\iref{stopsource.mem,stopsource.inplace.mem}, -or in the constructor of -\tcode{std::stop_callback} or -\tcode{std::inplace_stop_callback}\iref{stopcallback.cons,stopcallback.inplace.cons} -when a callback invocation exits via an exception, or - -\item% -when a \tcode{run_loop} object is destroyed -that is still in the \tcode{running} state\iref{exec.run.loop}, or - -\item% -when \tcode{unhandled_stopped} is called on -a \tcode{with_awaitable_senders} object\iref{exec.with.awaitable.senders} -whose continuation is not a handle to a coroutine -whose promise type has an \tcode{unhandled_stopped} member function. - -\end{itemize} - -\end{note} - -\pnum -\indextext{\idxcode{terminate}}% -In such cases, -the function \tcode{std::terminate} is invoked\iref{exception.terminate}. -In the situation where no matching handler is found, it is -\impldef{stack unwinding before invocation of \tcode{std::terminate}} -whether or not the stack is unwound -before \tcode{std::terminate} is invoked. -In the situation where the search for a handler\iref{except.handle} encounters the -outermost block of a function -with a non-throwing exception specification\iref{except.spec}, it is -\impldef{whether stack is unwound before invoking the function \tcode{std::terminate} -when a \tcode{noexcept} specification is violated} -whether the stack is unwound, unwound partially, or not unwound at all -before the function \tcode{std::terminate} is invoked. -In all other situations, the stack shall not be unwound before -the function \tcode{std::terminate} -is invoked. -An implementation is not permitted to finish stack unwinding -prematurely based on a determination that the unwind process -will eventually cause an invocation of the function -\tcode{std::terminate}. - -\rSec2[except.uncaught]{The \tcode{std::uncaught_exceptions} function}% -\indexlibraryglobal{uncaught_exceptions} - -\pnum -An exception is considered uncaught -after completing the initialization of the exception object\iref{except.throw} -until completing the activation of a handler for the exception\iref{except.handle}. -\begin{note} -As a consequence, an exception is considered uncaught -during any stack unwinding resulting from it being thrown. -\end{note} -If an exception is rethrown\iref{expr.throw,propagation}, -it is considered uncaught from the point of rethrow -until the rethrown exception is caught. -The function \tcode{std::uncaught_exceptions}\iref{uncaught.exceptions} -returns the number of uncaught exceptions in the current thread.% -\indextext{exception handling|)} diff --git a/source/statements.tex b/source/statements.tex index 1e134ecee5..68d4416f33 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -19,8 +19,8 @@ \opt{attribute-specifier-seq} selection-statement\br \opt{attribute-specifier-seq} iteration-statement\br \opt{attribute-specifier-seq} jump-statement\br - declaration-statement\br - \opt{attribute-specifier-seq} try-block + \opt{attribute-specifier-seq} try-block\br + declaration-statement \end{bnf} \begin{bnf} @@ -1033,6 +1033,1160 @@ \indextext{label}% label\iref{stmt.label} located in the current function. +\rSec1[except]{Exception handling}% +\indextext{exception handling|(} + +\indextext{exception object|see{exception handling, exception object}}% +\indextext{object!exception|see{exception handling, exception object}} + +\rSec2[except.pre]{Preamble} + +\pnum +Exception handling provides a way of transferring control and information +from a point in the execution of a thread to an exception handler +associated with a point previously passed by the execution. +A handler will be invoked only by throwing an exception +in code executed in the handler's try block +or in functions called from the handler's try block. + +\indextext{\idxcode{try}}% +% +\begin{bnf} +\nontermdef{try-block}\br + \keyword{try} compound-statement handler-seq +\end{bnf} + +\indextext{\idxcode{try}}% +% +\begin{bnf} +\nontermdef{function-try-block}\br + \keyword{try} \opt{ctor-initializer} compound-statement handler-seq +\end{bnf} + +\begin{bnf} +\nontermdef{handler-seq}\br + handler \opt{handler-seq} +\end{bnf} + +\indextext{\idxcode{catch}}% +% +\begin{bnf} +\nontermdef{handler}\br + \keyword{catch} \terminal{(} exception-declaration \terminal{)} compound-statement +\end{bnf} + +\begin{bnf} +\nontermdef{exception-declaration}\br + \opt{attribute-specifier-seq} type-specifier-seq declarator\br + \opt{attribute-specifier-seq} type-specifier-seq \opt{abstract-declarator}\br + \terminal{...} +\end{bnf} + +The optional \grammarterm{attribute-specifier-seq} in an \grammarterm{exception-declaration} +appertains to the parameter of the catch clause\iref{except.handle}. + +\pnum +\indextext{exception handling!try block}% +\indextext{exception handling!handler}% +\indextext{try block|see{exception handling, try block}}% +\indextext{handler|see{exception handling, handler}}% +A \grammarterm{try-block} is a \grammarterm{statement}\iref{stmt.pre}. +\begin{note} +Within this Clause +``try block'' is taken to mean both \grammarterm{try-block} and +\grammarterm{function-try-block}. +\end{note} + +\pnum +\indextext{exception handling!\idxcode{goto}}% +\indextext{exception handling!\idxcode{switch}}% +\indextext{\idxcode{goto}!and try block}% +\indextext{\idxcode{switch}!and try block}% +\indextext{\idxcode{goto}!and handler}% +\indextext{\idxcode{switch}!and handler}% +The \grammarterm{compound-statement} of a try block or of a handler is a +control-flow-limited statement\iref{stmt.label}. +\begin{example} +\begin{codeblock} +void f() { + goto l1; // error + goto l2; // error + try { + goto l1; // OK + goto l2; // error + l1: ; + } catch (...) { + l2: ; + goto l1; // error + goto l2; // OK + } +} + +\end{codeblock} +\end{example} +\indextext{\idxcode{goto}!and try block}% +\indextext{\idxcode{switch}!and try block}% +\indextext{\idxcode{return}!and try block}% +\indextext{\idxcode{continue}!and try block}% +\indextext{\idxcode{goto}!and handler}% +\indextext{\idxcode{switch}!and handler}% +\indextext{\idxcode{return}!and handler}% +\indextext{\idxcode{continue}!and handler}% +A +\keyword{goto}, +\keyword{break}, +\keyword{return}, +or +\keyword{continue} +statement can be used to transfer control out of +a try block or handler. +When this happens, each variable declared in the try block +will be destroyed in the context that +directly contains its declaration. +\begin{example} +\begin{codeblock} +lab: try { + T1 t1; + try { + T2 t2; + if (@\grammarterm{condition}@) + goto lab; + } catch(...) { @\tcode{/* handler 2 */}@ } + } catch(...) { @\tcode{/* handler 1 */}@ } +\end{codeblock} + +Here, executing +\tcode{goto lab;} +will destroy first +\tcode{t2}, +then +\tcode{t1}, +assuming the +\grammarterm{condition} +does not declare a variable. +Any exception thrown while destroying +\tcode{t2} +will result in executing +\tcode{handler 2}; +any exception thrown while destroying +\tcode{t1} +will result in executing +\tcode{handler 1}. +\end{example} + +\pnum +\indextext{function try block|see{exception handling, function try block}}% +\indextext{exception handling!function try block}% +A +\grammarterm{function-try-block} +associates a +\grammarterm{handler-seq} +with the +\grammarterm{ctor-initializer}, +if present, and the +\grammarterm{compound-statement}. +An exception +thrown during the execution of the +\grammarterm{compound-statement} +or, for constructors and destructors, during the initialization or +destruction, respectively, of the class's subobjects, +transfers control to a handler in a +\grammarterm{function-try-block} +in the same way as an exception thrown during the execution of a +\grammarterm{try-block} +transfers control to other handlers. +\begin{example} +\begin{codeblock} +int f(int); +class C { + int i; + double d; +public: + C(int, double); +}; + +C::C(int ii, double id) +try : i(f(ii)), d(id) { + // constructor statements +} catch (...) { + // handles exceptions thrown from the ctor-initializer and from the constructor statements +} +\end{codeblock} +\end{example} + +\pnum +In this Clause, ``before'' and ``after'' refer to the +``sequenced before'' relation\iref{intro.execution}. + +\rSec2[except.throw]{Throwing an exception}% +\indextext{exception handling!throwing}% +\indextext{throwing|see{exception handling, throwing}} + +\pnum +Throwing an exception transfers control to a handler. +\begin{note} +An exception can be thrown from one of the following contexts: +\grammarterm{throw-expression}{s}\iref{expr.throw}, +allocation functions\iref{basic.stc.dynamic.allocation}, +\keyword{dynamic_cast}\iref{expr.dynamic.cast}, +\keyword{typeid}\iref{expr.typeid}, +\grammarterm{new-expression}{s}\iref{expr.new}, and standard library +functions\iref{structure.specifications}. +\end{note} +An object is passed and the type of that object determines which handlers +can catch it. +\begin{example} +\begin{codeblock} +throw "Help!"; +\end{codeblock} +can be caught by a +\grammarterm{handler} +of +\keyword{const} +\tcode{\keyword{char}*} +type: +\begin{codeblock} +try { + // ... +} catch(const char* p) { + // handle character string exceptions here +} +\end{codeblock} +and +\begin{codeblock} +class Overflow { +public: + Overflow(char,double,double); +}; + +void f(double x) { + throw Overflow('+',x,3.45e107); +} +\end{codeblock} +can be caught by a handler for exceptions of type +\tcode{Overflow}: +\begin{codeblock} +try { + f(1.2); +} catch(Overflow& oo) { + // handle exceptions of type \tcode{Overflow} here +} +\end{codeblock} +\end{example} + +\pnum +\indextext{exception handling!throwing}% +\indextext{exception handling!handler}% +\indextext{exception handling!nearest handler}% +When an exception is thrown, control is transferred to the nearest handler with +a matching type\iref{except.handle}; ``nearest'' means the handler +for which the +\grammarterm{compound-statement} or +\grammarterm{ctor-initializer} +following the +\keyword{try} +keyword was most recently entered by the thread of control and not yet exited. + +\pnum +Throwing an exception +initializes an object with dynamic storage duration, +called the +\defnx{exception object}{exception handling!exception object}. +If the type of the exception object would be +an incomplete type\iref{basic.types.general}, +an abstract class type\iref{class.abstract}, +or a pointer to an incomplete type other than +\cv{}~\keyword{void}\iref{basic.compound}, +the program is ill-formed. + +\pnum +\indextext{exception handling!memory}% +\indextext{exception handling!rethrowing}% +\indextext{exception handling!exception object}% +The memory for the exception object is +allocated in an unspecified way, except as noted in~\ref{basic.stc.dynamic.allocation}. +If a handler exits by rethrowing, control is passed to another handler for +the same exception object. +The points of potential destruction for the exception object are: +\begin{itemize} +\item +when an active handler for the exception exits by +any means other than +rethrowing, +immediately after the destruction of the object (if any) +declared in the \grammarterm{exception-declaration} in the handler; + +\item +when an object of type \tcode{std::exception_ptr}\iref{propagation} +that refers to the exception object is destroyed, +before the destructor of \tcode{std::exception_ptr} returns. +\end{itemize} + +Among all points of potential destruction for the exception object, +there is an unspecified last one +where the exception object is destroyed. +All other points happen before that last one\iref{intro.races}. +\begin{note} +No other thread synchronization is implied in exception handling. +\end{note} +The implementation may then +deallocate the memory for the exception object; any such deallocation +is done in an unspecified way. +\begin{note} +A thrown exception does not +propagate to other threads unless caught, stored, and rethrown using +appropriate library functions; see~\ref{propagation} and~\ref{futures}. +\end{note} + +\pnum +\indextext{exception handling!exception object!constructor}% +\indextext{exception handling!exception object!destructor}% +Let \tcode{T} denote the type of the exception object. +Copy-initialization of an object of type \tcode{T} from +an lvalue of type \tcode{const T} in a context unrelated to \tcode{T} +shall be well-formed. +If \tcode{T} is a class type, +the selected constructor is odr-used\iref{basic.def.odr} and +the destructor of \tcode{T} is potentially invoked\iref{class.dtor}. + +\pnum +An exception is considered uncaught +after completing the initialization of the exception object +until completing the activation of a handler for the exception\iref{except.handle}. +\begin{note} +As a consequence, an exception is considered uncaught +during any stack unwinding resulting from it being thrown. +\end{note} + +\pnum +\indextext{exception handling!rethrow}% +\indextext{rethrow|see{exception handling, rethrow}}% +An exception is considered caught when a handler for that exception +becomes active\iref{except.handle}. +\begin{note} +An exception can have active handlers and still be considered uncaught if +it is rethrown. +\end{note} + +\pnum +If an exception is rethrown\iref{expr.throw,propagation}, +it is considered uncaught from the point of rethrow +until the rethrown exception is caught. +\indexlibraryglobal{uncaught_exceptions}% +\begin{note} +The function \tcode{std::uncaught_exceptions}\iref{uncaught.exceptions} +returns the number of uncaught exceptions in the current thread. +\end{note} + +\pnum +\indextext{exception handling!terminate called@\tcode{terminate} called}% +\indextext{\idxcode{terminate}!called}% +If the exception handling mechanism +handling an uncaught exception +directly invokes a function that exits via an +exception, the function \tcode{std::terminate} is invoked\iref{except.terminate}. +\begin{example} +\begin{codeblock} +struct C { + C() { } + C(const C&) { + if (std::uncaught_exceptions()) { + throw 0; // throw during copy to handler's \grammarterm{exception-declaration} object\iref{except.handle} + } + } +}; + +int main() { + try { + throw C(); // calls \tcode{std::terminate} if construction of the handler's + // \grammarterm{exception-declaration} object is not elided\iref{class.copy.elision} + } catch(C) { } +} +\end{codeblock} +\end{example} +\begin{note} +If a destructor directly invoked by stack unwinding exits via an exception, +\tcode{std::terminate} is invoked. +\end{note} + + +\rSec2[except.ctor]{Constructors and destructors}% +\indextext{exception handling!constructors and destructors}% +\indextext{constructor!exception handling|see{exception handling, constructors and destructors}}% +\indextext{destructor!exception handling|see{exception handling, constructors and destructors}} + +\pnum +\indextext{unwinding!stack}% +As control passes from the point where an exception is thrown +to a handler, +objects are destroyed by a process, +specified in this subclause, called \defn{stack unwinding}. + +\pnum +Each object with automatic storage duration is destroyed if it has been +constructed, but not yet destroyed, +since the try block was entered. +If an exception is thrown during the destruction of temporaries or +local variables for a \keyword{return} statement\iref{stmt.return}, +the destructor for the returned object (if any) is also invoked. +The objects are destroyed in the reverse order of the completion +of their construction. +\begin{example} +\begin{codeblock} +struct A { }; + +struct Y { ~Y() noexcept(false) { throw 0; } }; + +A f() { + try { + A a; + Y y; + A b; + return {}; // \#1 + } catch (...) { + } + return {}; // \#2 +} +\end{codeblock} +At \#1, the returned object of type \tcode{A} is constructed. +Then, the local variable \tcode{b} is destroyed\iref{stmt.jump}. +Next, the local variable \tcode{y} is destroyed, +causing stack unwinding, +resulting in the destruction of the returned object, +followed by the destruction of the local variable \tcode{a}. +Finally, the returned object is constructed again at \#2. +\end{example} + +\pnum +If the initialization of an object +other than by delegating constructor +is terminated by an exception, +the destructor is invoked for +each of the object's subobjects +that were known to be initialized by the object's initialization and +whose initialization has completed\iref{dcl.init}. +\begin{note} +If such an object has a reference member +that extends the lifetime of a temporary object, +this ends the lifetime of the reference member, +so the lifetime of the temporary object is effectively not extended. +\end{note} +\indextext{subobject!initialized, known to be}% +A subobject is \defn{known to be initialized} +if it is not an anonymous union member and +its initialization is specified +\begin{itemize} +\item in \ref{expr.prim.lambda.capture} for the initialization of +the closure object when evaluating a \grammarterm{lambda-expression}, +\item in \ref{dcl.init.general} for +default-initialization, value-initialization, or direct-initialization +of an array, +\item in \ref{dcl.init.aggr} for aggregate initialization, +\item in \ref{class.copy.ctor} for initialization by defaulted copy/move constructor, +\item in \ref{class.base.init} for initialization by constructor, +\item in \ref{class.inhctor.init} for initialization by inherited constructor. +\end{itemize} +\begin{note} +This includes virtual base class subobjects +if the initialization +is for a complete object, and +can include variant members +that were nominated explicitly by +a \grammarterm{mem-initializer} or \grammarterm{designated-initializer-clause} or +that have a default member initializer. +\end{note} +If the destructor of an object is terminated by an exception, +each destructor invocation +that would be performed after executing the body of the destructor\iref{class.dtor} and +that has not yet begun execution +is performed. +\begin{note} +This includes virtual base class subobjects if +the destructor was invoked for a complete object. +\end{note} +The subobjects are destroyed in the reverse order of the completion of +their construction. Such destruction is sequenced before entering a +handler of the \grammarterm{function-try-block} of the constructor or destructor, +if any. + +\pnum +If the \grammarterm{compound-statement} +of the \grammarterm{function-body} +of a delegating constructor +for an object exits via +an exception, the object's destructor is invoked. +Such destruction is sequenced before entering a handler of the +\grammarterm{function-try-block} of a delegating constructor for that object, if any. + +\pnum +\begin{note} +If the object was allocated by a \grammarterm{new-expression}\iref{expr.new}, +the matching deallocation function\iref{basic.stc.dynamic.deallocation}, +if any, is called to free the storage occupied by the object. +\end{note} + + +\rSec2[except.handle]{Handling an exception} +\indextext{exception handling!handler|(}% + +\pnum +The +\grammarterm{exception-declaration} +in a +\grammarterm{handler} +describes the type(s) of exceptions that can cause +that +\grammarterm{handler} +to be entered. +\indextext{exception handling!handler!incomplete type in}% +\indextext{exception handling!handler!rvalue reference in}% +\indextext{exception handling!handler!array in}% +\indextext{exception handling!handler!pointer to function in}% +The +\grammarterm{exception-declaration} +shall not denote an incomplete type, an abstract class type, or an rvalue reference type. +The +\grammarterm{exception-declaration} +shall not denote a pointer or reference to an +incomplete type, other than ``pointer to \cv{}~\keyword{void}''. + +\pnum +A handler of type +\indextext{array!handler of type}% +``array of \tcode{T}'' or +\indextext{function!handler of type}% +function type \tcode{T} +is adjusted to be of type +``pointer to \tcode{T}''. + +\pnum +\indextext{exception handling!handler!match|(}% +A +\grammarterm{handler} +is a match for +an exception object +of type +\tcode{E} +if +\begin{itemize} +\item% +The \grammarterm{handler} is of type \cv{}~\tcode{T} or +\cv{}~\tcode{T\&} and +\tcode{E} and \tcode{T} +are the same type (ignoring the top-level \grammarterm{cv-qualifier}{s}), or +\item% +the \grammarterm{handler} is of type \cv{}~\tcode{T} or +\cv{}~\tcode{T\&} and +\tcode{T} is an unambiguous public base class of \tcode{E}, or +\item% +the \grammarterm{handler} is of type \cv{}~\tcode{T} or \tcode{const T\&} +where \tcode{T} is a pointer or pointer-to-member type and +\tcode{E} is a pointer or pointer-to-member type +that can be converted to \tcode{T} by one or more of +\begin{itemize} + +\item% +a standard pointer conversion\iref{conv.ptr} not involving conversions +to pointers to private or protected or ambiguous classes +\item% +a function pointer conversion\iref{conv.fctptr} +\item% +a qualification conversion\iref{conv.qual}, or + +\end{itemize} + +\item +the \grammarterm{handler} is of type \cv{}~\tcode{T} or \tcode{const T\&} where \tcode{T} is a pointer or pointer-to-member type and \tcode{E} is \tcode{std::nullptr_t}. + +\end{itemize} + +\begin{note} +A +\grammarterm{throw-expression} +whose operand is an integer literal with value zero does not match a handler of +pointer or pointer-to-member type. +A handler of reference to array or function type +is never a match for any exception object\iref{expr.throw}. +\end{note} + +\begin{example} +\begin{codeblock} +class Matherr { @\commentellip@ virtual void vf(); }; +class Overflow: public Matherr { @\commentellip@ }; +class Underflow: public Matherr { @\commentellip@ }; +class Zerodivide: public Matherr { @\commentellip@ }; + +void f() { + try { + g(); + } catch (Overflow oo) { + // ... + } catch (Matherr mm) { + // ... + } +} +\end{codeblock} +Here, the +\tcode{Overflow} +handler will catch exceptions of type +\tcode{Overflow} +and the +\tcode{Matherr} +handler will catch exceptions of type +\tcode{Matherr} +and of all types publicly derived from +\tcode{Matherr} +including exceptions of type +\tcode{Underflow} +and +\tcode{Zerodivide}. +\end{example} + +\pnum +The handlers for a try block are tried in order of appearance. +\begin{note} +This makes it possible to write handlers that can never be +executed, for example by placing a handler for a final derived class after +a handler for a corresponding unambiguous public base class. +\end{note} + +\pnum +A +\tcode{...} +in a handler's +\grammarterm{exception-declaration} +functions similarly to +\tcode{...} +in a function parameter declaration; +it specifies a match for any exception. +If present, a +\tcode{...} +handler shall be the last handler for its try block. + +\pnum +If no match is found among the handlers for a try block, +the search for a matching +handler continues in a dynamically surrounding try block +of the same thread. + +\pnum +A handler is considered \defnx{active}{exception handling!handler!active} when +initialization is complete for the parameter (if any) of the catch clause. +\begin{note} +The stack will have been unwound at that point. +\end{note} +Also, an implicit handler is considered active when +the function \tcode{std::terminate} +is entered due to a throw. A handler is no longer considered active when the +catch clause exits. + +\pnum +\indextext{currently handled exception|see{exception handling, currently handled exception}}% +The exception with the most recently activated handler that is +still active is called the +\defnx{currently handled exception}{exception handling!currently handled exception}. + +\pnum +If no matching handler is found, +the function \tcode{std::terminate} is invoked; +whether or not the stack is unwound before this invocation of +\tcode{std::terminate} +is \impldef{stack unwinding before invocation of +\tcode{std::terminate}}\iref{except.terminate}. + +\pnum +Referring to any non-static member or base class of an object +in the handler for a +\grammarterm{function-try-block} +of a constructor or destructor for that object results in undefined behavior. + +\pnum +Exceptions thrown in destructors of objects with static storage duration or in +constructors of objects associated with non-block variables with static storage duration are not caught by a +\grammarterm{function-try-block} +on +the \tcode{main} function\iref{basic.start.main}. +Exceptions thrown in destructors of objects with thread storage duration or in constructors of objects associated with non-block variables with thread storage duration are not caught by a +\grammarterm{function-try-block} +on the initial function of the thread. + +\pnum +If a \keyword{return} statement\iref{stmt.return} appears in a handler of the +\grammarterm{function-try-block} +of a +constructor, the program is ill-formed. + +\pnum +The currently handled exception +is rethrown if control reaches the end of a handler of the +\grammarterm{function-try-block} +of a constructor or destructor. +Otherwise, flowing off the end of +the \grammarterm{compound-statement} +of a \grammarterm{handler} +of a \grammarterm{function-try-block} +is equivalent to flowing off the end of +the \grammarterm{compound-statement} +of that function (see \ref{stmt.return}). + +\pnum +The variable declared by the \grammarterm{exception-declaration}, of type +\cv{}~\tcode{T} or \cv{}~\tcode{T\&}, is initialized from the exception object, +of type \tcode{E}, as follows: +\begin{itemize} +\item +if \tcode{T} is a base class of \tcode{E}, +the variable is copy-initialized\iref{dcl.init} +from an lvalue of type \tcode{T} designating the corresponding base class subobject +of the exception object; +\item otherwise, the variable is copy-initialized\iref{dcl.init} +from an lvalue of type \tcode{E} designating the exception object. +\end{itemize} + +The lifetime of the variable ends +when the handler exits, after the +destruction of any objects with automatic storage duration initialized +within the handler. + +\pnum +When the handler declares an object, +any changes to that object will not affect the exception object. +When the handler declares a reference to an object, +any changes to the referenced object are changes to the +exception object and will have effect should that object be rethrown.% +\indextext{exception handling!handler!match|)}% +\indextext{exception handling!handler|)} + +\rSec2[except.spec]{Exception specifications}% +\indextext{exception specification|(} + +\pnum +The predicate indicating whether a function cannot exit via an exception +is called the \defn{exception specification} of the function. +If the predicate is false, +the function has a +\indextext{exception specification!potentially-throwing}% +\defnx{potentially-throwing exception specification}% +{potentially-throwing!exception specification}, +otherwise it has a +\indextext{exception specification!non-throwing}% +\defn{non-throwing exception specification}. +The exception specification is either defined implicitly, +or defined explicitly +by using a \grammarterm{noexcept-specifier} +as a suffix of a function declarator\iref{dcl.fct}. + +\begin{bnf} +\nontermdef{noexcept-specifier}\br + \keyword{noexcept} \terminal{(} constant-expression \terminal{)}\br + \keyword{noexcept}\br +\end{bnf} + +\pnum +\indextext{exception specification!noexcept!constant expression and}% +In a \grammarterm{noexcept-specifier}, the \grammarterm{constant-expression}, +if supplied, shall be a contextually converted constant expression +of type \keyword{bool}\iref{expr.const}; +that constant expression is the exception specification of +the function type in which the \grammarterm{noexcept-specifier} appears. +A \tcode{(} token that follows \keyword{noexcept} is part of the +\grammarterm{noexcept-specifier} and does not commence an +initializer\iref{dcl.init}. +The \grammarterm{noexcept-specifier} \keyword{noexcept} +without a \grammarterm{constant-expression} +is +equivalent to the \grammarterm{noexcept-specifier} +\tcode{\keyword{noexcept}(\keyword{true})}. +\begin{example} +\begin{codeblock} +void f() noexcept(sizeof(char[2])); // error: narrowing conversion of value 2 to type \keyword{bool} +void g() noexcept(sizeof(char)); // OK, conversion of value 1 to type \keyword{bool} is non-narrowing +\end{codeblock} +\end{example} + +\pnum +If a declaration of a function +does not have a \grammarterm{noexcept-specifier}, +the declaration has a potentially throwing exception specification +unless it is a destructor or a deallocation function +or is defaulted on its first declaration, +in which cases the exception specification +is as specified below +and no other declaration for that function +shall have a \grammarterm{noexcept-specifier}. +In an explicit instantiation\iref{temp.explicit} +a \grammarterm{noexcept-specifier} may be specified, +but is not required. +If a \grammarterm{noexcept-specifier} is specified +in an explicit instantiation, +the exception specification shall be the same as +the exception specification of all other declarations of that function. +A diagnostic is required only if the +exception specifications are not the same +within a single translation unit. + +\pnum +\indextext{exception specification!virtual function and}% +If a virtual function has a +non-throwing exception specification, +all declarations, including the definition, of any function +that overrides that virtual function in any derived class +shall have a non-throwing +exception specification, +unless the overriding function is defined as deleted. +\begin{example} +\begin{codeblock} +struct B { + virtual void f() noexcept; + virtual void g(); + virtual void h() noexcept = delete; +}; + +struct D: B { + void f(); // error + void g() noexcept; // OK + void h() = delete; // OK +}; +\end{codeblock} + +The declaration of +\tcode{D::f} +is ill-formed because it +has a potentially-throwing exception specification, +whereas +\tcode{B::f} +has a non-throwing exception specification. +\end{example} + +\pnum +\indextext{exception handling!terminate called@\tcode{terminate} called}% +\indextext{\idxcode{terminate}!called}% +Whenever an exception is thrown +and the search for a handler\iref{except.handle} +encounters the outermost block of a function with a +non-throwing exception specification, +the function \tcode{std::terminate} is invoked\iref{except.terminate}. +\begin{note} +An implementation is not permitted to reject an expression merely because, when +executed, it throws or might +throw an exception from a function with a non-throwing exception specification. +\end{note} +\begin{example} +\begin{codeblock} +extern void f(); // potentially-throwing + +void g() noexcept { + f(); // valid, even if \tcode{f} throws + throw 42; // valid, effectively a call to \tcode{std::terminate} +} +\end{codeblock} +The call to +\tcode{f} +is well-formed despite the possibility for it to throw an exception. +\end{example} + +\pnum +An expression $E$ is +\defnx{potentially-throwing}{potentially-throwing!expression} if +\begin{itemize} +\item +$E$ is a \grammarterm{throw-expression}\iref{expr.throw}, +or +\item +$E$ implicitly invokes a function +(such as an overloaded operator, +an allocation function in a \grammarterm{new-expression}, +a constructor for a function argument, +or a destructor if $E$ is a full-expression\iref{intro.execution}) +that has a potentially-throwing exception specification, +or +\item +any of the immediate subexpressions\iref{intro.execution} +of $E$ is potentially-throwing, +or +\item +$E$ is a function call\iref{expr.call} +whose \grammarterm{postfix-expression} +has a function type, +or a pointer-to-function type, +with a potentially-throwing exception specification, +or +\item +$E$ is a \keyword{dynamic_cast} expression that casts to a reference type and +requires a runtime check\iref{expr.dynamic.cast}, +or +\item +$E$ is a \keyword{typeid} expression applied to a +(possibly parenthesized) built-in unary \tcode{*} operator +applied to a pointer to a +polymorphic class type\iref{expr.typeid}. +\end{itemize} + +\pnum +An implicitly-declared constructor for a class \tcode{X}, +or a constructor without a \grammarterm{noexcept-specifier} +that is defaulted on its first declaration, +has a potentially-throwing exception specification +if and only if +any of the following constructs is potentially-throwing: +\begin{itemize} +\item +the invocation of a constructor selected by overload resolution +in the implicit definition of the constructor +for class \tcode{X} +to initialize a potentially constructed subobject, or +\item +a subexpression of such an initialization, +such as a default argument expression, or, +\item +for a default constructor, a default member initializer. +\end{itemize} +\begin{note} +Even though destructors for fully-constructed subobjects +are invoked when an exception is thrown +during the execution of a constructor\iref{except.ctor}, +their exception specifications do not contribute +to the exception specification of the constructor, +because an exception thrown from such a destructor +would call the function \tcode{std::terminate} +rather than escape the constructor\iref{except.throw,except.terminate}. +\end{note} + +\pnum +The exception specification for an implicitly-declared destructor, +or a destructor without a \grammarterm{noexcept-specifier}, +is potentially-throwing if and only if +any of the destructors +for any of its potentially constructed subobjects +has a potentially-throwing exception specification or +the destructor is virtual and the destructor of any virtual base class +has a potentially-throwing exception specification. + +\pnum +The exception specification for an implicitly-declared assignment operator, +or an assignment-operator without a \grammarterm{noexcept-specifier} +that is defaulted on its first declaration, +is potentially-throwing if and only if +the invocation of any assignment operator +in the implicit definition is potentially-throwing. + +\pnum +A deallocation function\iref{basic.stc.dynamic.deallocation} +with no explicit \grammarterm{noexcept-specifier} +has a non-throwing exception specification. + +\pnum +The exception specification for a comparison operator function\iref{over.binary} +without a \grammarterm{noexcept-specifier} +that is defaulted on its first declaration +is potentially-throwing if and only if +any expression +in the implicit definition is potentially-throwing. + +\pnum +\begin{example} +\begin{codeblock} +struct A { + A(int = (A(5), 0)) noexcept; + A(const A&) noexcept; + A(A&&) noexcept; + ~A(); +}; +struct B { + B() noexcept; + B(const B&) = default; // implicit exception specification is \tcode{\keyword{noexcept}(\keyword{true})} + B(B&&, int = (throw 42, 0)) noexcept; + ~B() noexcept(false); +}; +int n = 7; +struct D : public A, public B { + int * p = new int[n]; + // \tcode{D::D()} potentially-throwing, as the \keyword{new} operator may throw \tcode{bad_alloc} or \tcode{bad_array_new_length} + // \tcode{D::D(const D\&)} non-throwing + // \tcode{D::D(D\&\&)} potentially-throwing, as the default argument for \tcode{B}'s constructor may throw + // \tcode{D::\~D()} potentially-throwing +}; +\end{codeblock} +Furthermore, if +\tcode{A::\~{}A()} +were virtual, +the program would be ill-formed since a function that overrides a virtual +function from a base class +shall not have a potentially-throwing exception specification +if the base class function has a non-throwing exception specification. +\end{example} + +\pnum +An exception specification is considered to be \defnx{needed}{needed!exception specification} when: +\begin{itemize} +\item in an expression, the function is selected by +overload resolution\iref{over.match,over.over}; + +\item the function is odr-used\iref{term.odr.use} or, if it appears in an +unevaluated operand, would be odr-used if the expression were +potentially-evaluated; + +\item the exception specification is compared to that of another +declaration (e.g., an explicit specialization or an overriding virtual +function); + +\item the function is defined; or + +\item the exception specification is needed for a defaulted +function that calls the function. +\begin{note} +A defaulted declaration does not require the +exception specification of a base member function to be evaluated +until the implicit exception specification of the derived +function is needed, but an explicit \grammarterm{noexcept-specifier} needs +the implicit exception specification to compare against. +\end{note} +\end{itemize} +The exception specification of a defaulted +function is evaluated as described above only when needed; similarly, the +\grammarterm{noexcept-specifier} of a specialization of a function +template or member function of a class template is instantiated only when +needed. +% +\indextext{exception specification|)} + +\rSec2[except.special]{Special functions} + +\rSec3[except.special.general]{General} + +\pnum +The function \tcode{std::terminate}\iref{except.terminate} +is used by the exception +handling mechanism for coping with errors related to the exception handling +mechanism itself. +The function \tcode{std::uncaught_exceptions}\iref{uncaught.exceptions} +reports how many exceptions are uncaught in the current thread. +The function \tcode{std::current_exception}\iref{propagation} and the class +\tcode{std::nested_exception}\iref{except.nested} can be used by a program to +capture the currently handled exception. + +\rSec3[except.terminate]{The \tcode{std::terminate} function} + +\pnum +\indextext{\idxcode{terminate}}% +% FIXME: What does it mean to abandon exception handling? +In some situations, exception handling is abandoned +for less subtle error handling techniques. +\begin{note} +These situations are: +\indextext{\idxcode{terminate}!called}% +\begin{itemize} +\item% +when the exception handling mechanism, after completing +the initialization of the exception object +but before +activation of a handler for the exception\iref{except.throw}, +calls a function that exits +via an exception, or + +\item% +when the exception handling mechanism cannot find a handler for a thrown exception\iref{except.handle}, or + +\item when the search for a handler\iref{except.handle} encounters the +outermost block of a function +with a non-throwing exception specification\iref{except.spec}, or + +\item% +when the destruction of an object during stack unwinding\iref{except.ctor} +terminates by throwing an exception, or + +\item% +when initialization of a non-block +variable with static or thread storage duration\iref{basic.start.dynamic} +exits via an exception, or + +\item% +when destruction of an object with static or thread storage duration exits +via an exception\iref{basic.start.term}, or + +\item% +when execution of a function registered with +\tcode{std::atexit} or \tcode{std::at_quick_exit} +exits via an exception\iref{support.start.term}, or + +\item% +when a +\grammarterm{throw-expression}\iref{expr.throw} +with no operand attempts to rethrow an exception and no exception is being +handled\iref{except.throw}, or + +\item% +when the function \tcode{std::nested_exception::rethrow_nested} is called for an object +that has captured no exception\iref{except.nested}, or + +\item% +when execution of the initial function of a thread exits via +an exception\iref{thread.thread.constr}, or + +\item% +for a parallel algorithm whose \tcode{ExecutionPolicy} specifies such +behavior\iref{execpol.seq,execpol.par,execpol.parunseq}, +when execution of an element access function\iref{algorithms.parallel.defns} +of the parallel algorithm exits via an exception\iref{algorithms.parallel.exceptions}, or + +\item% +when the destructor or the move assignment operator is invoked on an object +of type \tcode{std::thread} that refers to +a joinable thread\iref{thread.thread.destr,thread.thread.assign}, or + +\item% +when a call to a \tcode{wait()}, \tcode{wait_until()}, or \tcode{wait_for()} +function on a condition variable\iref{thread.condition.condvar,thread.condition.condvarany} +fails to meet a postcondition, or + +\item% +when a callback invocation exits via an exception +when requesting stop on +a \tcode{std::stop_source} or +a \tcode{std::in\-place_stop_source}\iref{stopsource.mem,stopsource.inplace.mem}, +or in the constructor of +\tcode{std::stop_callback} or +\tcode{std::inplace_stop_callback}\iref{stopcallback.cons,stopcallback.inplace.cons} +when a callback invocation exits via an exception, or + +\item% +when a \tcode{run_loop} object is destroyed +that is still in the \tcode{running} state\iref{exec.run.loop}, or + +\item% +when \tcode{unhandled_stopped} is called on +a \tcode{with_awaitable_senders} object\iref{exec.with.awaitable.senders} +whose continuation is not a handle to a coroutine +whose promise type has an \tcode{unhandled_stopped} member function. + +\end{itemize} + +\end{note} + +\pnum +\indextext{\idxcode{terminate}}% +In such cases, +the function \tcode{std::terminate} is invoked\iref{exception.terminate}. +In the situation where no matching handler is found, it is +\impldef{stack unwinding before invocation of \tcode{std::terminate}} +whether or not the stack is unwound +before \tcode{std::terminate} is invoked. +In the situation where the search for a handler\iref{except.handle} encounters the +outermost block of a function +with a non-throwing exception specification\iref{except.spec}, it is +\impldef{whether stack is unwound before invoking the function \tcode{std::terminate} +when a \tcode{noexcept} specification is violated} +whether the stack is unwound, unwound partially, or not unwound at all +before the function \tcode{std::terminate} is invoked. +In all other situations, the stack shall not be unwound before +the function \tcode{std::terminate} +is invoked. +An implementation is not permitted to finish stack unwinding +prematurely based on a determination that the unwind process +will eventually cause an invocation of the function +\tcode{std::terminate}. +\indextext{exception handling|)} + \rSec1[stmt.dcl]{Declaration statement}% \indextext{statement!declaration} diff --git a/source/std.tex b/source/std.tex index 7b5f3358b5..0a5f56221d 100644 --- a/source/std.tex +++ b/source/std.tex @@ -112,13 +112,12 @@ \include{intro} \include{lex} -\include{modules} \include{basic} \include{expressions} \include{statements} \include{declarations} \include{overloading} -\include{exceptions} +\include{modules} \include{classes} \include{templates} \include{lib-intro} diff --git a/source/support.tex b/source/support.tex index bebd8957aa..fda729a263 100644 --- a/source/support.tex +++ b/source/support.tex @@ -3849,7 +3849,7 @@ \begin{itemdescr} \pnum \returns -The number of uncaught exceptions\iref{except.uncaught}. +The number of uncaught exceptions\iref{except.throw} in the current thread. \pnum \remarks diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index e39699f8c6..2d9cb9a741 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -101,6 +101,7 @@ % Lexing reorganization \movedxref{basic.stc.inherit}{basic.stc.general} +\movedxref{except.uncaught}{except.throw} \movedxref{gram.basic}{gram.module} \movedxref{lex.digraph}{lex.operators} From 3eaa2da1b388af4731d3331100d555295663f8f7 Mon Sep 17 00:00:00 2001 From: Alisdair Meredith Date: Wed, 2 Oct 2024 08:25:54 -0400 Subject: [PATCH 17/18] Redistribute parts of exception handling as appropriate --- source/basic.tex | 32 +-- source/declarations.tex | 267 +++++++++++++++++++++ source/future.tex | 297 ++++++++++++------------ source/lex.tex | 122 +++++++++- source/statements.tex | 501 ++++------------------------------------ source/xrefdelta.tex | 4 +- 6 files changed, 600 insertions(+), 623 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 0e1fb2ea4b..a33792f15b 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -4772,13 +4772,13 @@ \pnum Each of the following is termed a \defnadj{definable}{item}: \begin{itemize} -\item a class type\iref{class}, -\item an enumeration type\iref{dcl.enum}, -\item a function\iref{dcl.fct}, \item a variable\iref{basic.link}, -\item a templated entity\iref{temp.pre}, +\item a function\iref{dcl.fct}, \item a default argument for a parameter (for a function in a given scope)\iref{dcl.fct.default}, or +\item an enumeration type\iref{dcl.enum}, +\item a class type\iref{class}, +\item a templated entity\iref{temp.pre}, \item a default template argument\iref{temp.param}. \end{itemize} @@ -5059,13 +5059,12 @@ type \tcode{T} must be complete if \begin{itemize} \item an object of type \tcode{T} is defined\iref{basic.def}, or -\item a non-static class data member of type \tcode{T} is -declared\iref{class.mem}, or +\item a function with a return type or argument type of type \tcode{T} +is defined\iref{basic.def} or called\iref{expr.call}, or +\item the type \tcode{T} is the subject of an +\keyword{alignof} expression\iref{expr.alignof}, or \item \tcode{T} is used as the allocated type or array element type in a \grammarterm{new-expression}\iref{expr.new}, or -\item an lvalue-to-rvalue conversion is applied to -a glvalue referring -to an object of type \tcode{T}\iref{conv.lval}, or \item an expression is converted (either implicitly or explicitly) to type \tcode{T}\iref{conv,expr.type.conv, expr.dynamic.cast,expr.static.cast,expr.cast}, or @@ -5074,20 +5073,21 @@ or reference to \tcode{T} using a standard conversion\iref{conv}, a \keyword{dynamic_cast}\iref{expr.dynamic.cast} or a \keyword{static_cast}\iref{expr.static.cast}, or +\item an lvalue-to-rvalue conversion is applied to +a glvalue referring +to an object of type \tcode{T}\iref{conv.lval}, or \item a class member access operator is applied to an expression of type \tcode{T}\iref{expr.ref}, or \item the \keyword{typeid} operator\iref{expr.typeid} or the \keyword{sizeof} operator\iref{expr.sizeof} is applied to an operand of type \tcode{T}, or -\item a function with a return type or argument type of type \tcode{T} -is defined\iref{basic.def} or called\iref{expr.call}, or -\item a class with a base class of type \tcode{T} is -defined\iref{class.derived}, or \item an lvalue of type \tcode{T} is assigned to\iref{expr.ass}, or -\item the type \tcode{T} is the subject of an -\keyword{alignof} expression\iref{expr.alignof}, or \item an \grammarterm{exception-declaration} has type \tcode{T}, reference to -\tcode{T}, or pointer to \tcode{T}\iref{except.handle}. +\tcode{T}, or pointer to \tcode{T}\iref{except.handle}, or +\item a non-static class data member of type \tcode{T} is +declared\iref{class.mem}, or +\item a class with a base class of type \tcode{T} is +defined\iref{class.derived}. \end{itemize} \end{note} diff --git a/source/declarations.tex b/source/declarations.tex index 8f89479a9b..12c59a9853 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -4422,6 +4422,273 @@ \indextext{declaration!default argument|)}% \indextext{declarator!meaning of|)} +\rSec3[except.spec]{Exception specifications}% +\indextext{exception specification|(} + +\pnum +The predicate indicating whether a function cannot exit via an exception +is called the \defn{exception specification} of the function. +If the predicate is false, +the function has a +\indextext{exception specification!potentially-throwing}% +\defnx{potentially-throwing exception specification}% +{potentially-throwing!exception specification}, +otherwise it has a +\indextext{exception specification!non-throwing}% +\defn{non-throwing exception specification}. +The exception specification is either defined implicitly, +or defined explicitly +by using a \grammarterm{noexcept-specifier} +as a suffix of a function declarator\iref{dcl.fct}. + +\begin{bnf} +\nontermdef{noexcept-specifier}\br + \keyword{noexcept} \terminal{(} constant-expression \terminal{)}\br + \keyword{noexcept}\br +\end{bnf} + +\pnum +\indextext{exception specification!noexcept!constant expression and}% +In a \grammarterm{noexcept-specifier}, the \grammarterm{constant-expression}, +if supplied, shall be a contextually converted constant expression +of type \keyword{bool}\iref{expr.const}; +that constant expression is the exception specification of +the function type in which the \grammarterm{noexcept-specifier} appears. +A \tcode{(} token that follows \keyword{noexcept} is part of the +\grammarterm{noexcept-specifier} and does not commence an +initializer\iref{dcl.init}. +The \grammarterm{noexcept-specifier} \keyword{noexcept} +without a \grammarterm{constant-expression} +is +equivalent to the \grammarterm{noexcept-specifier} +\tcode{\keyword{noexcept}(\keyword{true})}. +\begin{example} +\begin{codeblock} +void f() noexcept(sizeof(char[2])); // error: narrowing conversion of value 2 to type \keyword{bool} +void g() noexcept(sizeof(char)); // OK, conversion of value 1 to type \keyword{bool} is non-narrowing +\end{codeblock} +\end{example} + +\pnum +If a declaration of a function +does not have a \grammarterm{noexcept-specifier}, +the declaration has a potentially throwing exception specification +unless it is a destructor or a deallocation function +or is defaulted on its first declaration, +in which cases the exception specification +is as specified below +and no other declaration for that function +shall have a \grammarterm{noexcept-specifier}. +In an explicit instantiation\iref{temp.explicit} +a \grammarterm{noexcept-specifier} may be specified, +but is not required. +If a \grammarterm{noexcept-specifier} is specified +in an explicit instantiation, +the exception specification shall be the same as +the exception specification of all other declarations of that function. +A diagnostic is required only if the +exception specifications are not the same +within a single translation unit. + +\pnum +\indextext{exception specification!virtual function and}% +If a virtual function has a +non-throwing exception specification, +all declarations, including the definition, of any function +that overrides that virtual function in any derived class +shall have a non-throwing +exception specification, +unless the overriding function is defined as deleted. +\begin{example} +\begin{codeblock} +struct B { + virtual void f() noexcept; + virtual void g(); + virtual void h() noexcept = delete; +}; + +struct D: B { + void f(); // error + void g() noexcept; // OK + void h() = delete; // OK +}; +\end{codeblock} + +The declaration of +\tcode{D::f} +is ill-formed because it +has a potentially-throwing exception specification, +whereas +\tcode{B::f} +has a non-throwing exception specification. +\end{example} + +\pnum +An expression $E$ is +\defnx{potentially-throwing}{potentially-throwing!expression} if +\begin{itemize} +\item +$E$ is a \grammarterm{throw-expression}\iref{expr.throw}, +or +\item +$E$ implicitly invokes a function +(such as an overloaded operator, +an allocation function in a \grammarterm{new-expression}, +a constructor for a function argument, +or a destructor if $E$ is a full-expression\iref{intro.execution}) +that has a potentially-throwing exception specification, +or +\item +any of the immediate subexpressions\iref{intro.execution} +of $E$ is potentially-throwing, +or +\item +$E$ is a function call\iref{expr.call} +whose \grammarterm{postfix-expression} +has a function type, +or a pointer-to-function type, +with a potentially-throwing exception specification, +or +\item +$E$ is a \keyword{dynamic_cast} expression that casts to a reference type and +requires a runtime check\iref{expr.dynamic.cast}, +or +\item +$E$ is a \keyword{typeid} expression applied to a +(possibly parenthesized) built-in unary \tcode{*} operator +applied to a pointer to a +polymorphic class type\iref{expr.typeid}. +\end{itemize} + +\pnum +An implicitly-declared constructor for a class \tcode{X}, +or a constructor without a \grammarterm{noexcept-specifier} +that is defaulted on its first declaration, +has a potentially-throwing exception specification +if and only if +any of the following constructs is potentially-throwing: +\begin{itemize} +\item +the invocation of a constructor selected by overload resolution +in the implicit definition of the constructor +for class \tcode{X} +to initialize a potentially constructed subobject, or +\item +a subexpression of such an initialization, +such as a default argument expression, or, +\item +for a default constructor, a default member initializer. +\end{itemize} +\begin{note} +Even though destructors for fully-constructed subobjects +are invoked when an exception is thrown +during the execution of a constructor\iref{except.ctor}, +their exception specifications do not contribute +to the exception specification of the constructor, +because an exception thrown from such a destructor +would call the function \tcode{std::terminate} +rather than escape the constructor\iref{except.throw,except.terminate}. +\end{note} + +\pnum +The exception specification for an implicitly-declared destructor, +or a destructor without a \grammarterm{noexcept-specifier}, +is potentially-throwing if and only if +any of the destructors +for any of its potentially constructed subobjects +has a potentially-throwing exception specification or +the destructor is virtual and the destructor of any virtual base class +has a potentially-throwing exception specification. + +\pnum +The exception specification for an implicitly-declared assignment operator, +or an assignment-operator without a \grammarterm{noexcept-specifier} +that is defaulted on its first declaration, +is potentially-throwing if and only if +the invocation of any assignment operator +in the implicit definition is potentially-throwing. + +\pnum +A deallocation function\iref{basic.stc.dynamic.deallocation} +with no explicit \grammarterm{noexcept-specifier} +has a non-throwing exception specification. + +\pnum +The exception specification for a comparison operator function\iref{over.binary} +without a \grammarterm{noexcept-specifier} +that is defaulted on its first declaration +is potentially-throwing if and only if +any expression +in the implicit definition is potentially-throwing. + +\pnum +\begin{example} +\begin{codeblock} +struct A { + A(int = (A(5), 0)) noexcept; + A(const A&) noexcept; + A(A&&) noexcept; + ~A(); +}; +struct B { + B() noexcept; + B(const B&) = default; // implicit exception specification is \tcode{\keyword{noexcept}(\keyword{true})} + B(B&&, int = (throw 42, 0)) noexcept; + ~B() noexcept(false); +}; +int n = 7; +struct D : public A, public B { + int * p = new int[n]; + // \tcode{D::D()} potentially-throwing, as the \keyword{new} operator may throw \tcode{bad_alloc} or \tcode{bad_array_new_length} + // \tcode{D::D(const D\&)} non-throwing + // \tcode{D::D(D\&\&)} potentially-throwing, as the default argument for \tcode{B}'s constructor may throw + // \tcode{D::\~D()} potentially-throwing +}; +\end{codeblock} +Furthermore, if +\tcode{A::\~{}A()} +were virtual, +the program would be ill-formed since a function that overrides a virtual +function from a base class +shall not have a potentially-throwing exception specification +if the base class function has a non-throwing exception specification. +\end{example} + +\pnum +An exception specification is considered to be \defnx{needed}{needed!exception specification} when: +\begin{itemize} +\item in an expression, the function is selected by +overload resolution\iref{over.match,over.over}; + +\item the function is odr-used\iref{term.odr.use} or, if it appears in an +unevaluated operand, would be odr-used if the expression were +potentially-evaluated; + +\item the exception specification is compared to that of another +declaration (e.g., an explicit specialization or an overriding virtual +function); + +\item the function is defined; or + +\item the exception specification is needed for a defaulted +function that calls the function. +\begin{note} +A defaulted declaration does not require the +exception specification of a base member function to be evaluated +until the implicit exception specification of the derived +function is needed, but an explicit \grammarterm{noexcept-specifier} needs +the implicit exception specification to compare against. +\end{note} +\end{itemize} +The exception specification of a defaulted +function is evaluated as described above only when needed; similarly, the +\grammarterm{noexcept-specifier} of a specialization of a function +template or member function of a class template is instantiated only when +needed. +% +\indextext{exception specification|)} +\indextext{exception handling|)} + \rSec1[dcl.init]{Initializers}% \rSec2[dcl.init.general]{General}% diff --git a/source/future.tex b/source/future.tex index a16d108869..28f503b4e0 100644 --- a/source/future.tex +++ b/source/future.tex @@ -16,6 +16,43 @@ An implementation may declare library names and entities described in this Clause with the \tcode{deprecated} attribute\iref{dcl.attr.deprecated}. +\rSec1[depr.local]{Non-local use of TU-local entities} + +\pnum +A declaration of a non-TU-local entity that is an exposure\iref{basic.link} +is deprecated. +\begin{note} +Such a declaration in an importable module unit is ill-formed. +\end{note} +\begin{example} +\begin{codeblock} +namespace { + struct A { + void f() {} + }; +} +A h(); // deprecated: not internal linkage +inline void g() {A().f();} // deprecated: inline and not internal linkage +\end{codeblock} +\end{example} + +\rSec1[depr.static.constexpr]{Redeclaration of \tcode{static constexpr} data members} + +\pnum +For compatibility with prior revisions of \Cpp{}, a \keyword{constexpr} +static data member may be redundantly redeclared outside the class with no +initializer\iref{basic.def,class.static.data}. +This usage is deprecated. +\begin{example} +\begin{codeblock} +struct A { + static constexpr int n = 5; // definition (declaration in \CppXIV{}) +}; + +constexpr int A::n; // redundant declaration (definition in \CppXIV{}) +\end{codeblock} +\end{example} + \rSec1[depr.capture.this]{Implicit capture of \tcode{*this} by reference} \pnum @@ -114,43 +151,14 @@ \end{codeblock} \end{example} - -\rSec1[depr.static.constexpr]{Redeclaration of \tcode{static constexpr} data members} +\rSec1[depr.lit]{Literal operator function declarations using an identifier} \pnum -For compatibility with prior revisions of \Cpp{}, a \keyword{constexpr} -static data member may be redundantly redeclared outside the class with no -initializer\iref{basic.def,class.static.data}. -This usage is deprecated. -\begin{example} +A \grammarterm{literal-operator-id}\iref{over.literal} of the form \begin{codeblock} -struct A { - static constexpr int n = 5; // definition (declaration in \CppXIV{}) -}; - -constexpr int A::n; // redundant declaration (definition in \CppXIV{}) +operator @\grammarterm{unevaluataed-string}@ @\grammarterm{identifier}@ \end{codeblock} -\end{example} - -\rSec1[depr.local]{Non-local use of TU-local entities} - -\pnum -A declaration of a non-TU-local entity that is an exposure\iref{basic.link} is deprecated. -\begin{note} -Such a declaration in an importable module unit is ill-formed. -\end{note} -\begin{example} -\begin{codeblock} -namespace { - struct A { - void f() {} - }; -} -A h(); // deprecated: not internal linkage -inline void g() {A().f();} // deprecated: inline and not internal linkage -\end{codeblock} -\end{example} \rSec1[depr.impldec]{Implicit declaration of copy functions} @@ -166,15 +174,6 @@ It is possible that future versions of \Cpp{} will specify that these implicit definitions are deleted\iref{dcl.fct.def.delete}. -\rSec1[depr.lit]{Literal operator function declarations using an identifier} - -\pnum -A \grammarterm{literal-operator-id}\iref{over.literal} of the form -\begin{codeblock} -operator @\grammarterm{unevaluated-string}@ @\grammarterm{identifier}@ -\end{codeblock} -is deprecated. - \rSec1[depr.template.template]{\tcode{template} keyword before qualified names} \pnum @@ -244,86 +243,6 @@ #define @\xname{bool_true_false_are_defined}@ 1 \end{codeblock} -\rSec1[depr.relops]{Relational operators}% -\indexlibraryglobal{rel_ops}% - -\pnum -The header \libheaderref{utility} has the following additions: - -\begin{codeblock} -namespace std::rel_ops { - template bool operator!=(const T&, const T&); - template bool operator> (const T&, const T&); - template bool operator<=(const T&, const T&); - template bool operator>=(const T&, const T&); -} -\end{codeblock} - -\pnum -To avoid redundant definitions of \tcode{operator!=} out of \tcode{operator==} -and operators \tcode{>}, \tcode{<=}, and \tcode{>=} out of \tcode{operator<}, -the library provides the following: - -\indexlibrary{\idxcode{operator"!=}}% -\begin{itemdecl} -template bool operator!=(const T& x, const T& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{T} meets the \oldconcept{EqualityComparable} requirements (\tref{cpp17.equalitycomparable}). - -\pnum -\returns -\tcode{!(x == y)}. -\end{itemdescr} - -\indexlibraryglobal{operator>}% -\begin{itemdecl} -template bool operator>(const T& x, const T& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). - -\pnum -\returns -\tcode{y < x}. -\end{itemdescr} - -\indexlibrary{\idxcode{operator<=}}% -\begin{itemdecl} -template bool operator<=(const T& x, const T& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). - -\pnum -\returns -\tcode{!(y < x)}. -\end{itemdescr} - -\indexlibrary{\idxcode{operator>=}}% -\begin{itemdecl} -template bool operator>=(const T& x, const T& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). - -\pnum -\returns -\tcode{!(x < y)}. -\end{itemdescr} - \rSec1[depr.cerrno]{Deprecated error numbers} \pnum @@ -483,6 +402,86 @@ whose value is the strictest alignment of all types listed in \tcode{Types}. \end{itemdescr} +\rSec1[depr.relops]{Relational operators}% +\indexlibraryglobal{rel_ops}% + +\pnum +The header \libheaderref{utility} has the following additions: + +\begin{codeblock} +namespace std::rel_ops { + template bool operator!=(const T&, const T&); + template bool operator> (const T&, const T&); + template bool operator<=(const T&, const T&); + template bool operator>=(const T&, const T&); +} +\end{codeblock} + +\pnum +To avoid redundant definitions of \tcode{operator!=} out of \tcode{operator==} +and operators \tcode{>}, \tcode{<=}, and \tcode{>=} out of \tcode{operator<}, +the library provides the following: + +\indexlibrary{\idxcode{operator"!=}}% +\begin{itemdecl} +template bool operator!=(const T& x, const T& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} meets the \oldconcept{EqualityComparable} requirements (\tref{cpp17.equalitycomparable}). + +\pnum +\returns +\tcode{!(x == y)}. +\end{itemdescr} + +\indexlibraryglobal{operator>}% +\begin{itemdecl} +template bool operator>(const T& x, const T& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). + +\pnum +\returns +\tcode{y < x}. +\end{itemdescr} + +\indexlibrary{\idxcode{operator<=}}% +\begin{itemdecl} +template bool operator<=(const T& x, const T& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). + +\pnum +\returns +\tcode{!(y < x)}. +\end{itemdescr} + +\indexlibrary{\idxcode{operator>=}}% +\begin{itemdecl} +template bool operator>=(const T& x, const T& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). + +\pnum +\returns +\tcode{!(x < y)}. +\end{itemdescr} + \rSec1[depr.tuple]{Tuple} \pnum @@ -600,6 +599,34 @@ \end{itemize} \end{itemdescr} +\rSec1[depr.format]{Deprecated formatting} + +\rSec2[depr.format.syn]{Header \tcode{} synopsis} + +\pnum +The header \libheaderref{format}{format.syn} has the following additions: + +\begin{codeblock} +namespace std { + template + decltype(auto) visit_format_arg(Visitor&& vis, basic_format_arg arg); +} +\end{codeblock} + +\rSec2[depr.format.arg]{Formatting arguments} + +\indexlibraryglobal{visit_format_arg}% +\begin{itemdecl} +template + decltype(auto) visit_format_arg(Visitor&& vis, basic_format_arg arg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return visit(std::forward(vis), arg.value);} +\end{itemdescr} + \rSec1[depr.iterator]{Deprecated \tcode{iterator} class template} \pnum @@ -674,34 +701,6 @@ \tcode{current}. \end{itemdescr} -\rSec1[depr.format]{Deprecated formatting} - -\rSec2[depr.format.syn]{Header \tcode{} synopsis} - -\pnum -The header \libheaderref{format}{format.syn} has the following additions: - -\begin{codeblock} -namespace std { - template - decltype(auto) visit_format_arg(Visitor&& vis, basic_format_arg arg); -} -\end{codeblock} - -\rSec2[depr.format.arg]{Formatting arguments} - -\indexlibraryglobal{visit_format_arg}% -\begin{itemdecl} -template - decltype(auto) visit_format_arg(Visitor&& vis, basic_format_arg arg); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return visit(std::forward(vis), arg.value);} -\end{itemdescr} - \rSec1[depr.locale.category]{Deprecated locale category facets} \pnum diff --git a/source/lex.tex b/source/lex.tex index 4bb3e228d1..148f690fd7 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -4343,6 +4343,8 @@ \item \grammarterm{condition} with a \grammarterm{declarator}\iref{stmt.pre}, \item +\grammarterm{exception-declaration}\iref{except.pre}, +\item \grammarterm{elaborated-type-specifier} that introduces a name\iref{dcl.type.elab}, \item @@ -4358,8 +4360,6 @@ \item \grammarterm{using-declarator}\iref{namespace.udecl}, \item -\grammarterm{exception-declaration}\iref{except.pre}, -\item \grammarterm{class-specifier}\iref{class.pre}, \item implicit declaration of an injected-class-name\iref{class.pre}, @@ -6196,5 +6196,123 @@ and without calling the functions passed to \tcode{std::atexit()} or \tcode{std::at_quick_exit()}.% \indextext{program!termination|)} + +\rSec3[except.terminate]{The \tcode{std::terminate} function} + +\pnum +\indextext{\idxcode{terminate}}% +In some situations the \Cpp{} runtime encounters an error that cannot be recovered, +such as when an exception is not handled, or a thread is destroyed while still running. +In such cases, +the function \tcode{std::terminate} is invoked\iref{exception.terminate}. +\begin{note} +These situations are: +\indextext{\idxcode{terminate}!called}% +\begin{itemize} +\item% +when initialization of a non-block +variable with static or thread storage duration\iref{basic.start.dynamic} +exits via an exception, or + +\item% +when destruction of an object with static or thread storage duration exits +via an exception\iref{basic.start.term}, or + +\item% +when a +\grammarterm{throw-expression}\iref{expr.throw} +with no operand attempts to rethrow an exception and no exception is being +handled\iref{except.throw}, or + +\item% +when the exception handling mechanism, after completing +the initialization of the exception object +but before +activation of a handler for the exception\iref{except.throw}, +calls a function that exits +via an exception, or + +\item% +when the destruction of an object during stack unwinding\iref{except.ctor} +terminates by throwing an exception, or + +\item when the search for a handler\iref{except.handle} encounters the +outermost block of a function +with a non-throwing exception specification, or + +\item% +when the exception handling mechanism cannot find a handler for a thrown exception\iref{except.handle}, or + +\item% +when execution of a function registered with +\tcode{std::atexit} or \tcode{std::at_quick_exit} +exits via an exception\iref{support.start.term}, or + +\item% +when the function \tcode{std::nested_exception::rethrow_nested} is called for an object +that has captured no exception\iref{except.nested}, or + +\item% +for a parallel algorithm whose \tcode{ExecutionPolicy} specifies such +behavior\iref{execpol.seq,execpol.par,execpol.parunseq}, +when execution of an element access function\iref{algorithms.parallel.defns} +of the parallel algorithm exits via an exception\iref{algorithms.parallel.exceptions}, or + +\item% +when a callback invocation exits via an exception +when requesting stop on +a \tcode{std::stop_source} or +a \tcode{std::in\-place_stop_source}\iref{stopsource.mem,stopsource.inplace.mem}, +or in the constructor of +\tcode{std::stop_callback} or +\tcode{std::inplace_stop_callback}\iref{stopcallback.cons,stopcallback.inplace.cons} +when a callback invocation exits via an exception, or + +\item% +when execution of the initial function of a thread exits via +an exception\iref{thread.thread.constr}, or + +\item% +when the destructor or the move assignment operator is invoked on an object +of type \tcode{std::thread} that refers to +a joinable thread\iref{thread.thread.destr,thread.thread.assign}, or + +\item% +when a call to a \tcode{wait()}, \tcode{wait_until()}, or \tcode{wait_for()} +function on a condition variable\iref{thread.condition.condvar,thread.condition.condvarany} +fails to meet a postcondition, or + +\item% +when a \tcode{run_loop} object is destroyed +that is still in the \tcode{running} state\iref{exec.run.loop}, or + +\item% +when \tcode{unhandled_stopped} is called on +a \tcode{with_awaitable_senders} object\iref{exec.with.awaitable.senders} +whose continuation is not a handle to a coroutine +whose promise type has an \tcode{unhandled_stopped} member function. + +\end{itemize} +\end{note} + +\pnum +In the situation where no matching handler is found, it is +\impldef{stack unwinding before invocation of \tcode{std::terminate}} +whether or not the stack is unwound +before \tcode{std::terminate} is invoked. +In the situation where the search for a handler\iref{except.handle} encounters the +outermost block of a function +with a non-throwing exception specification, it is +\impldef{whether stack is unwound before invoking the function \tcode{std::terminate} +when a \tcode{noexcept} specification is violated} +whether the stack is unwound, unwound partially, or not unwound at all +before the function \tcode{std::terminate} is invoked. +In all other situations, the stack shall not be unwound before +the function \tcode{std::terminate} +is invoked. +An implementation is not permitted to finish stack unwinding +prematurely based on a determination that the unwind process +will eventually cause an invocation of the function +\tcode{std::terminate}. \indextext{program execution|)} \indextext{conventions!lexical|)} diff --git a/source/statements.tex b/source/statements.tex index 68d4416f33..356110e99d 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -1033,13 +1033,13 @@ \indextext{label}% label\iref{stmt.label} located in the current function. -\rSec1[except]{Exception handling}% +\rSec1[except]{Try block statements}% \indextext{exception handling|(} \indextext{exception object|see{exception handling, exception object}}% \indextext{object!exception|see{exception handling, exception object}} -\rSec2[except.pre]{Preamble} +\rSec2[except.pre]{General} \pnum Exception handling provides a way of transferring control and information @@ -1085,21 +1085,21 @@ The optional \grammarterm{attribute-specifier-seq} in an \grammarterm{exception-declaration} appertains to the parameter of the catch clause\iref{except.handle}. +\pnum +In this Clause, ``before'' and ``after'' refer to the +``sequenced before'' relation\iref{intro.execution}. + \pnum \indextext{exception handling!try block}% -\indextext{exception handling!handler}% \indextext{try block|see{exception handling, try block}}% -\indextext{handler|see{exception handling, handler}}% -A \grammarterm{try-block} is a \grammarterm{statement}\iref{stmt.pre}. -\begin{note} Within this Clause ``try block'' is taken to mean both \grammarterm{try-block} and \grammarterm{function-try-block}. -\end{note} \pnum -\indextext{exception handling!\idxcode{goto}}% \indextext{exception handling!\idxcode{switch}}% +\indextext{exception handling!handler}% +\indextext{handler|see{exception handling, handler}}%\indextext{exception handling!\idxcode{goto}}% \indextext{\idxcode{goto}!and try block}% \indextext{\idxcode{switch}!and try block}% \indextext{\idxcode{goto}!and handler}% @@ -1124,6 +1124,8 @@ \end{codeblock} \end{example} + +\pnum \indextext{\idxcode{goto}!and try block}% \indextext{\idxcode{switch}!and try block}% \indextext{\idxcode{return}!and try block}% @@ -1214,10 +1216,6 @@ \end{codeblock} \end{example} -\pnum -In this Clause, ``before'' and ``after'' refer to the -``sequenced before'' relation\iref{intro.execution}. - \rSec2[except.throw]{Throwing an exception}% \indextext{exception handling!throwing}% \indextext{throwing|see{exception handling, throwing}} @@ -1410,7 +1408,7 @@ \end{note} -\rSec2[except.ctor]{Constructors and destructors}% +\rSec2[except.ctor]{Stack unwinding}% \indextext{exception handling!constructors and destructors}% \indextext{constructor!exception handling|see{exception handling, constructors and destructors}}% \indextext{destructor!exception handling|see{exception handling, constructors and destructors}} @@ -1655,10 +1653,7 @@ \tcode{...} in a handler's \grammarterm{exception-declaration} -functions similarly to -\tcode{...} -in a function parameter declaration; -it specifies a match for any exception. +specifies a match for any exception. If present, a \tcode{...} handler shall be the last handler for its try block. @@ -1669,6 +1664,40 @@ handler continues in a dynamically surrounding try block of the same thread. +\pnum +\indextext{exception handling!terminate called@\tcode{terminate} called}% +\indextext{\idxcode{terminate}!called}% +If the search for a handler +encounters the outermost block of a function with a +non-throwing exception specification, +the function \tcode{std::terminate} is invoked\iref{except.terminate}. +\begin{note} +An implementation is not permitted to reject an expression merely because, when +executed, it throws or might +throw an exception from a function with a non-throwing exception specification. +\end{note} +\begin{example} +\begin{codeblock} +extern void f(); // potentially-throwing + +void g() noexcept { + f(); // valid, even if \tcode{f} throws + throw 42; // valid, effectively a call to \tcode{std::terminate} +} +\end{codeblock} +The call to +\tcode{f} +is well-formed despite the possibility for it to throw an exception. +\end{example} + +\pnum +If no matching handler is found, +the function \tcode{std::terminate} is invoked; +whether or not the stack is unwound before this invocation of +\tcode{std::terminate} +is \impldef{stack unwinding before invocation of +\tcode{std::terminate}}\iref{except.terminate}. + \pnum A handler is considered \defnx{active}{exception handling!handler!active} when initialization is complete for the parameter (if any) of the catch clause. @@ -1686,14 +1715,6 @@ still active is called the \defnx{currently handled exception}{exception handling!currently handled exception}. -\pnum -If no matching handler is found, -the function \tcode{std::terminate} is invoked; -whether or not the stack is unwound before this invocation of -\tcode{std::terminate} -is \impldef{stack unwinding before invocation of -\tcode{std::terminate}}\iref{except.terminate}. - \pnum Referring to any non-static member or base class of an object in the handler for a @@ -1757,436 +1778,6 @@ \indextext{exception handling!handler!match|)}% \indextext{exception handling!handler|)} -\rSec2[except.spec]{Exception specifications}% -\indextext{exception specification|(} - -\pnum -The predicate indicating whether a function cannot exit via an exception -is called the \defn{exception specification} of the function. -If the predicate is false, -the function has a -\indextext{exception specification!potentially-throwing}% -\defnx{potentially-throwing exception specification}% -{potentially-throwing!exception specification}, -otherwise it has a -\indextext{exception specification!non-throwing}% -\defn{non-throwing exception specification}. -The exception specification is either defined implicitly, -or defined explicitly -by using a \grammarterm{noexcept-specifier} -as a suffix of a function declarator\iref{dcl.fct}. - -\begin{bnf} -\nontermdef{noexcept-specifier}\br - \keyword{noexcept} \terminal{(} constant-expression \terminal{)}\br - \keyword{noexcept}\br -\end{bnf} - -\pnum -\indextext{exception specification!noexcept!constant expression and}% -In a \grammarterm{noexcept-specifier}, the \grammarterm{constant-expression}, -if supplied, shall be a contextually converted constant expression -of type \keyword{bool}\iref{expr.const}; -that constant expression is the exception specification of -the function type in which the \grammarterm{noexcept-specifier} appears. -A \tcode{(} token that follows \keyword{noexcept} is part of the -\grammarterm{noexcept-specifier} and does not commence an -initializer\iref{dcl.init}. -The \grammarterm{noexcept-specifier} \keyword{noexcept} -without a \grammarterm{constant-expression} -is -equivalent to the \grammarterm{noexcept-specifier} -\tcode{\keyword{noexcept}(\keyword{true})}. -\begin{example} -\begin{codeblock} -void f() noexcept(sizeof(char[2])); // error: narrowing conversion of value 2 to type \keyword{bool} -void g() noexcept(sizeof(char)); // OK, conversion of value 1 to type \keyword{bool} is non-narrowing -\end{codeblock} -\end{example} - -\pnum -If a declaration of a function -does not have a \grammarterm{noexcept-specifier}, -the declaration has a potentially throwing exception specification -unless it is a destructor or a deallocation function -or is defaulted on its first declaration, -in which cases the exception specification -is as specified below -and no other declaration for that function -shall have a \grammarterm{noexcept-specifier}. -In an explicit instantiation\iref{temp.explicit} -a \grammarterm{noexcept-specifier} may be specified, -but is not required. -If a \grammarterm{noexcept-specifier} is specified -in an explicit instantiation, -the exception specification shall be the same as -the exception specification of all other declarations of that function. -A diagnostic is required only if the -exception specifications are not the same -within a single translation unit. - -\pnum -\indextext{exception specification!virtual function and}% -If a virtual function has a -non-throwing exception specification, -all declarations, including the definition, of any function -that overrides that virtual function in any derived class -shall have a non-throwing -exception specification, -unless the overriding function is defined as deleted. -\begin{example} -\begin{codeblock} -struct B { - virtual void f() noexcept; - virtual void g(); - virtual void h() noexcept = delete; -}; - -struct D: B { - void f(); // error - void g() noexcept; // OK - void h() = delete; // OK -}; -\end{codeblock} - -The declaration of -\tcode{D::f} -is ill-formed because it -has a potentially-throwing exception specification, -whereas -\tcode{B::f} -has a non-throwing exception specification. -\end{example} - -\pnum -\indextext{exception handling!terminate called@\tcode{terminate} called}% -\indextext{\idxcode{terminate}!called}% -Whenever an exception is thrown -and the search for a handler\iref{except.handle} -encounters the outermost block of a function with a -non-throwing exception specification, -the function \tcode{std::terminate} is invoked\iref{except.terminate}. -\begin{note} -An implementation is not permitted to reject an expression merely because, when -executed, it throws or might -throw an exception from a function with a non-throwing exception specification. -\end{note} -\begin{example} -\begin{codeblock} -extern void f(); // potentially-throwing - -void g() noexcept { - f(); // valid, even if \tcode{f} throws - throw 42; // valid, effectively a call to \tcode{std::terminate} -} -\end{codeblock} -The call to -\tcode{f} -is well-formed despite the possibility for it to throw an exception. -\end{example} - -\pnum -An expression $E$ is -\defnx{potentially-throwing}{potentially-throwing!expression} if -\begin{itemize} -\item -$E$ is a \grammarterm{throw-expression}\iref{expr.throw}, -or -\item -$E$ implicitly invokes a function -(such as an overloaded operator, -an allocation function in a \grammarterm{new-expression}, -a constructor for a function argument, -or a destructor if $E$ is a full-expression\iref{intro.execution}) -that has a potentially-throwing exception specification, -or -\item -any of the immediate subexpressions\iref{intro.execution} -of $E$ is potentially-throwing, -or -\item -$E$ is a function call\iref{expr.call} -whose \grammarterm{postfix-expression} -has a function type, -or a pointer-to-function type, -with a potentially-throwing exception specification, -or -\item -$E$ is a \keyword{dynamic_cast} expression that casts to a reference type and -requires a runtime check\iref{expr.dynamic.cast}, -or -\item -$E$ is a \keyword{typeid} expression applied to a -(possibly parenthesized) built-in unary \tcode{*} operator -applied to a pointer to a -polymorphic class type\iref{expr.typeid}. -\end{itemize} - -\pnum -An implicitly-declared constructor for a class \tcode{X}, -or a constructor without a \grammarterm{noexcept-specifier} -that is defaulted on its first declaration, -has a potentially-throwing exception specification -if and only if -any of the following constructs is potentially-throwing: -\begin{itemize} -\item -the invocation of a constructor selected by overload resolution -in the implicit definition of the constructor -for class \tcode{X} -to initialize a potentially constructed subobject, or -\item -a subexpression of such an initialization, -such as a default argument expression, or, -\item -for a default constructor, a default member initializer. -\end{itemize} -\begin{note} -Even though destructors for fully-constructed subobjects -are invoked when an exception is thrown -during the execution of a constructor\iref{except.ctor}, -their exception specifications do not contribute -to the exception specification of the constructor, -because an exception thrown from such a destructor -would call the function \tcode{std::terminate} -rather than escape the constructor\iref{except.throw,except.terminate}. -\end{note} - -\pnum -The exception specification for an implicitly-declared destructor, -or a destructor without a \grammarterm{noexcept-specifier}, -is potentially-throwing if and only if -any of the destructors -for any of its potentially constructed subobjects -has a potentially-throwing exception specification or -the destructor is virtual and the destructor of any virtual base class -has a potentially-throwing exception specification. - -\pnum -The exception specification for an implicitly-declared assignment operator, -or an assignment-operator without a \grammarterm{noexcept-specifier} -that is defaulted on its first declaration, -is potentially-throwing if and only if -the invocation of any assignment operator -in the implicit definition is potentially-throwing. - -\pnum -A deallocation function\iref{basic.stc.dynamic.deallocation} -with no explicit \grammarterm{noexcept-specifier} -has a non-throwing exception specification. - -\pnum -The exception specification for a comparison operator function\iref{over.binary} -without a \grammarterm{noexcept-specifier} -that is defaulted on its first declaration -is potentially-throwing if and only if -any expression -in the implicit definition is potentially-throwing. - -\pnum -\begin{example} -\begin{codeblock} -struct A { - A(int = (A(5), 0)) noexcept; - A(const A&) noexcept; - A(A&&) noexcept; - ~A(); -}; -struct B { - B() noexcept; - B(const B&) = default; // implicit exception specification is \tcode{\keyword{noexcept}(\keyword{true})} - B(B&&, int = (throw 42, 0)) noexcept; - ~B() noexcept(false); -}; -int n = 7; -struct D : public A, public B { - int * p = new int[n]; - // \tcode{D::D()} potentially-throwing, as the \keyword{new} operator may throw \tcode{bad_alloc} or \tcode{bad_array_new_length} - // \tcode{D::D(const D\&)} non-throwing - // \tcode{D::D(D\&\&)} potentially-throwing, as the default argument for \tcode{B}'s constructor may throw - // \tcode{D::\~D()} potentially-throwing -}; -\end{codeblock} -Furthermore, if -\tcode{A::\~{}A()} -were virtual, -the program would be ill-formed since a function that overrides a virtual -function from a base class -shall not have a potentially-throwing exception specification -if the base class function has a non-throwing exception specification. -\end{example} - -\pnum -An exception specification is considered to be \defnx{needed}{needed!exception specification} when: -\begin{itemize} -\item in an expression, the function is selected by -overload resolution\iref{over.match,over.over}; - -\item the function is odr-used\iref{term.odr.use} or, if it appears in an -unevaluated operand, would be odr-used if the expression were -potentially-evaluated; - -\item the exception specification is compared to that of another -declaration (e.g., an explicit specialization or an overriding virtual -function); - -\item the function is defined; or - -\item the exception specification is needed for a defaulted -function that calls the function. -\begin{note} -A defaulted declaration does not require the -exception specification of a base member function to be evaluated -until the implicit exception specification of the derived -function is needed, but an explicit \grammarterm{noexcept-specifier} needs -the implicit exception specification to compare against. -\end{note} -\end{itemize} -The exception specification of a defaulted -function is evaluated as described above only when needed; similarly, the -\grammarterm{noexcept-specifier} of a specialization of a function -template or member function of a class template is instantiated only when -needed. -% -\indextext{exception specification|)} - -\rSec2[except.special]{Special functions} - -\rSec3[except.special.general]{General} - -\pnum -The function \tcode{std::terminate}\iref{except.terminate} -is used by the exception -handling mechanism for coping with errors related to the exception handling -mechanism itself. -The function \tcode{std::uncaught_exceptions}\iref{uncaught.exceptions} -reports how many exceptions are uncaught in the current thread. -The function \tcode{std::current_exception}\iref{propagation} and the class -\tcode{std::nested_exception}\iref{except.nested} can be used by a program to -capture the currently handled exception. - -\rSec3[except.terminate]{The \tcode{std::terminate} function} - -\pnum -\indextext{\idxcode{terminate}}% -% FIXME: What does it mean to abandon exception handling? -In some situations, exception handling is abandoned -for less subtle error handling techniques. -\begin{note} -These situations are: -\indextext{\idxcode{terminate}!called}% -\begin{itemize} -\item% -when the exception handling mechanism, after completing -the initialization of the exception object -but before -activation of a handler for the exception\iref{except.throw}, -calls a function that exits -via an exception, or - -\item% -when the exception handling mechanism cannot find a handler for a thrown exception\iref{except.handle}, or - -\item when the search for a handler\iref{except.handle} encounters the -outermost block of a function -with a non-throwing exception specification\iref{except.spec}, or - -\item% -when the destruction of an object during stack unwinding\iref{except.ctor} -terminates by throwing an exception, or - -\item% -when initialization of a non-block -variable with static or thread storage duration\iref{basic.start.dynamic} -exits via an exception, or - -\item% -when destruction of an object with static or thread storage duration exits -via an exception\iref{basic.start.term}, or - -\item% -when execution of a function registered with -\tcode{std::atexit} or \tcode{std::at_quick_exit} -exits via an exception\iref{support.start.term}, or - -\item% -when a -\grammarterm{throw-expression}\iref{expr.throw} -with no operand attempts to rethrow an exception and no exception is being -handled\iref{except.throw}, or - -\item% -when the function \tcode{std::nested_exception::rethrow_nested} is called for an object -that has captured no exception\iref{except.nested}, or - -\item% -when execution of the initial function of a thread exits via -an exception\iref{thread.thread.constr}, or - -\item% -for a parallel algorithm whose \tcode{ExecutionPolicy} specifies such -behavior\iref{execpol.seq,execpol.par,execpol.parunseq}, -when execution of an element access function\iref{algorithms.parallel.defns} -of the parallel algorithm exits via an exception\iref{algorithms.parallel.exceptions}, or - -\item% -when the destructor or the move assignment operator is invoked on an object -of type \tcode{std::thread} that refers to -a joinable thread\iref{thread.thread.destr,thread.thread.assign}, or - -\item% -when a call to a \tcode{wait()}, \tcode{wait_until()}, or \tcode{wait_for()} -function on a condition variable\iref{thread.condition.condvar,thread.condition.condvarany} -fails to meet a postcondition, or - -\item% -when a callback invocation exits via an exception -when requesting stop on -a \tcode{std::stop_source} or -a \tcode{std::in\-place_stop_source}\iref{stopsource.mem,stopsource.inplace.mem}, -or in the constructor of -\tcode{std::stop_callback} or -\tcode{std::inplace_stop_callback}\iref{stopcallback.cons,stopcallback.inplace.cons} -when a callback invocation exits via an exception, or - -\item% -when a \tcode{run_loop} object is destroyed -that is still in the \tcode{running} state\iref{exec.run.loop}, or - -\item% -when \tcode{unhandled_stopped} is called on -a \tcode{with_awaitable_senders} object\iref{exec.with.awaitable.senders} -whose continuation is not a handle to a coroutine -whose promise type has an \tcode{unhandled_stopped} member function. - -\end{itemize} - -\end{note} - -\pnum -\indextext{\idxcode{terminate}}% -In such cases, -the function \tcode{std::terminate} is invoked\iref{exception.terminate}. -In the situation where no matching handler is found, it is -\impldef{stack unwinding before invocation of \tcode{std::terminate}} -whether or not the stack is unwound -before \tcode{std::terminate} is invoked. -In the situation where the search for a handler\iref{except.handle} encounters the -outermost block of a function -with a non-throwing exception specification\iref{except.spec}, it is -\impldef{whether stack is unwound before invoking the function \tcode{std::terminate} -when a \tcode{noexcept} specification is violated} -whether the stack is unwound, unwound partially, or not unwound at all -before the function \tcode{std::terminate} is invoked. -In all other situations, the stack shall not be unwound before -the function \tcode{std::terminate} -is invoked. -An implementation is not permitted to finish stack unwinding -prematurely based on a determination that the unwind process -will eventually cause an invocation of the function -\tcode{std::terminate}. -\indextext{exception handling|)} - \rSec1[stmt.dcl]{Declaration statement}% \indextext{statement!declaration} diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index 2d9cb9a741..03c9788f16 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -103,8 +103,10 @@ \movedxref{basic.stc.inherit}{basic.stc.general} \movedxref{except.uncaught}{except.throw} \movedxref{gram.basic}{gram.module} +\movedxref{gram.except}{gram.stmt} \movedxref{lex.digraph}{lex.operators} - +\removedxref{except.special} +\removedxref{except.special.general} %%% Deprecated features. %%% Example: From 66cf23b6091c1720624080f5a3a93797e5cdb730 Mon Sep 17 00:00:00 2001 From: Alisdair Meredith Date: Wed, 2 Oct 2024 12:53:22 -0400 Subject: [PATCH 18/18] Slightly less aggressive changes following feedback from Jens --- source/basic.tex | 1498 ++++++++++ source/lex.tex | 5727 ++++++++------------------------------- source/preprocessor.tex | 2009 ++++++++++++++ source/std.tex | 1 + 4 files changed, 4618 insertions(+), 4617 deletions(-) create mode 100644 source/preprocessor.tex diff --git a/source/basic.tex b/source/basic.tex index a33792f15b..ef90efa309 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -21,6 +21,1504 @@ Clauses. \end{note} +\rSec1[basic.exec]{Program execution} + +\rSec2[intro.execution]{Sequential execution} +\indextext{program execution|(} + +\pnum +An instance of each object with automatic storage +duration\iref{basic.stc.auto} is associated with each entry into its +block\iref{defns.block.stmt}. Such an object exists and retains its last-stored value during +the execution of the block and while the block is suspended (by a call +of a function, suspension of a coroutine\iref{expr.await}, or receipt of a signal). + +\pnum +A \defn{constituent expression} is defined as follows: +\begin{itemize} +\item +The constituent expression of an expression is that expression. +\item +The constituent expression of a conversion is +the corresponding implicit function call, if any, or +the converted expression otherwise. +\item +The constituent expressions of a \grammarterm{braced-init-list} or +of a (possibly parenthesized) \grammarterm{expression-list} +are the constituent expressions of the elements of the respective list. +\item +The constituent expressions of a \grammarterm{brace-or-equal-initializer} +of the form \tcode{=}~\grammarterm{initializer-clause} +are the constituent expressions of the \grammarterm{initializer-clause}. +\end{itemize} +\begin{example} +\begin{codeblock} +struct A { int x; }; +struct B { int y; struct A a; }; +B b = { 5, { 1+1 } }; +\end{codeblock} +The constituent expressions of the \grammarterm{initializer} +used for the initialization of \tcode{b} are \tcode{5} and \tcode{1+1}. +\end{example} + +\pnum +The \defnx{immediate subexpressions}{immediate subexpression} of an expression $E$ are +\begin{itemize} +\item +the constituent expressions of $E$'s operands\iref{expr.prop}, +\item +any function call that $E$ implicitly invokes, +\item +if $E$ is a \grammarterm{lambda-expression}\iref{expr.prim.lambda}, +the initialization of the entities captured by copy and +the constituent expressions of the \grammarterm{initializer} of the \grammarterm{init-capture}{s}, +\item +if $E$ is a function call\iref{expr.call} or implicitly invokes a function, +the constituent expressions of each default argument\iref{dcl.fct.default} +used in the call, or +\item +if $E$ creates an aggregate object\iref{dcl.init.aggr}, +the constituent expressions of each default member initializer\iref{class.mem} +used in the initialization. +\end{itemize} + +\pnum +A \defn{subexpression} of an expression $E$ is +an immediate subexpression of $E$ or +a subexpression of an immediate subexpression of $E$. +\begin{note} +Expressions appearing in the \grammarterm{compound-statement} of a \grammarterm{lambda-expression} +are not subexpressions of the \grammarterm{lambda-expression}. +\end{note} +The \defnadjx{potentially-evaluated}{subexpressions}{subexpression} of +an expression, conversion, or \grammarterm{initializer} $E$ are +\begin{itemize} +\item +the constituent expressions of $E$ and +\item +the subexpressions thereof that +are not subexpressions of a nested unevaluated operand\iref{term.unevaluated.operand}. +\end{itemize} + +\pnum +A \defn{full-expression} is +\begin{itemize} +\item +an unevaluated operand\iref{expr.context}, +\item +a \grammarterm{constant-expression}\iref{expr.const}, +\item +an immediate invocation\iref{expr.const}, +\item +an \grammarterm{init-declarator}\iref{dcl.decl} +(including such introduced by a structured binding\iref{dcl.struct.bind}) or +a \grammarterm{mem-initializer}\iref{class.base.init}, +including the constituent expressions of the initializer, +\item +an invocation of a destructor generated at the end of the lifetime +of an object other than a temporary object\iref{class.temporary} +whose lifetime has not been extended, or +\item +an expression that is not a subexpression of another expression and +that is not otherwise part of a full-expression. +\end{itemize} +If a language construct is defined to produce an implicit call of a function, +a use of the language construct is considered to be an expression +for the purposes of this definition. +Conversions applied to the result of an expression in order to satisfy the requirements +of the language construct in which the expression appears +are also considered to be part of the full-expression. +For an initializer, performing the initialization of the entity +(including evaluating default member initializers of an aggregate) +is also considered part of the full-expression. +\begin{example} +\begin{codeblock} +struct S { + S(int i): I(i) { } // full-expression is initialization of \tcode{I} + int& v() { return I; } + ~S() noexcept(false) { } +private: + int I; +}; + +S s1(1); // full-expression comprises call of \tcode{S::S(int)} +void f() { + S s2 = 2; // full-expression comprises call of \tcode{S::S(int)} + if (S(3).v()) // full-expression includes lvalue-to-rvalue and \tcode{int} to \tcode{bool} conversions, + // performed before temporary is deleted at end of full-expression + { } + bool b = noexcept(S(4)); // exception specification of destructor of \tcode{S} considered for \keyword{noexcept} + + // full-expression is destruction of \tcode{s2} at end of block +} +struct B { + B(S = S(0)); +}; +B b[2] = { B(), B() }; // full-expression is the entire initialization + // including the destruction of temporaries +\end{codeblock} +\end{example} + +\pnum +\begin{note} +The evaluation of a full-expression can include the +evaluation of subexpressions that are not lexically part of the +full-expression. For example, subexpressions involved in evaluating +default arguments\iref{dcl.fct.default} are considered to +be created in the expression that calls the function, not the expression +that defines the default argument. +\end{note} + +\pnum +\indextext{value computation|(}% +Reading an object designated by a \keyword{volatile} +glvalue\iref{basic.lval}, modifying an object, calling a library I/O +function, or calling a function that does any of those operations are +all +\defn{side effects}, which are changes in the state of the execution +environment. \defnx{Evaluation}{evaluation} 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 volatile 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 \keyword{volatile} access +may not have completed yet. + +\pnum +\defnx{Sequenced before}{sequenced before} is an asymmetric, transitive, pair-wise relation between +evaluations executed by a single thread\iref{intro.multithread}, which induces +a partial order among those evaluations. Given any two evaluations \placeholder{A} and +\placeholder{B}, if \placeholder{A} is sequenced before \placeholder{B} +(or, equivalently, \placeholder{B} is \defn{sequenced after} \placeholder{A}), +then the execution of +\placeholder{A} shall precede the execution of \placeholder{B}. If \placeholder{A} is not sequenced +before \placeholder{B} and \placeholder{B} is not sequenced before \placeholder{A}, then \placeholder{A} and +\placeholder{B} are \defn{unsequenced}. +\begin{note} +The execution of unsequenced +evaluations can overlap. +\end{note} +Evaluations \placeholder{A} and \placeholder{B} are +\defn{indeterminately sequenced} when either \placeholder{A} is sequenced before +\placeholder{B} or \placeholder{B} is sequenced before \placeholder{A}, but it is unspecified which. +\begin{note} +Indeterminately sequenced evaluations cannot overlap, but either +can be executed first. +\end{note} +An expression \placeholder{X} +is said to be sequenced before +an expression \placeholder{Y} if +every value computation and every side effect +associated with the expression \placeholder{X} +is sequenced before +every value computation and every side effect +associated with the expression \placeholder{Y}. + +\pnum +Every +\indextext{value computation}% +value computation and +\indextext{side effects}% +side effect associated with a full-expression is +sequenced before every value computation and side effect associated with the +next full-expression to be evaluated. +\begin{footnote} +As specified +in~\ref{class.temporary}, after a full-expression is evaluated, a sequence of +zero or more invocations of destructor functions for temporary objects takes +place, usually in reverse order of the construction of each temporary object. +\end{footnote} + +\pnum +\indextext{evaluation!unspecified order of}% +Except where noted, evaluations of operands of individual operators and +of subexpressions of individual expressions are unsequenced. +\begin{note} +In an expression that is evaluated more than once during the execution +of a program, unsequenced and indeterminately sequenced evaluations of +its subexpressions need not be performed consistently in different +evaluations. +\end{note} +The value computations of the operands of an +operator are sequenced before the value computation of the result of the +operator. If a +\indextext{side effects}% +side effect on a memory location\iref{intro.memory} is unsequenced +relative to either another side effect on the same memory location or +a value computation using the value of any object in the same memory location, +and they are not potentially concurrent\iref{intro.multithread}, +the behavior is undefined. +\begin{note} +The next subclause imposes similar, but more complex restrictions on +potentially concurrent computations. +\end{note} + +\begin{example} +\begin{codeblock} +void g(int i) { + i = 7, i++, i++; // \tcode{i} becomes \tcode{9} + + i = i++ + 1; // the value of \tcode{i} is incremented + i = i++ + i; // undefined behavior + i = i + 1; // the value of \tcode{i} is incremented +} +\end{codeblock} +\end{example} + +\pnum +When invoking a function (whether or not the function is inline), +every argument expression and +the postfix expression designating the called function +are sequenced before every expression or statement +in the body of the called function. +For each function invocation or +evaluation of an \grammarterm{await-expression} \placeholder{F}, +each evaluation that does not occur within \placeholder{F} but +is evaluated on the same thread and as part of the same signal handler (if any) +is either sequenced before all evaluations that occur within \placeholder{F} +or sequenced after all evaluations that occur within \placeholder{F}; +\begin{footnote} +In other words, +function executions do not interleave with each other. +\end{footnote} +if \placeholder{F} invokes or resumes a coroutine\iref{expr.await}, +only evaluations +subsequent to the previous suspension (if any) and +prior to the next suspension (if any) +are considered to occur within \placeholder{F}. + +Several contexts in \Cpp{} cause evaluation of a function call, even +though no corresponding function call syntax appears in the translation +unit. +\begin{example} +Evaluation of a \grammarterm{new-expression} invokes one or more allocation +and constructor functions; see~\ref{expr.new}. For another example, +invocation of a conversion function\iref{class.conv.fct} can arise in +contexts in which no function call syntax appears. +\end{example} +The sequencing constraints on the execution of the called function (as +described above) are features of the function calls as evaluated, +regardless of the syntax of the expression that calls the function.% +\indextext{value computation|)}% + +\indextext{behavior!on receipt of signal}% +\indextext{signal}% +\pnum +If a signal handler is executed as a result of a call to the \tcode{std::raise} +function, then the execution of the handler is sequenced after the invocation +of the \tcode{std::raise} function and before its return. +\begin{note} +When a signal is received for another reason, the execution of the +signal handler is usually unsequenced with respect to the rest of the program. +\end{note} + +\rSec2[intro.multithread]{Multi-threaded executions and data races} + +\rSec3[intro.multithread.general]{General} + +\pnum +\indextext{threads!multiple|(}% +\indextext{atomic!operation|(}% +A \defn{thread of execution} (also known as a \defn{thread}) is a single flow of +control within a program, including the initial invocation of a specific +top-level function, and recursively including every function invocation +subsequently executed by the thread. +\begin{note} +When one thread creates another, +the initial call to the top-level function of the new thread is executed by the +new thread, not by the creating thread. +\end{note} +Every thread in a program can +potentially access every object and function in a program. +\begin{footnote} +An object +with automatic or thread storage duration\iref{basic.stc} is associated with +one specific thread, and can be accessed by a different thread only indirectly +through a pointer or reference\iref{basic.compound}. +\end{footnote} +Under a hosted +implementation, a \Cpp{} program can have more than one thread running +concurrently. The execution of each thread proceeds as defined by the remainder +of this document. The execution of the entire program consists of an execution +of all of its threads. +\begin{note} +Usually the execution can be viewed as an +interleaving of all its threads. However, some kinds of atomic operations, for +example, allow executions inconsistent with a simple interleaving, as described +below. +\end{note} +\indextext{implementation!freestanding}% +Under a freestanding implementation, it is \impldef{number of +threads in a program under a freestanding implementation} whether a program can +have more than one thread of execution. + +\pnum +For a signal handler that is not executed as a result of a call to the +\tcode{std::raise} function, it is unspecified which thread of execution +contains the signal handler invocation. + +\rSec3[intro.races]{Data races} + +\pnum +The value of an object visible to a thread $T$ at a particular point is the +initial value of the object, a value assigned to the object by $T$, or a +value assigned to the object by another thread, according to the rules below. +\begin{note} +In some cases, there might instead be undefined behavior. Much of this +subclause is motivated by the desire to support atomic operations with explicit +and detailed visibility constraints. However, it also implicitly supports a +simpler view for more restricted programs. +\end{note} + +\pnum +Two expression evaluations \defn{conflict} if one of them modifies a memory +location\iref{intro.memory} and the other one reads or modifies the same +memory location. + +\pnum +The library defines a number of atomic operations\iref{atomics} and +operations on mutexes\iref{thread} that are specially identified as +synchronization operations. These operations play a special role in making +assignments in one thread visible to another. A synchronization operation on one +or more memory locations is either a consume operation, an acquire operation, a +release operation, or both an acquire and release operation. A synchronization +operation without an associated memory location is a fence and can be either an +acquire fence, a release fence, or both an acquire and release fence. In +addition, there are relaxed atomic operations, which are not synchronization +operations, and atomic read-modify-write operations, which have special +characteristics. +\begin{note} +For example, a call that acquires a mutex will +perform an acquire operation on the locations comprising the mutex. +Correspondingly, a call that releases the same mutex will perform a release +operation on those same locations. Informally, performing a release operation on +$A$ forces prior +\indextext{side effects}% +side effects on other memory locations to become visible +to other threads that later perform a consume or an acquire operation on +$A$. ``Relaxed'' atomic operations are not synchronization operations even +though, like synchronization operations, they cannot contribute to data races. +\end{note} + +\pnum +All modifications to a particular atomic object $M$ occur in some +particular total order, called the \defn{modification order} of $M$. +\begin{note} +There is a separate order for each +atomic object. There is no requirement that these can be combined into a single +total order for all objects. In general this will be impossible since different +threads can observe modifications to different objects in inconsistent orders. +\end{note} + +\pnum +A \defn{release sequence} headed +by a release operation $A$ on an atomic object $M$ +is a maximal contiguous sub-sequence of +\indextext{side effects}% +side effects in the modification order of $M$, +where the first operation is $A$, and +every subsequent operation is an atomic read-modify-write operation. + +\pnum +Certain library calls \defn{synchronize with} other library calls performed by +another thread. For example, an atomic store-release synchronizes with a +load-acquire that takes its value from the store\iref{atomics.order}. +\begin{note} +Except in the specified cases, reading a later value does not +necessarily ensure visibility as described below. Such a requirement would +sometimes interfere with efficient implementation. +\end{note} +\begin{note} +The +specifications of the synchronization operations define when one reads the value +written by another. For atomic objects, the definition is clear. All operations +on a given mutex occur in a single total order. Each mutex acquisition ``reads +the value written'' by the last mutex release. +\end{note} + +\pnum +An evaluation $A$ \defn{carries a dependency} to an evaluation $B$ if +\begin{itemize} +\item +the value of $A$ is used as an operand of $B$, unless: +\begin{itemize} +\item +$B$ is an invocation of any specialization of +\tcode{std::kill_dependency}\iref{atomics.order}, or +\item +$A$ is the left operand of a built-in logical \logop{and} (\tcode{\&\&}, +see~\ref{expr.log.and}) or logical \logop{or} (\tcode{||}, see~\ref{expr.log.or}) +operator, or +\item +$A$ is the left operand of a conditional (\tcode{?:}, see~\ref{expr.cond}) +operator, or +\item +$A$ is the left operand of the built-in comma (\tcode{,}) +operator\iref{expr.comma}; \end{itemize} or +\item +$A$ writes a scalar object or bit-field $M$, $B$ reads the value +written by $A$ from $M$, and $A$ is sequenced before $B$, or +\item +for some evaluation $X$, $A$ carries a dependency to $X$, and +$X$ carries a dependency to $B$. +\end{itemize} +\begin{note} +``Carries a dependency to'' is a subset of ``is sequenced before'', +and is similarly strictly intra-thread. +\end{note} + +\pnum +An evaluation $A$ is \defn{dependency-ordered before} an evaluation +$B$ if +\begin{itemize} +\item +$A$ performs a release operation on an atomic object $M$, and, in +another thread, $B$ performs a consume operation on $M$ and reads +the value written by $A$, or + +\item +for some evaluation $X$, $A$ is dependency-ordered before $X$ and +$X$ carries a dependency to $B$. + +\end{itemize} +\begin{note} +The relation ``is dependency-ordered before'' is analogous to +``synchronizes with'', but uses release/consume in place of release/acquire. +\end{note} + +\pnum +An evaluation $A$ \defn{inter-thread happens before} an evaluation $B$ +if +\begin{itemize} +\item + $A$ synchronizes with $B$, or +\item + $A$ is dependency-ordered before $B$, or +\item + for some evaluation $X$ + \begin{itemize} + \item + $A$ synchronizes with $X$ and $X$ + is sequenced before $B$, or + \item + $A$ is sequenced before $X$ and $X$ + inter-thread happens before $B$, or + \item + $A$ inter-thread happens before $X$ and $X$ + inter-thread happens before $B$. + \end{itemize} +\end{itemize} +\begin{note} +The ``inter-thread happens before'' relation describes arbitrary +concatenations of ``sequenced before'', ``synchronizes with'' and +``dependency-ordered before'' relationships, with two exceptions. The first +exception is that a concatenation never ends with +``dependency-ordered before'' followed by ``sequenced before''. The reason for +this limitation is that a consume operation participating in a +``dependency-ordered before'' relationship provides ordering only with respect +to operations to which this consume operation actually carries a dependency. The +reason that this limitation applies only to the end of such a concatenation is +that any subsequent release operation will provide the required ordering for a +prior consume operation. The second exception is that a concatenation never +consist entirely of ``sequenced before''. The reasons for this +limitation are (1) to permit ``inter-thread happens before'' to be transitively +closed and (2) the ``happens before'' relation, defined below, provides for +relationships consisting entirely of ``sequenced before''. +\end{note} + +\pnum +An evaluation $A$ \defn{happens before} an evaluation $B$ +(or, equivalently, $B$ \defn{happens after} $A$) if +\begin{itemize} +\item $A$ is sequenced before $B$, or +\item $A$ inter-thread happens before $B$. +\end{itemize} +The implementation shall ensure that no program execution demonstrates a cycle +in the ``happens before'' relation. +\begin{note} +This cycle would otherwise be +possible only through the use of consume operations. +\end{note} + +\pnum +An evaluation $A$ \defn{simply happens before} an evaluation $B$ +if either +\begin{itemize} +\item $A$ is sequenced before $B$, or +\item $A$ synchronizes with $B$, or +\item $A$ simply happens before $X$ and +$X$ simply happens before $B$. +\end{itemize} +\begin{note} +In the absence of consume operations, +the happens before and simply happens before relations are identical. +\end{note} + +\pnum +An evaluation $A$ \defn{strongly happens before} +an evaluation $D$ if, either +\begin{itemize} +\item $A$ is sequenced before $D$, or +\item $A$ synchronizes with $D$, and +both $A$ and $D$ are +sequentially consistent atomic operations\iref{atomics.order}, or +\item there are evaluations $B$ and $C$ +such that $A$ is sequenced before $B$, +$B$ simply happens before $C$, and +$C$ is sequenced before $D$, or +\item there is an evaluation $B$ such that +$A$ strongly happens before $B$, and +$B$ strongly happens before $D$. +\end{itemize} +\begin{note} +Informally, if $A$ strongly happens before $B$, +then $A$ appears to be evaluated before $B$ +in all contexts. Strongly happens before excludes consume operations. +\end{note} + +\pnum +A \defnadjx{visible}{side effect}{side effects} $A$ on a scalar object or bit-field $M$ +with respect to a value computation $B$ of $M$ satisfies the +conditions: +\begin{itemize} +\item $A$ happens before $B$ and +\item there is no other +\indextext{side effects}% +side effect $X$ to $M$ such that $A$ +happens before $X$ and $X$ happens before $B$. +\end{itemize} + +The value of a non-atomic scalar object or bit-field $M$, as determined by +evaluation $B$, is the value stored by the +\indextext{side effects!visible}% +visible side effect $A$. +\begin{note} +If there is ambiguity about which side effect to a +non-atomic object or bit-field is visible, then the behavior is either +unspecified or undefined. +\end{note} +\begin{note} +This states that operations on +ordinary objects are not visibly reordered. This is not actually detectable +without data races, but is needed to ensure that data races, as defined +below, and with suitable restrictions on the use of atomics, correspond to data +races in a simple interleaved (sequentially consistent) execution. +\end{note} + +\pnum +The value of an +atomic object $M$, as determined by evaluation $B$, is the value +stored by some unspecified +side effect $A$ that modifies $M$, where $B$ does not happen +before $A$. +\begin{note} +The set of such side effects is also restricted by the rest of the rules +described here, and in particular, by the coherence requirements below. +\end{note} + +\pnum +\indextext{coherence!write-write}% +If an operation $A$ that modifies an atomic object $M$ happens before +an operation $B$ that modifies $M$, then $A$ is earlier +than $B$ in the modification order of $M$. +\begin{note} +This requirement is known as write-write coherence. +\end{note} + +\pnum +\indextext{coherence!read-read}% +If a +\indextext{value computation}% +value computation $A$ of an atomic object $M$ happens before a +value computation $B$ of $M$, and $A$ takes its value from a side +effect $X$ on $M$, then the value computed by $B$ is either +the value stored by $X$ or the value stored by a +\indextext{side effects}% +side effect $Y$ on $M$, +where $Y$ follows $X$ in the modification order of $M$. +\begin{note} +This requirement is known as read-read coherence. +\end{note} + +\pnum +\indextext{coherence!read-write}% +If a +\indextext{value computation}% +value computation $A$ of an atomic object $M$ happens before an +operation $B$ that modifies $M$, then $A$ takes its value from a side +effect $X$ on $M$, where $X$ precedes $B$ in the +modification order of $M$. +\begin{note} +This requirement is known as +read-write coherence. +\end{note} + +\pnum +\indextext{coherence!write-read}% +If a +\indextext{side effects}% +side effect $X$ on an atomic object $M$ happens before a value +computation $B$ of $M$, then the evaluation $B$ takes its +value from $X$ or from a +\indextext{side effects}% +side effect $Y$ that follows $X$ in the modification order of $M$. +\begin{note} +This requirement is known as write-read coherence. +\end{note} + +\pnum +\begin{note} +The four preceding coherence requirements effectively disallow +compiler reordering of atomic operations to a single object, even if both +operations are relaxed loads. This effectively makes the cache coherence +guarantee provided by most hardware available to \Cpp{} atomic operations. +\end{note} + +\pnum +\begin{note} +The value observed by a load of an atomic depends on the ``happens +before'' relation, which depends on the values observed by loads of atomics. +The intended reading is that there must exist an +association of atomic loads with modifications they observe that, together with +suitably chosen modification orders and the ``happens before'' relation derived +as described above, satisfy the resulting constraints as imposed here. +\end{note} + +\pnum +Two actions are \defn{potentially concurrent} if +\begin{itemize} +\item they are performed by different threads, or +\item they are unsequenced, at least one is performed by a signal handler, and +they are not both performed by the same signal handler invocation. +\end{itemize} +The execution of a program contains a \defn{data race} if it contains two +potentially concurrent conflicting actions, at least one of which is not atomic, +and neither happens before the other, +except for the special case for signal handlers described below. +Any such data race results in undefined +behavior. +\begin{note} +It can be shown that programs that correctly use mutexes +and \tcode{memory_order::seq_cst} operations to prevent all data races and use no +other synchronization operations behave as if the operations executed by their +constituent threads were simply interleaved, with each +\indextext{value computation}% +value computation of an +object being taken from the last +\indextext{side effects}% +side effect on that object in that +interleaving. This is normally referred to as ``sequential consistency''. +However, this applies only to data-race-free programs, and data-race-free +programs cannot observe most program transformations that do not change +single-threaded program semantics. In fact, most single-threaded program +transformations remain possible, since any program that behaves +differently as a result has undefined behavior. +\end{note} + +\pnum +Two accesses to the same object of type \tcode{\keyword{volatile} std::sig_atomic_t} 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 \tcode{\keyword{volatile} std::sig_atomic_t} 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$. + +\pnum +\begin{note} +Compiler transformations that introduce assignments to a potentially +shared memory location that would not be modified by the abstract machine are +generally precluded by this document, since such an assignment might overwrite +another assignment by a different thread in cases in which an abstract machine +execution would not have encountered a data race. This includes implementations +of data member assignment that overwrite adjacent members in separate memory +locations. Reordering of atomic loads in cases in which the atomics in question +might alias is also generally precluded, since this could violate the coherence +rules. +\end{note} + +\pnum +\begin{note} +It is possible that transformations that introduce a speculative read of a potentially +shared memory location do not preserve the semantics of the \Cpp{} program as +defined in this document, since they potentially introduce a data race. However, +they are typically valid in the context of an optimizing compiler that targets a +specific machine with well-defined semantics for data races. They would be +invalid for a hypothetical machine that is not tolerant of races or provides +hardware race detection. +\end{note} + +\rSec3[intro.progress]{Forward progress} + +\pnum +The implementation may assume that any thread will eventually do one of the +following: +\begin{itemize} +\item terminate, +\item invoke the function \tcode{std::this_thread::yield}\iref{thread.thread.this}, +\item make a call to a library I/O function, +\item perform an access through a volatile glvalue, +\item perform a synchronization operation or an atomic operation, or +\item continue execution of a trivial infinite loop\iref{stmt.iter.general}. +\end{itemize} +\begin{note} +This is intended to allow compiler transformations +such as removal, merging, and reordering of empty loops, +even when termination cannot be proven. +An affordance is made for trivial infinite loops, +which cannot be removed nor reordered. +\end{note} + +\pnum +Executions of atomic functions +that are either defined to be lock-free\iref{atomics.flag} +or indicated as lock-free\iref{atomics.lockfree} +are \defnx{lock-free executions}{lock-free execution}. +\begin{itemize} +\item + If there is only one thread that is not blocked\iref{defns.block} + in a standard library function, + a lock-free execution in that thread shall complete. + \begin{note} + Concurrently executing threads + might prevent progress of a lock-free execution. + For example, + this situation can occur + with load-locked store-conditional implementations. + This property is sometimes termed obstruction-free. + \end{note} +\item + When one or more lock-free executions run concurrently, + at least one should complete. + \begin{note} + It is difficult for some implementations + to provide absolute guarantees to this effect, + since repeated and particularly inopportune interference + from other threads + could prevent forward progress, + e.g., + by repeatedly stealing a cache line + for unrelated purposes + between load-locked and store-conditional instructions. + For implementations that follow this recommendation and + ensure that such effects cannot indefinitely delay progress + under expected operating conditions, + such anomalies + can therefore safely be ignored by programmers. + Outside this document, + this property is sometimes termed lock-free. + \end{note} +\end{itemize} + +\pnum +During the execution of a thread of execution, each of the following is termed +an \defn{execution step}: +\begin{itemize} +\item termination of the thread of execution, +\item performing an access through a volatile glvalue, or +\item completion of a call to a library I/O function, a + synchronization operation, or an atomic operation. +\end{itemize} + +\pnum +An invocation of a standard library function that blocks\iref{defns.block} +is considered to continuously execute execution steps while waiting for the +condition that it blocks on to be satisfied. +\begin{example} +A library I/O function that blocks until the I/O operation is complete can +be considered to continuously check whether the operation is complete. Each +such check consists of one or more execution steps, for example using +observable behavior of the abstract machine. +\end{example} + +\pnum +\begin{note} +Because of this and the preceding requirement regarding what threads of execution +have to perform eventually, it follows that no thread of execution can execute +forever without an execution step occurring. +\end{note} + +\pnum +A thread of execution \defnx{makes progress}{make progress!thread} +when an execution step occurs or a +lock-free execution does not complete because there are other concurrent threads +that are not blocked in a standard library function (see above). + +\pnum +\indextext{forward progress guarantees!concurrent}% +For a thread of execution providing \defn{concurrent forward progress guarantees}, +the implementation ensures that the thread will eventually make progress for as +long as it has not terminated. +\begin{note} +This applies regardless of whether or not other threads of execution (if any) +have been or are making progress. To eventually fulfill this requirement means that +this will happen in an unspecified but finite amount of time. +\end{note} + +\pnum +It is \impldef{whether the thread that executes \tcode{main} and the threads created +by \tcode{std::thread} or \tcode{std::jthread} provide concurrent forward progress guarantees} whether the +implementation-created thread of execution that executes +\tcode{main}\iref{basic.start.main} and the threads of execution created by +\tcode{std::thread}\iref{thread.thread.class} +or \tcode{std::jthread}\iref{thread.jthread.class} +provide concurrent forward progress guarantees. +General-purpose implementations should provide these guarantees. + +\pnum +\indextext{forward progress guarantees!parallel}% +For a thread of execution providing \defn{parallel forward progress guarantees}, +the implementation is not required to ensure that the thread will eventually make +progress if it has not yet executed any execution step; once this thread has +executed a step, it provides concurrent forward progress guarantees. + +\pnum +\begin{note} +This does not specify a requirement for when to start this thread of execution, +which will typically be specified by the entity that creates this thread of +execution. For example, a thread of execution that provides concurrent forward +progress guarantees and executes tasks from a set of tasks in an arbitrary order, +one after the other, satisfies the requirements of parallel forward progress for +these tasks. +\end{note} + +\pnum +\indextext{forward progress guarantees!weakly parallel}% +For a thread of execution providing \defn{weakly parallel forward progress +guarantees}, the implementation does not ensure that the thread will eventually +make progress. + +\pnum +\begin{note} +Threads of execution providing weakly parallel forward progress guarantees cannot +be expected to make progress regardless of whether other threads make progress or +not; however, blocking with forward progress guarantee delegation, as defined below, +can be used to ensure that such threads of execution make progress eventually. +\end{note} + +\pnum +Concurrent forward progress guarantees are stronger than parallel forward progress +guarantees, which in turn are stronger than weakly parallel forward progress +guarantees. +\begin{note} +For example, some kinds of synchronization between threads of execution might only +make progress if the respective threads of execution provide parallel forward progress +guarantees, but will fail to make progress under weakly parallel guarantees. +\end{note} + +\pnum +\indextext{forward progress guarantees!delegation of}% +When a thread of execution $P$ is specified to +\defnx{block with forward progress guarantee delegation} +{block (execution)!with forward progress guarantee delegation} +on the completion of a set $S$ of threads of execution, +then throughout the whole time of $P$ being blocked on $S$, +the implementation shall ensure that the forward progress guarantees +provided by at least one thread of execution in $S$ +is at least as strong as $P$'s forward progress guarantees. +\begin{note} +It is unspecified which thread or threads of execution in $S$ are chosen +and for which number of execution steps. The strengthening is not permanent and +not necessarily in place for the rest of the lifetime of the affected thread of +execution. As long as $P$ is blocked, the implementation has to eventually +select and potentially strengthen a thread of execution in $S$. +\end{note} +Once a thread of execution in $S$ terminates, it is removed from $S$. +Once $S$ is empty, $P$ is unblocked. + +\pnum +\begin{note} +A thread of execution $B$ thus can temporarily provide an effectively +stronger forward progress guarantee for a certain amount of time, due to a +second thread of execution $A$ being blocked on it with forward +progress guarantee delegation. In turn, if $B$ then blocks with +forward progress guarantee delegation on $C$, this can also temporarily +provide a stronger forward progress guarantee to $C$. +\end{note} + +\pnum +\begin{note} +If all threads of execution in $S$ finish executing (e.g., they terminate +and do not use blocking synchronization incorrectly), then $P$'s execution +of the operation that blocks with forward progress guarantee delegation will not +result in $P$'s progress guarantee being effectively weakened. +\end{note} + +\pnum +\begin{note} +This does not remove any constraints regarding blocking synchronization for +threads of execution providing parallel or weakly parallel forward progress +guarantees because the implementation is not required to strengthen a particular +thread of execution whose too-weak progress guarantee is preventing overall progress. +\end{note} + +\pnum +An implementation should ensure that the last value (in modification order) +assigned by an atomic or synchronization operation will become visible to all +other threads in a finite period of time.% +\indextext{atomic!operation|)}% +\indextext{threads!multiple|)} + +\rSec2[basic.start]{Start and termination} + +\rSec3[basic.start.main]{\tcode{main} function} +\indextext{\idxcode{main} function|(} + +\pnum +\indextext{program!startup|(}% +A program shall contain exactly one function called \tcode{main} +that belongs to the global scope. +Executing a program starts a main thread of execution\iref{intro.multithread,thread.threads} +in which the \tcode{main} function is invoked. +\indextext{implementation!freestanding}% +It is \impldef{defining \tcode{main} in freestanding environment} +whether a program in a freestanding environment is required to define a \tcode{main} +function. +\begin{note} +In a freestanding environment, startup and termination is +\impldef{startup and termination in freestanding environment}; startup contains the +execution of constructors for non-local objects with static storage duration; +termination contains the execution of destructors for objects with static storage +duration. +\end{note} + +\pnum +An implementation shall not predefine the \tcode{main} function. +Its type shall have \Cpp{} language linkage +and it shall have a declared return type of type +\keyword{int}, but otherwise its type is \impldef{parameters to \tcode{main}}. +\indextext{\idxcode{main} function!implementation-defined parameters to}% +An implementation shall allow both +\begin{itemize} +\item a function of \tcode{()} returning \keyword{int} and +\item a function of \tcode{(\keyword{int}}, pointer to pointer to \tcode{\keyword{char})} returning \keyword{int} +\end{itemize} +\indextext{\idxcode{argc}}% +\indextext{\idxcode{argv}}% +as the type of \tcode{main}\iref{dcl.fct}. +\indextext{\idxcode{main} function!parameters to}% +\indextext{environment!program}% +In the latter form, for purposes of exposition, the first function +parameter is called \tcode{argc} and the second function parameter is +called \tcode{argv}, where \tcode{argc} shall be the number of +arguments passed to the program from the environment in which the +program is run. If +\tcode{argc} is nonzero these arguments shall be supplied in +\tcode{argv[0]} through \tcode{argv[argc-1]} as pointers to the initial +characters of null-terminated multibyte strings (\ntmbs{}s)\iref{multibyte.strings} +and \tcode{argv[0]} shall be the pointer to +the initial character of an \ntmbs{} that represents the name used to +invoke the program or \tcode{""}. The value of \tcode{argc} shall be +non-negative. The value of \tcode{argv[argc]} shall be 0. + +\recommended +Any further (optional) parameters should be added after \tcode{argv}. + +\pnum +The function \tcode{main} shall not be named by an expression. +\indextext{\idxcode{main} function!implementation-defined linkage of}% +The linkage\iref{basic.link} of \tcode{main} is +\impldef{linkage of \tcode{main}}. A program that defines \tcode{main} as +deleted or that declares \tcode{main} to be +\keyword{inline}, \keyword{static}, \keyword{constexpr}, or \keyword{consteval} is ill-formed. +The function \tcode{main} shall not be a coroutine\iref{dcl.fct.def.coroutine}. +The \tcode{main} function shall not be declared with a +\grammarterm{linkage-specification}\iref{dcl.link}. +A program that declares +\begin{itemize} +\item +a variable \tcode{main} that belongs to the global scope, or +\item +a function \tcode{main} that belongs to the global scope and +is attached to a named module, or +\item +a function template \tcode{main} that belongs to the global scope, or +\item +an entity named \tcode{main} +with C language linkage (in any namespace) +\end{itemize} +is ill-formed. +The name \tcode{main} is +not otherwise reserved. +\begin{example} +Member functions, classes, and +enumerations can be called \tcode{main}, as can entities in other +namespaces. +\end{example} + +\pnum +\indextext{\idxcode{exit}}% +\indexlibraryglobal{exit}% +\indextext{termination!program}% +Terminating the program +without leaving the current block (e.g., by calling the function +\tcode{std::exit(int)}\iref{support.start.term}) does not destroy any +objects with automatic storage duration\iref{class.dtor}. If +\tcode{std::exit} is invoked during the destruction of +an object with static or thread storage duration, the program has undefined +behavior. + +\pnum +\indextext{termination!program}% +\indextext{\idxcode{main} function!return from}% +A \keyword{return} statement\iref{stmt.return} in \tcode{main} has the effect of leaving the main +function (destroying any objects with automatic storage duration) and +calling \tcode{std::exit} with the return value as the argument. +If control flows off the end of +the \grammarterm{compound-statement} of \tcode{main}, +the effect is equivalent to a \keyword{return} with operand \tcode{0} +(see also \ref{except.handle}). +\indextext{\idxcode{main} function|)} + +\rSec3[basic.start.static]{Static initialization} + +\pnum +\indextext{initialization}% +\indextext{initialization!static and thread}% +Variables with static storage duration +are initialized as a consequence of program initiation. Variables with +thread storage duration are initialized as a consequence of thread execution. +Within each of these phases of initiation, initialization occurs as follows. + +\pnum +\indextext{initialization!constant}% +\defnx{Constant initialization}{constant initialization} is performed +if a variable or temporary object with static or thread storage duration +is constant-initialized\iref{expr.const}. +\indextext{initialization!zero-initialization}% +If constant initialization is not performed, a variable with static +storage duration\iref{basic.stc.static} or thread storage +duration\iref{basic.stc.thread} is zero-initialized\iref{dcl.init}. +Together, zero-initialization and constant initialization are called +\defnadj{static}{initialization}; +all other initialization is \defnadj{dynamic}{initialization}. +All static initialization strongly happens before\iref{intro.races} +any dynamic initialization. +\begin{note} +The dynamic initialization of non-block variables is described +in~\ref{basic.start.dynamic}; that of static block variables is described +in~\ref{stmt.dcl}. +\end{note} + +\pnum +An implementation is permitted to perform the initialization of a +variable with static or thread storage duration as a static +initialization even if such initialization is not required to be done +statically, provided that +\begin{itemize} +\item +the dynamic version of the initialization does not change the +value of any other object of static or thread storage duration +prior to its initialization, and + +\item +the static version of the initialization produces the same value +in the initialized variable as would be produced by the dynamic +initialization if all variables not required to be initialized statically +were initialized dynamically. +\end{itemize} +\begin{note} +As a consequence, if the initialization of an object \tcode{obj1} refers to an +object \tcode{obj2} potentially requiring dynamic initialization and defined +later in the same translation unit, it is unspecified whether the value of \tcode{obj2} used +will be the value of the fully initialized \tcode{obj2} (because \tcode{obj2} was statically +initialized) or will be the value of \tcode{obj2} merely zero-initialized. For example, +\begin{codeblock} +inline double fd() { return 1.0; } +extern double d1; +double d2 = d1; // unspecified: + // either statically initialized to \tcode{0.0} or + // dynamically initialized to \tcode{0.0} if \tcode{d1} is + // dynamically initialized, or \tcode{1.0} otherwise +double d1 = fd(); // either initialized statically or dynamically to \tcode{1.0} +\end{codeblock} +\end{note} + +\rSec3[basic.start.dynamic]{Dynamic initialization of non-block variables} + +\pnum +\indextext{initialization!dynamic non-block}% +\indextext{start!program}% +\indextext{initialization!order of}% +Dynamic initialization of a non-block variable with static storage duration is +unordered if the variable is an implicitly or explicitly instantiated +specialization, is partially-ordered if the variable +is an inline variable that is not an implicitly or explicitly instantiated +specialization, and otherwise is ordered. +\begin{note} +A non-inline explicit specialization of a templated variable +has ordered initialization. +\end{note} + +\pnum +A declaration \tcode{D} is +\defn{appearance-ordered} before a declaration \tcode{E} if +\begin{itemize} +\item \tcode{D} appears in the same translation unit as \tcode{E}, or +\item the translation unit containing \tcode{E} +has an interface dependency on the translation unit containing \tcode{D}, +\end{itemize} +in either case prior to \tcode{E}. + +\pnum +Dynamic initialization of non-block variables \tcode{V} and \tcode{W} +with static storage duration are ordered as follows: +\begin{itemize} +\item +If \tcode{V} and \tcode{W} have ordered initialization and +the definition of \tcode{V} +is appearance-ordered before the definition of \tcode{W}, or +if \tcode{V} has partially-ordered initialization, +\tcode{W} does not have unordered initialization, and +for every definition \tcode{E} of \tcode{W} +there exists a definition \tcode{D} of \tcode{V} +such that \tcode{D} is appearance-ordered before \tcode{E}, then +\begin{itemize} +\item +if the program does not start a thread\iref{intro.multithread} +other than the main thread\iref{basic.start.main} +or \tcode{V} and \tcode{W} have ordered initialization and +they are defined in the same translation unit, +the initialization of \tcode{V} +is sequenced before +the initialization of \tcode{W}; +\item +otherwise, +the initialization of \tcode{V} +strongly happens before +the initialization of \tcode{W}. +\end{itemize} + +\item +Otherwise, if the program starts a thread +other than the main thread +before either \tcode{V} or \tcode{W} is initialized, +it is unspecified in which threads +the initializations of \tcode{V} and \tcode{W} occur; +the initializations are unsequenced if they occur in the same thread. + +\item +Otherwise, the initializations of \tcode{V} and \tcode{W} are indeterminately sequenced. +\end{itemize} +\begin{note} +This definition permits initialization of a sequence of +ordered variables concurrently with another sequence. +\end{note} + +\pnum +\indextext{non-initialization odr-use|see{odr-use, non-initialization}}% +A \defnx{non-initialization odr-use}{odr-use!non-initialization} +is an odr-use\iref{term.odr.use} not caused directly or indirectly by +the initialization of a non-block static or thread storage duration variable. + +\pnum +\indextext{evaluation!unspecified order of}% +It is \impldef{dynamic initialization of static variables before \tcode{main}} +whether the dynamic initialization of a +non-block non-inline variable with static storage duration +is sequenced before the first statement of \tcode{main} or is deferred. +If it is deferred, it strongly happens before +any non-initialization odr-use +of any non-inline function or non-inline variable +defined in the same translation unit as the variable to be initialized. +\begin{footnote} +A non-block variable with static storage duration +having initialization +with side effects is initialized in this case, +even if it is not itself odr-used\iref{term.odr.use,basic.stc.static}. +\end{footnote} +It is \impldef{threads and program points at which deferred dynamic initialization is performed} +in which threads and at which points in the program such deferred dynamic initialization occurs. + +\recommended +An implementation should choose such points in a way +that allows the programmer to avoid deadlocks. +\begin{example} +\begin{codeblock} +// - File 1 - +#include "a.h" +#include "b.h" +B b; +A::A() { + b.Use(); +} + +// - File 2 - +#include "a.h" +A a; + +// - File 3 - +#include "a.h" +#include "b.h" +extern A a; +extern B b; + +int main() { + a.Use(); + b.Use(); +} +\end{codeblock} + +It is \impldef{dynamic initialization of static variables before \tcode{main}} +whether either \tcode{a} or \tcode{b} is +initialized before \tcode{main} is entered or whether the +initializations are delayed until \tcode{a} is first odr-used in +\tcode{main}. In particular, if \tcode{a} is initialized before +\tcode{main} is entered, it is not guaranteed that \tcode{b} will be +initialized before it is odr-used by the initialization of \tcode{a}, that +is, before \tcode{A::A} is called. If, however, \tcode{a} is initialized +at some point after the first statement of \tcode{main}, \tcode{b} will +be initialized prior to its use in \tcode{A::A}. +\end{example} + +\pnum +It is \impldef{dynamic initialization of static inline variables before \tcode{main}} +whether the dynamic initialization of a +non-block inline variable with static storage duration +is sequenced before the first statement of \tcode{main} or is deferred. +If it is deferred, it strongly happens before +any non-initialization odr-use +of that variable. +It is \impldef{threads and program points at which deferred dynamic initialization is performed} +in which threads and at which points in the program such deferred dynamic initialization occurs. + +\pnum +It is \impldef{dynamic initialization of thread-local variables before entry} +whether the dynamic initialization of a +non-block non-inline variable with thread storage duration +is sequenced before the first statement of the initial function of a thread or is deferred. +If it is deferred, +the initialization associated with the entity for thread \placeholder{t} +is sequenced before the first non-initialization odr-use by \placeholder{t} +of any non-inline variable with thread storage duration +defined in the same translation unit as the variable to be initialized. +It is \impldef{threads and program points at which deferred dynamic initialization is performed} +in which threads and at which points in the program such deferred dynamic initialization occurs. + +\pnum +If the initialization of +a non-block variable with static or thread storage duration +exits via an exception, +the function \tcode{std::terminate} is called\iref{except.terminate}.% +\indextext{program!startup|)} + +\rSec3[basic.start.term]{Termination} + +\pnum +\indextext{program!termination|(}% +\indextext{object!destructor static}% +\indextext{\idxcode{main} function!return from}% +Constructed objects\iref{dcl.init} +with static storage duration are destroyed +and functions registered with \tcode{std::atexit} +are called as part of a call to +\indextext{\idxcode{exit}}% +\indexlibraryglobal{exit}% +\tcode{std::exit}\iref{support.start.term}. +The call to \tcode{std::exit} is sequenced before +the destructions and the registered functions. +\begin{note} +Returning from \tcode{main} invokes \tcode{std::exit}\iref{basic.start.main}. +\end{note} + +\pnum +Constructed objects with thread storage duration within a given thread +are destroyed as a result of returning from the initial function of that thread and as a +result of that thread calling \tcode{std::exit}. +The destruction of all constructed objects with thread storage +duration within that thread strongly happens before destroying +any object with static storage duration. + +\pnum +If the completion of the constructor or dynamic initialization of an object with static +storage duration strongly happens before that of another, the completion of the destructor +of the second is sequenced before the initiation of the destructor of the first. +If the completion of the constructor or dynamic initialization of an object with thread +storage duration is sequenced before that of another, the completion of the destructor +of the second is sequenced before the initiation of the destructor of the first. +If an object is +initialized statically, the object is destroyed in the same order as if +the object was dynamically initialized. For an object of array or class +type, all subobjects of that object are destroyed before any block +variable with static storage duration initialized during the construction +of the subobjects is destroyed. +If the destruction of an object with static or thread storage duration +exits via an exception, +the function \tcode{std::terminate} is called\iref{except.terminate}. + +\pnum +If a function contains a block variable of static or thread storage duration that has been +destroyed and the function is called during the destruction of an object with static or +thread storage duration, the program has undefined behavior if the flow of control +passes through the definition of the previously destroyed block variable. +\begin{note} +Likewise, the behavior is undefined +if the block variable is used indirectly (e.g., through a pointer) +after its destruction. +\end{note} + +\pnum +\indextext{\idxcode{atexit}}% +\indexlibraryglobal{atexit}% +If the completion of the initialization of an object with static storage +duration strongly happens before a call to \tcode{std::atexit}~(see +\libheader{cstdlib}, \ref{support.start.term}), the call to the function passed to +\tcode{std::atexit} is sequenced before the call to the destructor for the object. If a +call to \tcode{std::atexit} strongly happens before the completion of the initialization of +an object with static storage duration, the call to the destructor for the +object is sequenced before the call to the function passed to \tcode{std::atexit}. If a +call to \tcode{std::atexit} strongly happens before another call to \tcode{std::atexit}, the +call to the function passed to the second \tcode{std::atexit} call is sequenced before +the call to the function passed to the first \tcode{std::atexit} call. + +\pnum +If there is a use of a standard library object or function not permitted within signal +handlers\iref{support.runtime} that does not happen before\iref{intro.multithread} +completion of destruction of objects with static storage duration and execution of +\tcode{std::atexit} registered functions\iref{support.start.term}, the program has +undefined behavior. +\begin{note} +If there is a use of an object with static storage +duration that does not happen before the object's destruction, the program has undefined +behavior. Terminating every thread before a call to \tcode{std::exit} or the exit from +\tcode{main} is sufficient, but not necessary, to satisfy these requirements. These +requirements permit thread managers as static-storage-duration objects. +\end{note} + +\pnum +\indextext{\idxcode{abort}}% +\indexlibraryglobal{abort}% +\indextext{termination!program}% +Calling the function \tcode{std::abort()} declared in +\libheaderref{cstdlib} terminates the program without executing any destructors +and without calling +the functions passed to \tcode{std::atexit()} or \tcode{std::at_quick_exit()}.% +\indextext{program!termination|)} + +\rSec3[except.terminate]{The \tcode{std::terminate} function} + +\pnum +\indextext{\idxcode{terminate}}% +In some situations the \Cpp{} runtime encounters an error that cannot be recovered, +such as when an exception is not handled, or a thread is destroyed while still running. +In such cases, +the function \tcode{std::terminate} is invoked\iref{exception.terminate}. +\begin{note} +These situations are: +\indextext{\idxcode{terminate}!called}% +\begin{itemize} +\item% +when initialization of a non-block +variable with static or thread storage duration\iref{basic.start.dynamic} +exits via an exception, or + +\item% +when destruction of an object with static or thread storage duration exits +via an exception\iref{basic.start.term}, or + +\item% +when a +\grammarterm{throw-expression}\iref{expr.throw} +with no operand attempts to rethrow an exception and no exception is being +handled\iref{except.throw}, or + +\item% +when the exception handling mechanism, after completing +the initialization of the exception object +but before +activation of a handler for the exception\iref{except.throw}, +calls a function that exits +via an exception, or + +\item% +when the destruction of an object during stack unwinding\iref{except.ctor} +terminates by throwing an exception, or + +\item when the search for a handler\iref{except.handle} encounters the +outermost block of a function +with a non-throwing exception specification, or + +\item% +when the exception handling mechanism cannot find a handler for a thrown exception\iref{except.handle}, or + +\item% +when execution of a function registered with +\tcode{std::atexit} or \tcode{std::at_quick_exit} +exits via an exception\iref{support.start.term}, or + +\item% +when the function \tcode{std::nested_exception::rethrow_nested} is called for an object +that has captured no exception\iref{except.nested}, or + +\item% +for a parallel algorithm whose \tcode{ExecutionPolicy} specifies such +behavior\iref{execpol.seq,execpol.par,execpol.parunseq}, +when execution of an element access function\iref{algorithms.parallel.defns} +of the parallel algorithm exits via an exception\iref{algorithms.parallel.exceptions}, or + +\item% +when a callback invocation exits via an exception +when requesting stop on +a \tcode{std::stop_source} or +a \tcode{std::in\-place_stop_source}\iref{stopsource.mem,stopsource.inplace.mem}, +or in the constructor of +\tcode{std::stop_callback} or +\tcode{std::inplace_stop_callback}\iref{stopcallback.cons,stopcallback.inplace.cons} +when a callback invocation exits via an exception, or + +\item% +when execution of the initial function of a thread exits via +an exception\iref{thread.thread.constr}, or + +\item% +when the destructor or the move assignment operator is invoked on an object +of type \tcode{std::thread} that refers to +a joinable thread\iref{thread.thread.destr,thread.thread.assign}, or + +\item% +when a call to a \tcode{wait()}, \tcode{wait_until()}, or \tcode{wait_for()} +function on a condition variable\iref{thread.condition.condvar,thread.condition.condvarany} +fails to meet a postcondition, or + +\item% +when a \tcode{run_loop} object is destroyed +that is still in the \tcode{running} state\iref{exec.run.loop}, or + +\item% +when \tcode{unhandled_stopped} is called on +a \tcode{with_awaitable_senders} object\iref{exec.with.awaitable.senders} +whose continuation is not a handle to a coroutine +whose promise type has an \tcode{unhandled_stopped} member function. + +\end{itemize} +\end{note} + +\pnum +In the situation where no matching handler is found, it is +\impldef{stack unwinding before invocation of \tcode{std::terminate}} +whether or not the stack is unwound +before \tcode{std::terminate} is invoked. +In the situation where the search for a handler\iref{except.handle} encounters the +outermost block of a function +with a non-throwing exception specification, it is +\impldef{whether stack is unwound before invoking the function \tcode{std::terminate} +when a \tcode{noexcept} specification is violated} +whether the stack is unwound, unwound partially, or not unwound at all +before the function \tcode{std::terminate} is invoked. +In all other situations, the stack shall not be unwound before +the function \tcode{std::terminate} +is invoked. +An implementation is not permitted to finish stack unwinding +prematurely based on a determination that the unwind process +will eventually cause an invocation of the function +\tcode{std::terminate}. +\indextext{program execution|)} + \rSec1[basic.memobj]{Memory and objects} \rSec2[intro.memory]{Memory model} diff --git a/source/lex.tex b/source/lex.tex index 148f690fd7..c2c72b275d 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -1457,4862 +1457,1355 @@ \end{itemize}% \indextext{identifier|)} +\rSec1[lex.tutokenize]{Translation unit tokenization} +\rSec2[lex.token]{Tokens} -\rSec1[cpp]{Preprocessing directives}% -\indextext{preprocessing directive|(} - -\indextext{compiler control line|see{preprocessing directive}}% -\indextext{control line|see{preprocessing directive}}% -\indextext{directive, preprocessing|see{preprocessing directive}} +\indextext{token|(}% +\begin{bnf} +\nontermdef{token}\br + identifier\br + keyword\br + literal\br + operator-or-punctuator +\end{bnf} -\gramSec[gram.cpp]{Preprocessing directives} +\pnum +\indextext{\idxgram{token}}% +There are five kinds of tokens: identifiers, keywords, literals,% +\begin{footnote} +Literals include strings and character and numeric literals. +\end{footnote} +operators, and other separators. +\indextext{whitespace}% +Blanks, horizontal and vertical tabs, newlines, formfeeds, and comments +(collectively, ``whitespace''), are ignored except +as they serve to separate tokens. +\begin{note} +Whitespace can separate otherwise adjacent identifiers, keywords, numeric +literals, and alternative tokens containing alphabetic characters. +\end{note} +\indextext{token|)} -\rSec2[cpp.pre]{Preamble} +\rSec2[lex.key]{Keywords} \begin{bnf} -\nontermdef{preprocessing-file}\br - \opt{group}\br - module-file +\nontermdef{keyword}\br + \textnormal{any identifier listed in \tref{lex.key}}\br + \grammarterm{import-keyword}\br + \grammarterm{module-keyword}\br + \grammarterm{export-keyword} \end{bnf} -\begin{bnf} -\nontermdef{module-file}\br - \opt{pp-global-module-fragment} pp-module \opt{group} \opt{pp-private-module-fragment} -\end{bnf} +\pnum +\indextext{keyword|(}% +The identifiers shown in \tref{lex.key} are reserved for use +as keywords (that is, they are unconditionally treated as keywords in +phase 7) except in an \grammarterm{attribute-token}\iref{dcl.attr.grammar}. +\begin{note} +The \keyword{register} keyword is unused but +is reserved for future use. +\end{note} -\begin{bnf} -\nontermdef{pp-global-module-fragment}\br - \keyword{module} \terminal{;} new-line \opt{group} -\end{bnf} +\begin{multicolfloattable}{Keywords}{lex.key} +{lllll} +\keyword{alignas} \\ +\keyword{alignof} \\ +\keyword{asm} \\ +\keyword{auto} \\ +\keyword{bool} \\ +\keyword{break} \\ +\keyword{case} \\ +\keyword{catch} \\ +\keyword{char} \\ +\keyword{char8_t} \\ +\keyword{char16_t} \\ +\keyword{char32_t} \\ +\keyword{class} \\ +\keyword{concept} \\ +\keyword{const} \\ +\keyword{consteval} \\ +\keyword{constexpr} \\ +\columnbreak +\keyword{constinit} \\ +\keyword{const_cast} \\ +\keyword{continue} \\ +\keyword{co_await} \\ +\keyword{co_return} \\ +\keyword{co_yield} \\ +\keyword{decltype} \\ +\keyword{default} \\ +\keyword{delete} \\ +\keyword{do} \\ +\keyword{double} \\ +\keyword{dynamic_cast} \\ +\keyword{else} \\ +\keyword{enum} \\ +\keyword{explicit} \\ +\keyword{export} \\ +\keyword{extern} \\ +\columnbreak +\keyword{false} \\ +\keyword{float} \\ +\keyword{for} \\ +\keyword{friend} \\ +\keyword{goto} \\ +\keyword{if} \\ +\keyword{inline} \\ +\keyword{int} \\ +\keyword{long} \\ +\keyword{mutable} \\ +\keyword{namespace} \\ +\keyword{new} \\ +\keyword{noexcept} \\ +\keyword{nullptr} \\ +\keyword{operator} \\ +\keyword{private} \\ +\keyword{protected} \\ +\columnbreak +\keyword{public} \\ +\keyword{register} \\ +\keyword{reinterpret_cast} \\ +\keyword{requires} \\ +\keyword{return} \\ +\keyword{short} \\ +\keyword{signed} \\ +\keyword{sizeof} \\ +\keyword{static} \\ +\keyword{static_assert} \\ +\keyword{static_cast} \\ +\keyword{struct} \\ +\keyword{switch} \\ +\keyword{template} \\ +\keyword{this} \\ +\keyword{thread_local} \\ +\keyword{throw} \\ +\columnbreak +\keyword{true} \\ +\keyword{try} \\ +\keyword{typedef} \\ +\keyword{typeid} \\ +\keyword{typename} \\ +\keyword{union} \\ +\keyword{unsigned} \\ +\keyword{using} \\ +\keyword{virtual} \\ +\keyword{void} \\ +\keyword{volatile} \\ +\keyword{wchar_t} \\ +\keyword{while} \\ +\end{multicolfloattable} -\begin{bnf} -\nontermdef{pp-private-module-fragment}\br - \keyword{module} \terminal{:} \keyword{private} \terminal{;} new-line \opt{group} -\end{bnf} +\pnum +\indextext{\idxcode{import}}% +\indextext{\idxcode{final}}% +\indextext{\idxcode{module}}% +\indextext{\idxcode{override}}% +The identifiers in \tref{lex.name.special} have a special meaning when +appearing in a certain context. When referred to in the grammar, these identifiers +are used explicitly rather than using the \grammarterm{identifier} grammar production. +Unless otherwise specified, any ambiguity as to whether a given +\grammarterm{identifier} has a special meaning is resolved to interpret the +token as a regular \grammarterm{identifier}. -\begin{bnf} -\nontermdef{group}\br - group-part\br - group group-part -\end{bnf} +\begin{multicolfloattable}{Identifiers with special meaning}{lex.name.special} +{llll} +\keyword{final} \\ +\columnbreak +\keyword{import} \\ +\columnbreak +\keyword{module} \\ +\columnbreak +\keyword{override} \\ +\end{multicolfloattable} + +\pnum +\indextext{unit!translation}% +A translation unit shall not \tcode{\#define} or \tcode{\#undef} +names lexically identical +to keywords, +to the identifiers listed in \tref{lex.name.special}, or +to the \grammarterm{attribute-token}{s} described in~\ref{dcl.attr}, +except that the names \tcode{likely} and \tcode{unlikely} may be +defined as function-like macros~\iref{cpp.replace}. + +\pnum +Furthermore, the alternative representations shown in +\tref{lex.key.digraph} for certain operators and +punctuators\iref{lex.operators} are reserved and shall not be used +otherwise. + +\begin{floattable}{Alternative representations}{lex.key.digraph} +{llllll} +\topline +\keyword{and} & \keyword{and_eq} & \keyword{bitand} & \keyword{bitor} & \keyword{compl} & \keyword{not} \\ +\keyword{not_eq} & \keyword{or} & \keyword{or_eq} & \keyword{xor} & \keyword{xor_eq} & \\ +\end{floattable}% +\indextext{keyword|)}% + +\rSec2[lex.literal]{Literals}% +\indextext{literal|(} + +\rSec3[lex.literal.kinds]{Kinds of literals} + +\pnum +\indextext{constant}% +\indextext{literal!constant}% +There are several kinds of literals. +\begin{footnote} +The term ``literal'' generally designates, in this +document, those tokens that are called ``constants'' in C. +\end{footnote} \begin{bnf} -\nontermdef{group-part}\br - control-line\br - if-section\br - text-line\br - \terminal{\#} conditionally-supported-directive +\nontermdef{literal}\br + integer-literal\br + character-literal\br + floating-point-literal\br + string-literal\br + boolean-literal\br + pointer-literal\br + user-defined-literal \end{bnf} +\begin{note} +When appearing as an \grammarterm{expression}, +a literal has a type and a value category\iref{expr.prim.literal}. +\end{note} -\begin{bnf}\obeyspaces -\nontermdef{control-line}\br - \terminal{\# include} pp-tokens new-line\br - pp-import\br - \terminal{\# define } identifier replacement-list new-line\br - \terminal{\# define } identifier lparen \opt{identifier-list} \terminal{)} replacement-list new-line\br - \terminal{\# define } identifier lparen \terminal{... )} replacement-list new-line\br - \terminal{\# define } identifier lparen identifier-list \terminal{, ... )} replacement-list new-line\br - \terminal{\# undef } identifier new-line\br - \terminal{\# line } pp-tokens new-line\br - \terminal{\# error } \opt{pp-tokens} new-line\br - \terminal{\# warning} \opt{pp-tokens} new-line\br - \terminal{\# pragma } \opt{pp-tokens} new-line\br - \terminal{\# }new-line -\end{bnf} +\rSec3[lex.icon]{Integer literals} +\indextext{literal!integer}% \begin{bnf} -\nontermdef{if-section}\br - if-group \opt{elif-groups} \opt{else-group} endif-line +\nontermdef{integer-literal}\br + binary-literal \opt{integer-suffix}\br + octal-literal \opt{integer-suffix}\br + decimal-literal \opt{integer-suffix}\br + hexadecimal-literal \opt{integer-suffix} \end{bnf} -\begin{bnf}\obeyspaces -\nontermdef{if-group}\br - \terminal{\# if } constant-expression new-line \opt{group}\br - \terminal{\# ifdef } identifier new-line \opt{group}\br - \terminal{\# ifndef } identifier new-line \opt{group} +\begin{bnf} +\nontermdef{binary-literal}\br + \terminal{0b} binary-digit\br + \terminal{0B} binary-digit\br + binary-literal \opt{\terminal{'}} binary-digit \end{bnf} \begin{bnf} -\nontermdef{elif-groups}\br - elif-group\br - elif-groups elif-group +\nontermdef{octal-literal}\br + \terminal{0}\br + octal-literal \opt{\terminal{'}} octal-digit \end{bnf} -\begin{bnf}\obeyspaces -\nontermdef{elif-group}\br - \terminal{\# elif } constant-expression new-line \opt{group}\br - \terminal{\# elifdef } identifier new-line \opt{group}\br - \terminal{\# elifndef} identifier new-line \opt{group} +\begin{bnf} +\nontermdef{decimal-literal}\br + nonzero-digit\br + decimal-literal \opt{\terminal{'}} digit \end{bnf} -\begin{bnf}\obeyspaces -\nontermdef{else-group}\br - \terminal{\# else } new-line \opt{group} +\begin{bnf} +\nontermdef{hexadecimal-literal}\br + hexadecimal-prefix hexadecimal-digit-sequence \end{bnf} -\begin{bnf}\obeyspaces -\nontermdef{endif-line}\br - \terminal{\# endif } new-line +\begin{bnf} +\nontermdef{binary-digit} \textnormal{one of}\br + \terminal{0 1} \end{bnf} \begin{bnf} -\nontermdef{text-line}\br - \opt{pp-tokens} new-line +\nontermdef{octal-digit} \textnormal{one of}\br + \terminal{0 1 2 3 4 5 6 7} \end{bnf} \begin{bnf} -\nontermdef{conditionally-supported-directive}\br - pp-tokens new-line +\nontermdef{nonzero-digit} \textnormal{one of}\br + \terminal{1 2 3 4 5 6 7 8 9} \end{bnf} \begin{bnf} -\nontermdef{lparen}\br - \descr{a \terminal{(} character not immediately preceded by whitespace} +\nontermdef{hexadecimal-prefix} \textnormal{one of}\br + \terminal{0x 0X} \end{bnf} \begin{bnf} -\nontermdef{identifier-list}\br - identifier\br - identifier-list \terminal{,} identifier +\nontermdef{hexadecimal-digit-sequence}\br + hexadecimal-digit\br + hexadecimal-digit-sequence \opt{\terminal{'}} hexadecimal-digit \end{bnf} \begin{bnf} -\nontermdef{replacement-list}\br - \opt{pp-tokens} +\nontermdef{hexadecimal-digit} \textnormal{one of}\br + \terminal{0 1 2 3 4 5 6 7 8 9}\br + \terminal{a b c d e f}\br + \terminal{A B C D E F} \end{bnf} \begin{bnf} -\nontermdef{pp-tokens}\br - preprocessing-token\br - pp-tokens preprocessing-token +\nontermdef{integer-suffix}\br + unsigned-suffix \opt{long-suffix} \br + unsigned-suffix \opt{long-long-suffix} \br + unsigned-suffix \opt{size-suffix} \br + long-suffix \opt{unsigned-suffix} \br + long-long-suffix \opt{unsigned-suffix} \br + size-suffix \opt{unsigned-suffix} \end{bnf} \begin{bnf} -\nontermdef{new-line}\br - \descr{the new-line character} +\nontermdef{unsigned-suffix} \textnormal{one of}\br + \terminal{u U} \end{bnf} -\pnum -A \defn{preprocessing directive} consists of a sequence of preprocessing tokens -that satisfies the following constraints: -At the start of translation phase 4, -the first token in the sequence, -referred to as a \defnadj{directive-introducing}{token}, -begins with the first character in the source file -(optionally after whitespace containing no new-line characters) or -follows whitespace containing at least one new-line character, -and is - -\begin{itemize} -\item -a \tcode{\#} preprocessing token, or - -\item -an \keyword{import} preprocessing token -immediately followed on the same logical source line by a -\grammarterm{header-name}, -\tcode{<}, -\grammarterm{identifier}, -\grammarterm{string-literal}, or -\tcode{:} -preprocessing token, or +\begin{bnf} +\nontermdef{long-suffix} \textnormal{one of}\br + \terminal{l L} +\end{bnf} -\item -a \keyword{module} preprocessing token -immediately followed on the same logical source line by an -\grammarterm{identifier}, -\tcode{:}, or -\tcode{;} -preprocessing token, or +\begin{bnf} +\nontermdef{long-long-suffix} \textnormal{one of}\br + \terminal{ll LL} +\end{bnf} -\item -an \keyword{export} preprocessing token -immediately followed on the same logical source line by -one of the two preceding forms. -\end{itemize} +\begin{bnf} +\nontermdef{size-suffix} \textnormal{one of}\br + \terminal{z Z} +\end{bnf} -The last token in the sequence is the first token within the sequence that -is immediately followed by whitespace containing a new-line character. -\begin{footnote} -Thus, -preprocessing directives are commonly called ``lines''. -These ``lines'' have no other syntactic significance, -as all whitespace is equivalent except in certain situations -during preprocessing (see the -\tcode{\#} -character string literal creation operator in~\ref{cpp.stringize}, for example). -\end{footnote} +\pnum +\indextext{literal!\idxcode{unsigned}}% +\indextext{literal!\idxcode{long}}% +\indextext{literal!base of integer}% +In an \grammarterm{integer-literal}, +the sequence of +\grammarterm{binary-digit}s, +\grammarterm{octal-digit}s, +\grammarterm{digit}s, or +\grammarterm{hexadecimal-digit}s +is interpreted as a base $N$ integer as shown in table \tref{lex.icon.base}; +the lexically first digit of the sequence of digits is the most significant. \begin{note} -A new-line character ends the preprocessing directive even if it occurs -within what would otherwise be an invocation of a function-like macro. +The prefix and any optional separating single quotes are ignored +when determining the value. \end{note} -\begin{example} -\begin{codeblock} -# // preprocessing directive -module ; // preprocessing directive -export module leftpad; // preprocessing directive -import ; // preprocessing directive -export import "squee"; // preprocessing directive -import rightpad; // preprocessing directive -import :part; // preprocessing directive - -module // not a preprocessing directive -; // not a preprocessing directive - -export // not a preprocessing directive -import // not a preprocessing directive -foo; // not a preprocessing directive - -export // not a preprocessing directive -import foo; // preprocessing directive (ill-formed at phase 7) - -import :: // not a preprocessing directive -import -> // not a preprocessing directive -\end{codeblock} -\end{example} - -\pnum -A sequence of preprocessing tokens is only a \grammarterm{text-line} -if it does not begin with a directive-introducing token. -A sequence of preprocessing tokens is only a \grammarterm{conditionally-supported-directive} -if it does not begin with any of the directive names -appearing after a \tcode{\#} in the syntax. -A \grammarterm{conditionally-supported-directive} is -conditionally-supported with -\impldef{additional supported forms of preprocessing directive} -semantics. +\begin{simpletypetable} +{Base of \grammarterm{integer-literal}{s}} +{lex.icon.base} +{lr} +\topline +\lhdr{Kind of \grammarterm{integer-literal}} & \rhdr{base $N$} \\ \capsep +\grammarterm{binary-literal} & 2 \\ +\grammarterm{octal-literal} & 8 \\ +\grammarterm{decimal-literal} & 10 \\ +\grammarterm{hexadecimal-literal} & 16 \\ +\end{simpletypetable} \pnum -At the start of phase 4 of translation, -the \grammarterm{group} of a \grammarterm{pp-global-module-fragment} shall -contain neither a \grammarterm{text-line} nor a \grammarterm{pp-import}. +The \grammarterm{hexadecimal-digit}s +\tcode{a} through \tcode{f} and \tcode{A} through \tcode{F} +have decimal values ten through fifteen. +\begin{example} +The number twelve can be written \tcode{12}, \tcode{014}, +\tcode{0XC}, or \tcode{0b1100}. The \grammarterm{integer-literal}s \tcode{1048576}, +\tcode{1'048'576}, \tcode{0X100000}, \tcode{0x10'0000}, and +\tcode{0'004'000'000} all have the same value. +\end{example} \pnum -When in a group that is skipped\iref{cpp.cond}, the directive -syntax is relaxed to allow any sequence of preprocessing tokens to occur between -the directive name and the following new-line character. +\indextext{literal!\idxcode{long}}% +\indextext{literal!\idxcode{unsigned}}% +\indextext{literal!integer}% +\indextext{literal!type of integer}% +\indextext{suffix!\idxcode{L}}% +\indextext{suffix!\idxcode{U}}% +\indextext{suffix!\idxcode{l}}% +\indextext{suffix!\idxcode{u}}% +The type of an \grammarterm{integer-literal} is +the first type in the list in \tref{lex.icon.type} +corresponding to its optional \grammarterm{integer-suffix} +in which its value can be represented. -\pnum -The only whitespace characters that shall appear -between preprocessing tokens -within a preprocessing directive -(from just after the directive-introducing token -through just before the terminating new-line character) -are space and horizontal-tab -(including spaces that have replaced comments -or possibly other whitespace characters -in translation phase 3). +\begin{floattable}{Types of \grammarterm{integer-literal}s}{lex.icon.type}{l|l|l} +\topline +\lhdr{\grammarterm{integer-suffix}} & \chdr{\grammarterm{decimal-literal}} & \rhdr{\grammarterm{integer-literal} other than \grammarterm{decimal-literal}} \\ \capsep +none & + \tcode{int} & + \tcode{int}\\ + & + \tcode{long int} & + \tcode{unsigned int}\\ + & + \tcode{long long int} & + \tcode{long int}\\ + & + & + \tcode{unsigned long int}\\ + & + & + \tcode{long long int}\\ + & + & + \tcode{unsigned long long int}\\\hline +\tcode{u} or \tcode{U} & + \tcode{unsigned int} & + \tcode{unsigned int}\\ + & + \tcode{unsigned long int} & + \tcode{unsigned long int}\\ + & + \tcode{unsigned long long int} & + \tcode{unsigned long long int}\\\hline +\tcode{l} or \tcode{L} & + \tcode{long int} & + \tcode{long int}\\ + & + \tcode{long long int} & + \tcode{unsigned long int}\\ + & + & + \tcode{long long int}\\ + & + & + \tcode{unsigned long long int}\\\hline +Both \tcode{u} or \tcode{U} & + \tcode{unsigned long int} & + \tcode{unsigned long int}\\ +and \tcode{l} or \tcode{L} & + \tcode{unsigned long long int} & + \tcode{unsigned long long int}\\\hline +\tcode{ll} or \tcode{LL} & + \tcode{long long int} & + \tcode{long long int}\\ + & + & + \tcode{unsigned long long int}\\\hline +Both \tcode{u} or \tcode{U} & + \tcode{unsigned long long int} & + \tcode{unsigned long long int}\\ +and \tcode{ll} or \tcode{LL} & + & + \\\hline +\tcode{z} or \tcode{Z} & + the signed integer type corresponding & + the signed integer type \\ + & + \qquad to \tcode{std::size_t}\iref{support.types.layout} & + \qquad corresponding to \tcode{std::size_t} \\ + & + & + \tcode{std::size_t}\\\hline +Both \tcode{u} or \tcode{U} & + \tcode{std::size_t} & + \tcode{std::size_t} \\ +and \tcode{z} or \tcode{Z} & + & + \\ +\end{floattable} \pnum -The implementation can -process and skip sections of source files conditionally, -include other source files, -import macros from header units, -and replace macros. -These capabilities are called -\defn{preprocessing}, -because conceptually they occur -before translation of the resulting translation unit. +Except for \grammarterm{integer-literal}{s} containing +a \grammarterm{size-suffix}, +if the value of an \grammarterm{integer-literal} +cannot be represented by any type in its list and +an extended integer type\iref{basic.fundamental} can represent its value, +it may have that extended integer type. +If all of the types in the list for the \grammarterm{integer-literal} +are signed, +the extended integer type is signed. +If all of the types in the list for the \grammarterm{integer-literal} +are unsigned, +the extended integer type is unsigned. +If the list contains both signed and unsigned types, +the extended integer type may be signed or unsigned. +If an \grammarterm{integer-literal} +cannot be represented by any of the allowed types, +the program is ill-formed. +\begin{note} +An \grammarterm{integer-literal} with a \tcode{z} or \tcode{Z} suffix +is ill-formed if it cannot be represented by \tcode{std::size_t}. +\end{note} -\pnum -The preprocessing tokens within a preprocessing directive -are not subject to macro expansion unless otherwise stated. +\rSec3[lex.fcon]{Floating-point literals} -\begin{example} -In: -\begin{codeblock} -#define EMPTY -EMPTY # include -\end{codeblock} -the sequence of preprocessing tokens on the second line is \textit{not} -a preprocessing directive, because it does not begin with a \tcode{\#} at the start of -translation phase 4, even though it will do so after the macro \tcode{EMPTY} -has been replaced. -\end{example} +\indextext{literal!floating-point}% +\begin{bnf} +\nontermdef{floating-point-literal}\br + decimal-floating-point-literal\br + hexadecimal-floating-point-literal +\end{bnf} -\rSec2[cpp.module]{Module directive} -\indextext{preprocessing directive!module}% +\begin{bnf} +\nontermdef{decimal-floating-point-literal}\br + fractional-constant \opt{exponent-part} \opt{floating-point-suffix}\br + digit-sequence exponent-part \opt{floating-point-suffix} +\end{bnf} \begin{bnf} -\nontermdef{pp-module}\br - \opt{\keyword{export}} \keyword{module} \opt{pp-tokens} \terminal{;} new-line +\nontermdef{hexadecimal-floating-point-literal}\br + hexadecimal-prefix hexadecimal-fractional-constant binary-exponent-part \opt{floating-point-suffix}\br + hexadecimal-prefix hexadecimal-digit-sequence binary-exponent-part \opt{floating-point-suffix} \end{bnf} -\pnum -A \grammarterm{pp-module} shall not -appear in a context where \tcode{module} -or (if it is the first token of the \grammarterm{pp-module}) \tcode{export} -is an identifier defined as an object-like macro. +\begin{bnf} +\nontermdef{fractional-constant}\br + \opt{digit-sequence} \terminal{.} digit-sequence\br + digit-sequence \terminal{.} +\end{bnf} -\pnum -The \grammarterm{pp-tokens}, if any, of a \grammarterm{pp-module} -shall be of the form: -\begin{ncsimplebnf} -pp-module-name \opt{pp-module-partition} \opt{pp-tokens} -\end{ncsimplebnf} -where the \grammarterm{pp-tokens} (if any) shall not begin with -a \tcode{(} preprocessing token and -the grammar non-terminals are defined as: -\begin{ncbnf} -\nontermdef{pp-module-name}\br - \opt{pp-module-name-qualifier} identifier -\end{ncbnf} -\begin{ncbnf} -\nontermdef{pp-module-partition}\br - \terminal{:} \opt{pp-module-name-qualifier} identifier -\end{ncbnf} -\begin{ncbnf} -\nontermdef{pp-module-name-qualifier}\br - identifier \terminal{.}\br - pp-module-name-qualifier identifier \terminal{.} -\end{ncbnf} -No \grammarterm{identifier} in -the \grammarterm{pp-module-name} or \grammarterm{pp-module-partition} -shall currently be defined as an object-like macro. +\begin{bnf} +\nontermdef{hexadecimal-fractional-constant}\br + \opt{hexadecimal-digit-sequence} \terminal{.} hexadecimal-digit-sequence\br + hexadecimal-digit-sequence \terminal{.} +\end{bnf} -\pnum -Any preprocessing tokens after the \tcode{module} preprocessing token -in the \tcode{module} directive are processed just as in normal text. -\begin{note} -Each identifier currently defined as a macro name -is replaced by its replacement list of preprocessing tokens. -\end{note} +\begin{bnf} +\nontermdef{exponent-part}\br + \terminal{e} \opt{sign} digit-sequence\br + \terminal{E} \opt{sign} digit-sequence +\end{bnf} -\pnum -The \tcode{module} and \tcode{export} (if it exists) preprocessing tokens -are replaced by the \grammarterm{module-keyword} and -\grammarterm{export-keyword} preprocessing tokens respectively. -\begin{note} -This makes the line no longer a directive -so it is not removed at the end of phase 4. -\end{note} +\begin{bnf} +\nontermdef{binary-exponent-part}\br + \terminal{p} \opt{sign} digit-sequence\br + \terminal{P} \opt{sign} digit-sequence +\end{bnf} -\rSec2[cpp.import]{Header unit importation} -\indextext{header unit!preprocessing}% -\indextext{preprocessing directive!import}% -\indextext{macro!import|(}% +\begin{bnf} +\nontermdef{sign} \textnormal{one of}\br + \terminal{+ -} +\end{bnf} \begin{bnf} -\nontermdef{pp-import}\br - \opt{\keyword{export}} \keyword{import} header-name \opt{pp-tokens} \terminal{;} new-line\br - \opt{\keyword{export}} \keyword{import} header-name-tokens \opt{pp-tokens} \terminal{;} new-line\br - \opt{\keyword{export}} \keyword{import} pp-tokens \terminal{;} new-line +\nontermdef{digit-sequence}\br + digit\br + digit-sequence \opt{\terminal{'}} digit \end{bnf} -\pnum -A \grammarterm{pp-import} shall not -appear in a context where \tcode{import} -or (if it is the first token of the \grammarterm{pp-import}) \tcode{export} -is an identifier defined as an object-like macro. +\begin{bnf} +\nontermdef{floating-point-suffix} \textnormal{one of}\br + \terminal{f l f16 f32 f64 f128 bf16 F L F16 F32 F64 F128 BF16} +\end{bnf} \pnum -The preprocessing tokens after the \tcode{import} preprocessing token -in the \tcode{import} \grammarterm{control-line} -are processed just as in normal text -(i.e., each identifier currently defined as a macro name -is replaced by its replacement list of preprocessing tokens). +\indextext{literal!type of floating-point}% +\indextext{literal!\idxcode{float}}% +\indextext{suffix!\idxcode{F}}% +\indextext{suffix!\idxcode{f}}% +\indextext{suffix!\idxcode{L}}% +\indextext{suffix!\idxcode{l}}% +\indextext{literal!\idxcode{long double}}% +The type of +a \grammarterm{floating-point-literal}\iref{basic.fundamental,basic.extended.fp} +is determined by +its \grammarterm{floating-point-suffix} as specified in \tref{lex.fcon.type}. \begin{note} -An \tcode{import} directive -matching the first two forms of a \grammarterm{pp-import} -instructs the preprocessor to import macros -from the header unit\iref{module.import} -denoted by the \grammarterm{header-name}, -as described below. +The floating-point suffixes +\tcode{f16}, \tcode{f32}, \tcode{f64}, \tcode{f128}, \tcode{bf16}, +\tcode{F16}, \tcode{F32}, \tcode{F64}, \tcode{F128}, and \tcode{BF16} +are conditionally-supported. See \ref{basic.extended.fp}. \end{note} -\indextext{point of!macro import|see{macro, point of import}}% -The \defnx{point of macro import}{macro!point of import} for the -first two forms of \grammarterm{pp-import} is -immediately after the \grammarterm{new-line} terminating -the \grammarterm{pp-import}. -The last form of \grammarterm{pp-import} is only considered -if the first two forms did not match, and -does not have a point of macro import. - -\pnum -If a \grammarterm{pp-import} is produced by source file inclusion -(including by the rewrite produced -when a \tcode{\#include} directive names an importable header) -while processing the \grammarterm{group} of a \grammarterm{module-file}, -the program is ill-formed. - -\pnum -In all three forms of \grammarterm{pp-import}, -the \tcode{import} and \tcode{export} (if it exists) preprocessing tokens -are replaced by the \grammarterm{import-keyword} and -\grammarterm{export-keyword} preprocessing tokens respectively. -\begin{note} -This makes the line no longer a directive -so it is not removed at the end of phase 4. -\end{note} -Additionally, in the second form of \grammarterm{pp-import}, -a \grammarterm{header-name} token is formed as if -the \grammarterm{header-name-tokens} -were the \grammarterm{pp-tokens} of a \tcode{\#include} directive. -The \grammarterm{header-name-tokens} are replaced by -the \grammarterm{header-name} token. -\begin{note} -This ensures that imports are treated consistently by -the preprocessor and later phases of translation. -\end{note} - -\pnum -Each \tcode{\#define} directive encountered when preprocessing -each translation unit in a program results in a distinct -\defnx{macro definition}{macro!definition}. -\begin{note} -A predefined macro name\iref{cpp.predefined} -is not introduced by a \tcode{\#define} directive. -Implementations providing mechanisms to predefine additional macros -are encouraged to not treat them -as being introduced by a \tcode{\#define} directive. -\end{note} -Each macro definition has at most one point of definition in -each translation unit and at most one point of undefinition, as follows: -\begin{itemize} -\item -\indextext{point of!macro definition|see{macro, point of definition}}% -The \defnx{point of definition}{macro!point of definition} -of a macro definition within a translation unit $T$ is -\begin{itemize} -\item -if the \tcode{\#define} directive of the macro definition occurs within $T$, -the point at which that directive occurs, or otherwise, -\item -if the macro name is not lexically identical to a keyword\iref{lex.key} -or to the \grammarterm{identifier}{s} \tcode{module} or \tcode{import}, -the first point of macro import in $T$ of a header unit -containing a point of definition for the macro definition, if any. -\end{itemize} -In the latter case, the macro is said -to be \defnx{imported}{macro!import} from the header unit. - -\item -\indextext{point of!macro undefinition|see{macro, point of undefinition}}% -The \defnx{point of undefinition}{macro!point of undefinition} -of a macro definition within a translation unit -is the first point at which a \tcode{\#undef} directive naming the macro occurs -after its point of definition, or the first point -of macro import of a header unit containing a point of undefinition for the -macro definition, whichever (if any) occurs first. -\end{itemize} - -\pnum -\indextext{active macro directive|see{macro, active}}% -A macro directive is \defnx{active}{macro!active} at a source location -if it has a point of definition in that translation unit preceding the location, -and does not have a point of undefinition in that translation unit preceding -the location. +\begin{simpletypetable} +{Types of \grammarterm{floating-point-literal}{s}} +{lex.fcon.type} +{ll} +\topline +\lhdr{\grammarterm{floating-point-suffix}} & \rhdr{type} \\ \capsep +none & \keyword{double} \\ +\tcode{f} or \tcode{F} & \keyword {float} \\ +\tcode{l} or \tcode{L} & \keyword{long} \keyword{double} \\ +\tcode{f16} or \tcode{F16} & \tcode{std::float16_t} \\ +\tcode{f32} or \tcode{F32} & \tcode{std::float32_t} \\ +\tcode{f64} or \tcode{F64} & \tcode{std::float64_t} \\ +\tcode{f128} or \tcode{F128} & \tcode{std::float128_t} \\ +\tcode{bf16} or \tcode{BF16} & \tcode{std::bfloat16_t} \\ +\end{simpletypetable} \pnum -If a macro would be replaced or redefined, and multiple macro definitions -are active for that macro name, the active macro definitions shall all be -valid redefinitions of the same macro\iref{cpp.replace}. +\indextext{literal!floating-point}% +The \defn{significand} of a \grammarterm{floating-point-literal} +is the \grammarterm{fractional-constant} or \grammarterm{digit-sequence} +of a \grammarterm{decimal-floating-point-literal} +or the \grammarterm{hexadecimal-fractional-constant} +or \grammarterm{hexadecimal-digit-sequence} +of a \grammarterm{hexadecimal-floating-point-literal}. +In the significand, +the sequence of \grammarterm{digit}s or \grammarterm{hexadecimal-digit}s +and optional period are interpreted as a base $N$ real number $s$, +where $N$ is 10 for a \grammarterm{decimal-floating-point-literal} and +16 for a \grammarterm{hexadecimal-floating-point-literal}. \begin{note} -The relative order of \grammarterm{pp-import}{s} has no bearing on whether a -particular macro definition is active. +Any optional separating single quotes are ignored when determining the value. \end{note} - -\pnum -\begin{example} -\begin{codeblocktu}{Importable header \tcode{"a.h"}} -#define X 123 // \#1 -#define Y 45 // \#2 -#define Z a // \#3 -#undef X // point of undefinition of \#1 in \tcode{"a.h"} -\end{codeblocktu} - -\begin{codeblocktu}{Importable header \tcode{"b.h"}} -import "a.h"; // point of definition of \#1, \#2, and \#3, point of undefinition of \#1 in \tcode{"b.h"} -#define X 456 // OK, \#1 is not active -#define Y 6 // error: \#2 is active -\end{codeblocktu} - -\begin{codeblocktu}{Importable header \tcode{"c.h"}} -#define Y 45 // \#4 -#define Z c // \#5 -\end{codeblocktu} - -\begin{codeblocktu}{Importable header \tcode{"d.h"}} -import "c.h"; // point of definition of \#4 and \#5 in \tcode{"d.h"} -\end{codeblocktu} - -\begin{codeblocktu}{Importable header \tcode{"e.h"}} -import "a.h"; // point of definition of \#1, \#2, and \#3, point of undefinition of \#1 in \tcode{"e.h"} -import "d.h"; // point of definition of \#4 and \#5 in \tcode{"e.h"} -int a = Y; // OK, active macro definitions \#2 and \#4 are valid redefinitions -int c = Z; // error: active macro definitions \#3 and \#5 are not valid redefinitions of \tcode{Z} -\end{codeblocktu} - -\begin{codeblocktu}{Module unit \tcode{f}} -export module f; -export import "a.h"; - -int a = Y; // OK -\end{codeblocktu} - -\begin{codeblocktu}{Translation unit \tcode{\#1}} -import f; -int x = Y; // error: \tcode{Y} is neither a defined macro nor a declared name -\end{codeblocktu} -\end{example} -\indextext{macro!import|)} - -\rSec2[cpp.null]{Null directive}% -\indextext{preprocessing directive!null} - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\#} new-line -\end{ncsimplebnf} -has no effect. - -\rSec2[cpp.error]{Diagnostic directives}% -\indextext{preprocessing directive!error}% -\indextext{preprocessing directive!diagnostic}% -\indextext{preprocessing directive!warning}% -\indextext{\idxcode{\#error}|see{preprocessing directive, error}} - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# error} \opt{pp-tokens} new-line -\end{ncsimplebnf} -renders the program ill-formed. -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# warning} \opt{pp-tokens} new-line -\end{ncsimplebnf} -requires the implementation to produce at least one diagnostic message -for the preprocessing translation unit\iref{intro.compliance.general}. -\recommended -Any diagnostic message caused by either of these directives -should include the specified sequence of preprocessing tokens. - -\rSec2[cpp.line]{Line control}% -\indextext{preprocessing directive!line control}% -\indextext{\idxcode{\#line}|see{preprocessing directive, line control}} - -\pnum -The \grammarterm{string-literal} of a -\tcode{\#line} -directive, if present, -shall be a character string literal. - -\pnum -The -\defn{line number} -of the current source line is one greater than -the number of new-line characters read or introduced -in translation phase 1\iref{lex.phases} -while processing the source file to the current token. - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# line} digit-sequence new-line -\end{ncsimplebnf} -causes the implementation to behave as if -the following sequence of source lines begins with a -source line that has a line number as specified -by the digit sequence (interpreted as a decimal integer). -If the digit sequence specifies zero -or a number greater than 2147483647, -the behavior is undefined. - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# line} digit-sequence \terminal{"} \opt{s-char-sequence} \terminal{"} new-line -\end{ncsimplebnf} -sets the presumed line number similarly and changes the -presumed name of the source file to be the contents -of the character string literal. - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# line} pp-tokens new-line -\end{ncsimplebnf} -(that does not match one of the two previous forms) -is permitted. -The preprocessing tokens after -\tcode{line} -on the directive are processed just as in normal text -(each identifier currently defined as a macro name is replaced by its -replacement list of preprocessing tokens). -If the directive resulting after all replacements does not match -one of the two previous forms, the behavior is undefined; -otherwise, the result is processed as appropriate. - -\rSec2[cpp.pragma]{Pragma directive}% -\indextext{preprocessing directive!pragma}% -\indextext{\idxcode{\#pragma}|see{preprocessing directive, pragma}} - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# pragma} \opt{pp-tokens} new-line -\end{ncsimplebnf} -causes the implementation to behave -in an \impldef{\tcode{\#pragma}} manner. -The behavior may cause translation to fail or cause the translator or -the resulting program to behave in a non-conforming manner. -Any pragma that is not recognized by the implementation is ignored. - -\rSec2[cpp.pragma.op]{Pragma operator}% -\indextext{macro!pragma operator}% -\indextext{operator!pragma|see{macro, pragma operator}} - -\pnum -A unary operator expression of the form: -\begin{ncbnf} -\terminal{_Pragma} \terminal{(} string-literal \terminal{)} -\end{ncbnf} -is processed as follows: The \grammarterm{string-literal} is \defnx{destringized}{destringization} -by deleting the \tcode{L} prefix, if present, deleting the leading and trailing -double-quotes, replacing each escape sequence \tcode{\textbackslash"} by a double-quote, and -replacing each escape sequence \tcode{\textbackslash\textbackslash} by a single -backslash. The resulting sequence of characters is processed through translation phase 3 -to produce preprocessing tokens that are executed as if they were the -\grammarterm{pp-tokens} in a pragma directive. The original four preprocessing -tokens in the unary operator expression are removed. - -\pnum -\begin{example} -\begin{codeblock} -#pragma listing on "..\listing.dir" -\end{codeblock} -can also be expressed as: -\begin{codeblock} -_Pragma ( "listing on \"..\\listing.dir\"" ) -\end{codeblock} -The latter form is processed in the same way whether it appears literally -as shown, or results from macro replacement, as in: -\begin{codeblock} -#define LISTING(x) PRAGMA(listing on #x) -#define PRAGMA(x) _Pragma(#x) - -LISTING( ..\listing.dir ) -\end{codeblock} -\end{example} -\indextext{preprocessing directive|)} - -\rSec2[cpp.replace]{Macro replacement}% - -\rSec3[cpp.replace.general]{General}% -\indextext{macro!replacement|(}% -\indextext{replacement!macro|see{macro, replacement}}% -\indextext{preprocessing directive!macro replacement|see{macro, replacement}} - -\pnum -\indextext{macro!replacement list}% -Two replacement lists are identical if and only if -the preprocessing tokens in both have -the same number, ordering, spelling, and whitespace separation, -where all whitespace separations are considered identical. - -\pnum -An identifier currently defined as an -\indextext{macro!object-like}% -object-like macro (see below) may be redefined by another -\tcode{\#define} -preprocessing directive provided that the second definition is an -object-like macro definition and the two replacement lists -are identical, otherwise the program is ill-formed. -Likewise, an identifier currently defined as a -\indextext{macro!function-like}% -function-like macro (see below) may be redefined by another -\tcode{\#define} -preprocessing directive provided that the second definition is a -function-like macro definition that has the same number and spelling -of parameters, -and the two replacement lists are identical, -otherwise the program is ill-formed. - -\pnum -\begin{example} -The following sequence is valid: -\begin{codeblock} -#define OBJ_LIKE (1-1) -#define OBJ_LIKE @\tcode{/* whitespace */ (1-1) /* other */}@ -#define FUNC_LIKE(a) ( a ) -#define FUNC_LIKE( a )( @\tcode{/* note the whitespace */ \textbackslash}@ - a @\tcode{/* other stuff on this line}@ - @\tcode{*/}@ ) -\end{codeblock} -But the following redefinitions are invalid: -\begin{codeblock} -#define OBJ_LIKE (0) // different token sequence -#define OBJ_LIKE (1 - 1) // different whitespace -#define FUNC_LIKE(b) ( a ) // different parameter usage -#define FUNC_LIKE(b) ( b ) // different parameter spelling -\end{codeblock} -\end{example} - -\pnum -\indextext{macro!replacement list}% -There shall be whitespace between the identifier and the replacement list -in the definition of an object-like macro. - -\pnum -If the \grammarterm{identifier-list} in the macro definition does not end with -an ellipsis, the number of arguments (including those arguments consisting -of no preprocessing tokens) -in an invocation of a function-like macro shall -equal the number of parameters in the macro definition. -Otherwise, there shall be at least as many arguments in the invocation as there are -parameters in the macro definition (excluding the \tcode{...}). There -shall exist a -\tcode{)} -preprocessing token that terminates the invocation. - -\pnum -\indextext{__va_args__@\mname{VA_ARGS}}% -\indextext{__va_opt__@\mname{VA_OPT}}% -The identifiers \mname{VA_ARGS} and \mname{VA_OPT} -shall occur only in the \grammarterm{replacement-list} -of a function-like macro that uses the ellipsis notation in the parameters. - -\pnum -A parameter identifier in a function-like macro -shall be uniquely declared within its scope. - -\pnum -The identifier immediately following the -\tcode{define} -is called the -\indextext{name!macro|see{macro, name}}% -\defnx{macro name}{macro!name}. -There is one name space for macro names. -Any whitespace characters preceding or following the -replacement list of preprocessing tokens are not considered -part of the replacement list for either form of macro. - -\pnum -If a -\indextext{\#\#0 operator@\tcode{\#} operator} -\tcode{\#} -preprocessing token, -followed by an identifier, -occurs lexically -at the point at which a preprocessing directive can begin, -the identifier is not subject to macro replacement. - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# define} identifier replacement-list new-line -\indextext{\idxcode{\#define}}% -\end{ncsimplebnf} -defines an -\defnadj{object-like}{macro} that -causes each subsequent instance of the macro name -\begin{footnote} -Since, by macro-replacement time, -all \grammarterm{character-literal}s and \grammarterm{string-literal}s are preprocessing tokens, -not sequences possibly containing identifier-like subsequences -(see \ref{lex.phases}, translation phases), -they are never scanned for macro names or parameters. -\end{footnote} -to be replaced by the replacement list of preprocessing tokens -that constitute the remainder of the directive. -\begin{footnote} -An alternative token\iref{lex.operators} is not an identifier, -even when its spelling consists entirely of letters and underscores. -Therefore it is not possible to define a macro -whose name is the same as that of an alternative token. -\end{footnote} -The replacement list is then rescanned for more macro names as -specified below. - -\pnum +If an \grammarterm{exponent-part} or \grammarterm{binary-exponent-part} +is present, +the exponent $e$ of the \grammarterm{floating-point-literal} +is the result of interpreting +the sequence of an optional \grammarterm{sign} and the \grammarterm{digit}s +as a base 10 integer. +Otherwise, the exponent $e$ is 0. +The scaled value of the literal is +$s \times 10^e$ for a \grammarterm{decimal-floating-point-literal} and +$s \times 2^e$ for a \grammarterm{hexadecimal-floating-point-literal}. \begin{example} -The simplest use of this facility is to define a ``manifest constant'', -as in -\begin{codeblock} -#define TABSIZE 100 -int table[TABSIZE]; -\end{codeblock} +The \grammarterm{floating-point-literal}{s} +\tcode{49.625} and \tcode{0xC.68p+2} have the same value. +The \grammarterm{floating-point-literal}{s} +\tcode{1.602'176'565e-19} and \tcode{1.602176565e-19} +have the same value. \end{example} \pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# define} identifier lparen \opt{identifier-list} \terminal{)} replacement-list new-line\br -\terminal{\# define} identifier lparen \terminal{...} \terminal{)} replacement-list new-line\br -\terminal{\# define} identifier lparen identifier-list \terminal{, ...} \terminal{)} replacement-list new-line -\end{ncsimplebnf} -defines a \defnadj{function-like}{macro} -with parameters, whose use is -similar syntactically to a function call. -The parameters -\indextext{parameter!macro}% -are specified by the optional list of identifiers. -Each subsequent instance of the function-like macro name followed by a -\tcode{(} -as the next preprocessing token -introduces the sequence of preprocessing tokens that is replaced -by the replacement list in the definition -(an invocation of the macro). -\indextext{invocation!macro}% -The replaced sequence of preprocessing tokens is terminated by the matching -\tcode{)} -preprocessing token, skipping intervening matched pairs of left and -right parenthesis preprocessing tokens. -Within the sequence of preprocessing tokens making up an invocation -of a function-like macro, -new-line is considered a normal whitespace character. - -\pnum -\indextext{macro!function-like!arguments}% -The sequence of preprocessing tokens -bounded by the outside-most matching parentheses -forms the list of arguments for the function-like macro. -The individual arguments within the list -are separated by comma preprocessing tokens, -but comma preprocessing tokens between matching -inner parentheses do not separate arguments. -If there are sequences of preprocessing tokens within the list of -arguments that would otherwise act as preprocessing directives, -\begin{footnote} -A \grammarterm{conditionally-supported-directive} is a preprocessing directive regardless of whether the implementation supports it. -\end{footnote} -the behavior is undefined. - -\pnum -\begin{example} -The following defines a function-like -macro whose value is the maximum of its arguments. -It has the disadvantages of evaluating one or the other of its arguments -a second time -(including -\indextext{side effects}% -side effects) -and generating more code than a function if invoked several times. -It also cannot have its address taken, -as it has none. - -\begin{codeblock} -#define max(a, b) ((a) > (b) ? (a) : (b)) -\end{codeblock} +If the scaled value is not in the range of representable +values for its type, the program is ill-formed. +Otherwise, the value of a \grammarterm{floating-point-literal} +is the scaled value if representable, +else the larger or smaller representable value nearest the scaled value, +chosen in an \impldef{choice of larger or smaller value of +\grammarterm{floating-point-literal}} manner. -The parentheses ensure that the arguments and -the resulting expression are bound properly. -\end{example} +\rSec3[lex.string.uneval]{Unevaluated strings} -\pnum -\indextext{macro!function-like!arguments}% -If there is a \tcode{...} immediately preceding the \tcode{)} in the -function-like macro -definition, then the trailing arguments (if any), including any separating comma preprocessing -tokens, are merged to form a single item: the \defn{variable arguments}. The number of -arguments so combined is such that, following merger, the number of arguments is -either equal to or -one more than the number of parameters in the macro definition (excluding the -\tcode{...}). - -\rSec3[cpp.subst]{Argument substitution}% -\indextext{macro!argument substitution}% -\indextext{argument substitution|see{macro, argument substitution}}% - -\indextext{__va_opt__@\mname{VA_OPT}}% \begin{bnf} -\nontermdef{va-opt-replacement}\br - \terminal{\mname{VA_OPT} (} \opt{pp-tokens} \terminal{)} +\nontermdef{unevaluated-string}\br + string-literal \end{bnf} \pnum -After the arguments for the invocation of a function-like macro have -been identified, argument substitution takes place. -For each parameter in the replacement list that is neither -preceded by a \tcode{\#} or \tcode{\#\#} preprocessing token nor -followed by a \tcode{\#\#} preprocessing token, the preprocessing tokens -naming the parameter are replaced by a token sequence determined as follows: -\begin{itemize} -\item - If the parameter is of the form \grammarterm{va-opt-replacement}, - the replacement preprocessing tokens are the - preprocessing token sequence for the corresponding argument, - as specified below. -\item - Otherwise, the replacement preprocessing tokens are the - preprocessing tokens of corresponding argument after all - macros contained therein have been expanded. The argument's - preprocessing tokens are completely macro replaced before - being substituted as if they formed the rest of the preprocessing - file with no other preprocessing tokens being available. -\end{itemize} -\begin{example} -\begin{codeblock} -#define LPAREN() ( -#define G(Q) 42 -#define F(R, X, ...) __VA_OPT__(G R X) ) -int x = F(LPAREN(), 0, <:-); // replaced by \tcode{int x = 42;} -\end{codeblock} -\end{example} - -\pnum -\indextext{__va_args__@\mname{VA_ARGS}}% -An identifier \mname{VA_ARGS} that occurs in the replacement list -shall be treated as if it were a parameter, and the variable arguments shall form -the preprocessing tokens used to replace it. - -\pnum -\begin{example} -\begin{codeblock} -#define debug(...) fprintf(stderr, @\mname{VA_ARGS}@) -#define showlist(...) puts(#@\mname{VA_ARGS}@) -#define report(test, ...) ((test) ? puts(#test) : printf(@\mname{VA_ARGS}@)) -debug("Flag"); -debug("X = %d\n", x); -showlist(The first, second, and third items.); -report(x>y, "x is %d but y is %d", x, y); -\end{codeblock} -results in -\begin{codeblock} -fprintf(stderr, "Flag"); -fprintf(stderr, "X = %d\n", x); -puts("The first, second, and third items."); -((x>y) ? puts("x>y") : printf("x is %d but y is %d", x, y)); -\end{codeblock} -\end{example} - -\pnum -\indextext{__va_opt__@\mname{VA_OPT}}% -The identifier \mname{VA_OPT} -shall always occur as part of the preprocessing token sequence -\grammarterm{va-opt-replacement}; -its closing \tcode{)} is determined by skipping -intervening pairs of matching left and right parentheses -in its \grammarterm{pp-tokens}. -The \grammarterm{pp-tokens} of a \grammarterm{va-opt-replacement} -shall not contain \mname{VA_OPT}. -If the \grammarterm{pp-tokens} would be ill-formed -as the replacement list of the current function-like macro, -the program is ill-formed. -A \grammarterm{va-opt-replacement} is treated as if it were a parameter, -and the preprocessing token sequence for the corresponding -argument is defined as follows. -If the substitution of \mname{VA_ARGS} as neither an operand -of \tcode{\#} nor \tcode{\#\#} consists of no preprocessing tokens, -the argument consists of -a single placemarker preprocessing token\iref{cpp.concat,cpp.rescan}. -Otherwise, the argument consists of -the results of the expansion of the contained \grammarterm{pp-tokens} -as the replacement list of the current function-like macro -before removal of placemarker tokens, rescanning, and further replacement. -\begin{note} -The placemarker tokens are removed before stringization\iref{cpp.stringize}, -and can be removed by rescanning and further replacement\iref{cpp.rescan}. -\end{note} -\begin{example} -\begin{codeblock} -#define F(...) f(0 __VA_OPT__(,) __VA_ARGS__) -#define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__) -#define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ }) -#define EMP - -F(a, b, c) // replaced by \tcode{f(0, a, b, c)} -F() // replaced by \tcode{f(0)} -F(EMP) // replaced by \tcode{f(0)} - -G(a, b, c) // replaced by \tcode{f(0, a, b, c)} -G(a, ) // replaced by \tcode{f(0, a)} -G(a) // replaced by \tcode{f(0, a)} - -SDEF(foo); // replaced by \tcode{S foo;} -SDEF(bar, 1, 2); // replaced by \tcode{S bar = \{ 1, 2 \};} - -#define H1(X, ...) X __VA_OPT__(##) __VA_ARGS__ // error: \tcode{\#\#} may not appear at - // the beginning of a replacement list\iref{cpp.concat} - -#define H2(X, Y, ...) __VA_OPT__(X ## Y,) __VA_ARGS__ -H2(a, b, c, d) // replaced by \tcode{ab, c, d} - -#define H3(X, ...) #__VA_OPT__(X##X X##X) -H3(, 0) // replaced by \tcode{""} - -#define H4(X, ...) __VA_OPT__(a X ## X) ## b -H4(, 1) // replaced by \tcode{a b} - -#define H5A(...) __VA_OPT__()@\tcode{/**/}@__VA_OPT__() -#define H5B(X) a ## X ## b -#define H5C(X) H5B(X) -H5C(H5A()) // replaced by \tcode{ab} -\end{codeblock} -\end{example} - -\rSec3[cpp.stringize]{The \tcode{\#} operator}% -\indextext{\#\#0 operator@\tcode{\#} operator}% -\indextext{stringize|see{\tcode{\#} operator}} - -\pnum -Each -\tcode{\#} -preprocessing token in the replacement list for a function-like -macro shall be followed by a parameter as the next preprocessing -token in the replacement list. - -\pnum -A \defn{character string literal} is a \grammarterm{string-literal} with no prefix. -If, in the replacement list, a parameter is immediately -preceded by a -\tcode{\#} -preprocessing token, -both are replaced by a single character string literal preprocessing token that -contains the spelling of the preprocessing token sequence for the -corresponding argument (excluding placemarker tokens). -Let the \defn{stringizing argument} be the preprocessing token sequence -for the corresponding argument with placemarker tokens removed. -Each occurrence of whitespace between the stringizing argument's preprocessing -tokens becomes a single space character in the character string literal. -Whitespace before the first preprocessing token and after the last -preprocessing token comprising the stringizing argument is deleted. -Otherwise, the original spelling of each preprocessing token in the -stringizing argument is retained in the character string literal, -except for special handling for producing the spelling of -\grammarterm{string-literal}s and \grammarterm{character-literal}s: -a -\tcode{\textbackslash} -character is inserted before each -\tcode{"} -and -\tcode{\textbackslash} -character of a \grammarterm{character-literal} or \grammarterm{string-literal} -(including the delimiting -\tcode{"} -characters). -If the replacement that results is not a valid character string literal, -the behavior is undefined. The character string literal corresponding to -an empty stringizing argument is \tcode{""}. -The order of evaluation of -\tcode{\#} -and -\tcode{\#\#} -operators is unspecified. - -\rSec3[cpp.concat]{The \tcode{\#\#} operator}% -\indextext{\#\#1 operator@\tcode{\#\#} operator}% -\indextext{concatenation!macro argument|see{\tcode{\#\#} operator}} - -\pnum -A -\tcode{\#\#} -preprocessing token shall not occur at the beginning or -at the end of a replacement list for either form -of macro definition. - -\pnum -If, in the replacement list of a function-like macro, a parameter is -immediately preceded or followed by a -\tcode{\#\#} -preprocessing token, the parameter is replaced by the -corresponding argument's preprocessing token sequence; however, if an argument consists of no preprocessing tokens, the parameter is -replaced by a placemarker preprocessing token instead. -\begin{footnote} -Placemarker preprocessing tokens do not appear in the syntax -because they are temporary entities that exist only within translation phase 4. -\end{footnote} - -\pnum -For both object-like and function-like macro invocations, before the -replacement list is reexamined for more macro names to replace, -each instance of a -\tcode{\#\#} -preprocessing token in the replacement list -(not from an argument) is deleted and the -preceding preprocessing token is concatenated -with the following preprocessing token. -Placemarker preprocessing tokens are handled specially: concatenation -of two placemarkers results in a single placemarker preprocessing token, and -concatenation of a placemarker with a non-placemarker preprocessing token results -in the non-placemarker preprocessing token. -\begin{note} -Concatenation can form -a \grammarterm{universal-character-name}\iref{lex.charset}. -\end{note} -If the result is not a valid preprocessing token, -the behavior is undefined. -The resulting token is available for further macro replacement. -The order of evaluation of -\tcode{\#\#} -operators is unspecified. - -\pnum -\begin{example} -The sequence -\begin{codeblock} -#define str(s) # s -#define xstr(s) str(s) -#define debug(s, t) printf("x" # s "= %d, x" # t "= %s", @\textbackslash@ - x ## s, x ## t) -#define INCFILE(n) vers ## n -#define glue(a, b) a ## b -#define xglue(a, b) glue(a, b) -#define HIGHLOW "hello" -#define LOW LOW ", world" - -debug(1, 2); -fputs(str(strncmp("abc@\textbackslash@0d", "abc", '@\textbackslash@4') // this goes away - == 0) str(: @\atsign\textbackslash@n), s); -#include xstr(INCFILE(2).h) -glue(HIGH, LOW); -xglue(HIGH, LOW) -\end{codeblock} -results in -\begin{codeblock} -printf("x" "1" "= %d, x" "2" "= %s", x1, x2); -fputs("strncmp(@\textbackslash@"abc@\textbackslash\textbackslash@0d@\textbackslash@", @\textbackslash@"abc@\textbackslash@", '@\textbackslash\textbackslash@4') == 0" ": @\atsign\textbackslash@n", s); -#include "vers2.h" @\textrm{(\textit{after macro replacement, before file access})}@ -"hello"; -"hello" ", world" -\end{codeblock} -or, after concatenation of the character string literals, -\begin{codeblock} -printf("x1= %d, x2= %s", x1, x2); -fputs("strncmp(@\textbackslash@"abc@\textbackslash\textbackslash@0d@\textbackslash@", @\textbackslash@"abc@\textbackslash@", '@\textbackslash\textbackslash@4') == 0: @\atsign\textbackslash@n", s); -#include "vers2.h" @\textrm{(\textit{after macro replacement, before file access})}@ -"hello"; -"hello, world" -\end{codeblock} - -Space around the \tcode{\#} and \tcode{\#\#} tokens in the macro definition -is optional. -\end{example} - -\pnum -\begin{example} -In the following fragment: - -\begin{codeblock} -#define hash_hash # ## # -#define mkstr(a) # a -#define in_between(a) mkstr(a) -#define join(c, d) in_between(c hash_hash d) -char p[] = join(x, y); // equivalent to \tcode{char p[] = "x \#\# y";} -\end{codeblock} - -The expansion produces, at various stages: - -\begin{codeblock} -join(x, y) -in_between(x hash_hash y) -in_between(x ## y) -mkstr(x ## y) -"x ## y" -\end{codeblock} - -In other words, expanding \tcode{hash_hash} produces a new token, -consisting of two adjacent sharp signs, but this new token is not the -\tcode{\#\#} operator. -\end{example} +An \grammarterm{unevaluated-string} shall have no \grammarterm{encoding-prefix}. \pnum -\begin{example} -To illustrate the rules for placemarker preprocessing tokens, the sequence -\begin{codeblock} -#define t(x,y,z) x ## y ## z -int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), - t(10,,), t(,11,), t(,,12), t(,,) }; -\end{codeblock} -results in -\begin{codeblock} -int j[] = { 123, 45, 67, 89, - 10, 11, 12, }; -\end{codeblock} -\end{example} - -\rSec3[cpp.rescan]{Rescanning and further replacement}% -\indextext{macro!rescanning and replacement}% -\indextext{rescanning and replacement|see{macro, rescanning and replacement}} - -\pnum -After all parameters in the replacement list have been substituted and \tcode{\#} and \tcode{\#\#} processing has taken -place, all placemarker preprocessing tokens are removed. Then -the resulting preprocessing token sequence is rescanned, along with all -subsequent preprocessing tokens of the source file, for more macro names -to replace. - -\pnum -\begin{example} -The sequence -\begin{codeblock} -#define x 3 -#define f(a) f(x * (a)) -#undef x -#define x 2 -#define g f -#define z z[0] -#define h g(~ -#define m(a) a(w) -#define w 0,1 -#define t(a) a -#define p() int -#define q(x) x -#define r(x,y) x ## y -#define str(x) # x - -f(y+1) + f(f(z)) % t(t(g)(0) + t)(1); -g(x+(3,4)-w) | h 5) & m - (f)^m(m); -p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) }; -char c[2][6] = { str(hello), str() }; -\end{codeblock} -results in -\begin{codeblock} -f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); -f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); -int i[] = { 1, 23, 4, 5, }; -char c[2][6] = { "hello", "" }; -\end{codeblock} -\end{example} - -\pnum -If the name of the macro being replaced is found during this scan of -the replacement list -(not including the rest of the source file's preprocessing tokens), -it is not replaced. -Furthermore, -if any nested replacements encounter the name of the macro being replaced, -it is not replaced. -These nonreplaced macro name preprocessing tokens are no longer available -for further replacement even if they are later (re)examined in contexts -in which that macro name preprocessing token would otherwise have been -replaced. - -\pnum -The resulting completely macro-replaced preprocessing token sequence -is not processed as a preprocessing directive even if it resembles one, -but all pragma unary operator expressions within it are then processed as -specified in~\ref{cpp.pragma.op} below. - -\rSec3[cpp.scope]{Scope of macro definitions}% -\indextext{macro!scope of definition}% -\indextext{scope!macro definition|see{macro, scope of definition}} - -\pnum -A macro definition lasts -(independent of block structure) -until a corresponding -\tcode{\#undef} -directive is encountered or -(if none is encountered) -until the end of the translation unit. -Macro definitions have no significance after translation phase 4. - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# undef} identifier new-line -\indextext{\idxcode{\#undef}}% -\end{ncsimplebnf} -causes the specified identifier no longer to be defined as a macro name. -It is ignored if the specified identifier is not currently defined as -a macro name. - -\indextext{macro!replacement|)} - -\rSec2[cpp.predefined]{Predefined macro names} -\indextext{macro!predefined}% -\indextext{name!predefined macro|see{macro, predefined}} - -\pnum -The following macro names shall be defined by the implementation: - -\begin{description} - -\item -\indextext{\idxxname{cplusplus}}% -\xname{cplusplus}\\ -The integer literal \tcode{\cppver}. -\begin{note} -Future revisions of this document will -replace the value of this macro with a greater value. -\end{note} - -\item The names listed in \tref{cpp.predefined.ft}.\\ -The macros defined in \tref{cpp.predefined.ft} shall be defined to -the corresponding integer literal. -\begin{note} -Future revisions of this document might replace -the values of these macros with greater values. -\end{note} - -\item -\indextext{__date__@\mname{DATE}}% -\mname{DATE}\\ -The date of translation of the source file: -a character string literal of the form -\tcode{"Mmm~dd~yyyy"}, -where the names of the months are the same as those generated -by the -\tcode{asctime} -function, -and the first character of -\tcode{dd} -is a space character if the value is less than 10. -If the date of translation is not available, -an \impldef{text of \mname{DATE} when date of translation is not available} valid date -shall be supplied. - -\item -\indextext{__file__@\mname{FILE}}% -\mname{FILE}\\ -The presumed name of the current source file (a character string -literal). -\begin{footnote} -The presumed source file name can be changed by the \tcode{\#line} directive. -\end{footnote} - -\item -\indextext{__line__@\mname{LINE}}% -\mname{LINE}\\ -The presumed line number (within the current source file) of the current source line -(an integer literal). -\begin{footnote} -The presumed line number can be changed by the \tcode{\#line} directive. -\end{footnote} - -\item -\indextext{__stdc_hosted__@\mname{STDC_HOSTED}}% -\indextext{implementation!hosted}% -\indextext{implementation!freestanding}% -\mname{STDC_HOSTED}\\ -The integer literal \tcode{1} -if the implementation is a hosted implementation or -the integer literal \tcode{0} -if it is a freestanding implementation\iref{intro.compliance}. - -\item -\indextext{__stdcpp_default_new_alignment__@\mname{STDCPP_DEFAULT_NEW_ALIGNMENT}}% -\mname{STDCPP_DEFAULT_NEW_ALIGNMENT}\\ -An integer literal of type \tcode{std::size_t} -whose value is the alignment guaranteed -by a call to \tcode{operator new(std::size_t)} -or \tcode{operator new[](std::size_t)}. -\begin{note} -Larger alignments will be passed to -\tcode{operator new(std::size_t, std::align_val_t)}, etc.\iref{expr.new}. -\end{note} - -\item -\indextext{__stdcpp_float16_t__@\mname{STDCPP_FLOAT16_T}}% -\mname{STDCPP_FLOAT16_T}\\ -Defined as the integer literal \tcode{1} -if and only if the implementation supports -the \IsoFloatUndated{} floating-point interchange format binary16 -as an extended floating-point type\iref{basic.extended.fp}. - -\item -\indextext{__stdcpp_float32_t__@\mname{STDCPP_FLOAT32_T}}% -\mname{STDCPP_FLOAT32_T}\\ -Defined as the integer literal \tcode{1} -if and only if the implementation supports -the \IsoFloatUndated{} floating-point interchange format binary32 -as an extended floating-point type. - -\item -\indextext{__stdcpp_float64_t__@\mname{STDCPP_FLOAT64_T}}% -\mname{STDCPP_FLOAT64_T}\\ -Defined as the integer literal \tcode{1} -if and only if the implementation supports -the \IsoFloatUndated{} floating-point interchange format binary64 -as an extended floating-point type. - -\item -\indextext{__stdcpp_float128_t__@\mname{STDCPP_FLOAT128_T}}% -\mname{STDCPP_FLOAT128_T}\\ -Defined as the integer literal \tcode{1} -if and only if the implementation supports -the \IsoFloatUndated{} floating-point interchange format binary128 -as an extended floating-point type. - -\item -\indextext{__stdcpp_bfloat16_t__@\mname{STDCPP_BFLOAT16_T}}% -\mname{STDCPP_BFLOAT16_T}\\ -Defined as the integer literal \tcode{1} -if and only if the implementation supports an extended floating-point type -with the properties of the \grammarterm{typedef-name} \tcode{std::bfloat16_t} -as described in \ref{basic.extended.fp}. - -\item -\indextext{__time__@\mname{TIME}}% -\mname{TIME}\\ -The time of translation of the source file: -a character string literal of the form -\tcode{"hh:mm:ss"} -as in the time generated by the -\tcode{asctime} -function. -If the time of translation is not available, -an \impldef{text of \mname{TIME} when time of translation is not available} valid time shall be supplied. -\end{description} - -\indextext{macro!feature-test}% -\indextext{feature-test macro|see{macro, feature-test}}% -\begin{LongTable}{Feature-test macros}{cpp.predefined.ft}{ll} -\\ \topline -\lhdr{Macro name} & \rhdr{Value} \\ \capsep -\endfirsthead -\continuedcaption \\ -\hline -\lhdr{Name} & \rhdr{Value} \\ \capsep -\endhead -\defnxname{cpp_aggregate_bases} & \tcode{201603L} \\ \rowsep -\defnxname{cpp_aggregate_nsdmi} & \tcode{201304L} \\ \rowsep -\defnxname{cpp_aggregate_paren_init} & \tcode{201902L} \\ \rowsep -\defnxname{cpp_alias_templates} & \tcode{200704L} \\ \rowsep -\defnxname{cpp_aligned_new} & \tcode{201606L} \\ \rowsep -\defnxname{cpp_attributes} & \tcode{200809L} \\ \rowsep -\defnxname{cpp_auto_cast} & \tcode{202110L} \\ \rowsep -\defnxname{cpp_binary_literals} & \tcode{201304L} \\ \rowsep -\defnxname{cpp_capture_star_this} & \tcode{201603L} \\ \rowsep -\defnxname{cpp_char8_t} & \tcode{202207L} \\ \rowsep -\defnxname{cpp_concepts} & \tcode{202002L} \\ \rowsep -\defnxname{cpp_conditional_explicit} & \tcode{201806L} \\ \rowsep -\defnxname{cpp_constexpr} & \tcode{202406L} \\ \rowsep -\defnxname{cpp_constexpr_dynamic_alloc} & \tcode{201907L} \\ \rowsep -\defnxname{cpp_constexpr_in_decltype} & \tcode{201711L} \\ \rowsep -\defnxname{cpp_consteval} & \tcode{202211L} \\ \rowsep -\defnxname{cpp_constinit} & \tcode{201907L} \\ \rowsep -\defnxname{cpp_decltype} & \tcode{200707L} \\ \rowsep -\defnxname{cpp_decltype_auto} & \tcode{201304L} \\ \rowsep -\defnxname{cpp_deduction_guides} & \tcode{201907L} \\ \rowsep -\defnxname{cpp_delegating_constructors} & \tcode{200604L} \\ \rowsep -\defnxname{cpp_deleted_function} & \tcode{202403L} \\ \rowsep -\defnxname{cpp_designated_initializers} & \tcode{201707L} \\ \rowsep -\defnxname{cpp_enumerator_attributes} & \tcode{201411L} \\ \rowsep -\defnxname{cpp_explicit_this_parameter} & \tcode{202110L} \\ \rowsep -\defnxname{cpp_fold_expressions} & \tcode{201603L} \\ \rowsep -\defnxname{cpp_generic_lambdas} & \tcode{201707L} \\ \rowsep -\defnxname{cpp_guaranteed_copy_elision} & \tcode{201606L} \\ \rowsep -\defnxname{cpp_hex_float} & \tcode{201603L} \\ \rowsep -\defnxname{cpp_if_consteval} & \tcode{202106L} \\ \rowsep -\defnxname{cpp_if_constexpr} & \tcode{201606L} \\ \rowsep -\defnxname{cpp_impl_coroutine} & \tcode{201902L} \\ \rowsep -\defnxname{cpp_impl_destroying_delete} & \tcode{201806L} \\ \rowsep -\defnxname{cpp_impl_three_way_comparison} & \tcode{201907L} \\ \rowsep -\defnxname{cpp_implicit_move} & \tcode{202207L} \\ \rowsep -\defnxname{cpp_inheriting_constructors} & \tcode{201511L} \\ \rowsep -\defnxname{cpp_init_captures} & \tcode{201803L} \\ \rowsep -\defnxname{cpp_initializer_lists} & \tcode{200806L} \\ \rowsep -\defnxname{cpp_inline_variables} & \tcode{201606L} \\ \rowsep -\defnxname{cpp_lambdas} & \tcode{200907L} \\ \rowsep -\defnxname{cpp_modules} & \tcode{201907L} \\ \rowsep -\defnxname{cpp_multidimensional_subscript} & \tcode{202211L} \\ \rowsep -\defnxname{cpp_named_character_escapes} & \tcode{202207L} \\ \rowsep -\defnxname{cpp_namespace_attributes} & \tcode{201411L} \\ \rowsep -\defnxname{cpp_noexcept_function_type} & \tcode{201510L} \\ \rowsep -\defnxname{cpp_nontype_template_args} & \tcode{201911L} \\ \rowsep -\defnxname{cpp_nontype_template_parameter_auto} & \tcode{201606L} \\ \rowsep -\defnxname{cpp_nsdmi} & \tcode{200809L} \\ \rowsep -\defnxname{cpp_pack_indexing} & \tcode{202311L} \\ \rowsep -\defnxname{cpp_placeholder_variables} & \tcode{202306L} \\ \rowsep -\defnxname{cpp_range_based_for} & \tcode{202211L} \\ \rowsep -\defnxname{cpp_raw_strings} & \tcode{200710L} \\ \rowsep -\defnxname{cpp_ref_qualifiers} & \tcode{200710L} \\ \rowsep -\defnxname{cpp_return_type_deduction} & \tcode{201304L} \\ \rowsep -\defnxname{cpp_rvalue_references} & \tcode{200610L} \\ \rowsep -\defnxname{cpp_size_t_suffix} & \tcode{202011L} \\ \rowsep -\defnxname{cpp_sized_deallocation} & \tcode{201309L} \\ \rowsep -\defnxname{cpp_static_assert} & \tcode{202306L} \\ \rowsep -\defnxname{cpp_static_call_operator} & \tcode{202207L} \\ \rowsep -\defnxname{cpp_structured_bindings} & \tcode{202403L} \\ \rowsep -\defnxname{cpp_template_template_args} & \tcode{201611L} \\ \rowsep -\defnxname{cpp_threadsafe_static_init} & \tcode{200806L} \\ \rowsep -\defnxname{cpp_unicode_characters} & \tcode{200704L} \\ \rowsep -\defnxname{cpp_unicode_literals} & \tcode{200710L} \\ \rowsep -\defnxname{cpp_user_defined_literals} & \tcode{200809L} \\ \rowsep -\defnxname{cpp_using_enum} & \tcode{201907L} \\ \rowsep -\defnxname{cpp_variable_templates} & \tcode{201304L} \\ \rowsep -\defnxname{cpp_variadic_friend} & \tcode{202403L} \\ \rowsep -\defnxname{cpp_variadic_templates} & \tcode{200704L} \\ \rowsep -\defnxname{cpp_variadic_using} & \tcode{201611L} \\ -\end{LongTable} - -\pnum -The following macro names are conditionally defined by the implementation: - -\begin{description} -\item -\indextext{__stdc__@\mname{STDC}}% -\mname{STDC}\\ -Whether \mname{STDC} is predefined and if so, what its value is, -are \impldef{definition and meaning of \mname{STDC}}. - -\item -\indextext{__stdc_mb_might_neq_wc__@\mname{STDC_MB_MIGHT_NEQ_WC}}% -\mname{STDC_MB_MIGHT_NEQ_WC}\\ -The integer literal \tcode{1}, intended to indicate that, in the encoding for -\keyword{wchar_t}, a member of the basic character set need not have a code value equal to -its value when used as the lone character in an ordinary character literal. - -\item -\indextext{__stdc_version__@\mname{STDC_VERSION}}% -\mname{STDC_VERSION}\\ -Whether \mname{STDC_VERSION} is predefined and if so, what its value is, -are \impldef{definition and meaning of \mname{STDC_VERSION}}. - -\item -\indextext{__stdc_iso_10646__@\mname{STDC_ISO_10646}}% -\mname{STDC_ISO_10646}\\ -An integer literal of the form \tcode{yyyymmL} -(for example, \tcode{199712L}). -Whether \mname{STDC_ISO_10646} is predefined and -if so, what its value is, -are \impldef{presence and value of \mname{STDC_ISO_10646}}. - -\item -\indextext{__stdcpp_threads__@\mname{STDCPP_THREADS}}% -\mname{STDCPP_THREADS}\\ -Defined, and has the value integer literal 1, if and only if a program -can have more than one thread of execution\iref{intro.multithread}. - -\end{description} - -\pnum -The values of the predefined macros -(except for -\mname{FILE} -and -\mname{LINE}) -remain constant throughout the translation unit. - -\pnum -If any of the pre-defined macro names in this subclause, -or the identifier -\tcode{defined}, -is the subject of a -\tcode{\#define} -or a -\tcode{\#undef} -preprocessing directive, -the behavior is undefined. -Any other predefined macro names shall begin with a -leading underscore followed by an uppercase letter or a second -underscore. - -\rSec2[cpp.cond]{Conditional inclusion}% -\indextext{preprocessing directive!conditional inclusion}% -\indextext{inclusion!conditional|see{preprocessing directive, conditional inclusion}} - -\indextext{\idxcode{defined}}% -\begin{bnf} -\nontermdef{defined-macro-expression}\br - \terminal{defined} identifier\br - \terminal{defined (} identifier \terminal{)} -\end{bnf} - -\begin{bnf} -\nontermdef{h-preprocessing-token}\br - \textnormal{any \grammarterm{preprocessing-token} other than \terminal{>}} -\end{bnf} - -\begin{bnf} -\nontermdef{h-pp-tokens}\br - h-preprocessing-token\br - h-pp-tokens h-preprocessing-token -\end{bnf} - -\begin{bnf} -\nontermdef{header-name-tokens}\br - string-literal\br - \terminal{<} h-pp-tokens \terminal{>} -\end{bnf} - -\indextext{\idxxname{has_include}}% -\begin{bnf} -\nontermdef{has-include-expression}\br - \terminal{\xname{has_include}} \terminal{(} header-name \terminal{)}\br - \terminal{\xname{has_include}} \terminal{(} header-name-tokens \terminal{)} -\end{bnf} - -\indextext{\idxxname{has_cpp_attribute}}% -\begin{bnf} -\nontermdef{has-attribute-expression}\br - \terminal{\xname{has_cpp_attribute} (} pp-tokens \terminal{)} -\end{bnf} - -\pnum -The expression that controls conditional inclusion -shall be an integral constant expression except that -identifiers -(including those lexically identical to keywords) -are interpreted as described below -\begin{footnote} -Because the controlling constant expression is evaluated -during translation phase 4, -all identifiers either are or are not macro names --- -there simply are no keywords, enumeration constants, etc. -\end{footnote} -and it may contain zero or more \grammarterm{defined-macro-expression}{s} and/or -\grammarterm{has-include-expression}{s} and/or -\grammarterm{has-attribute-expression}{s} as unary operator expressions. - -\pnum -A \grammarterm{defined-macro-expression} evaluates to \tcode{1} -if the identifier is currently defined -as a macro name -(that is, if it is predefined -or if it has one or more active macro definitions\iref{cpp.import}, -for example because -it has been the subject of a -\tcode{\#define} -preprocessing directive -without an intervening -\tcode{\#undef} -directive with the same subject identifier), \tcode{0} if it is not. - -\pnum -The second form of \grammarterm{has-include-expression} -is considered only if the first form does not match, -in which case the preprocessing tokens are processed just as in normal text. - -\pnum -The header or source file identified by -the parenthesized preprocessing token sequence -in each contained \grammarterm{has-include-expression} -is searched for as if that preprocessing token sequence -were the \grammarterm{pp-tokens} in a \tcode{\#include} directive, -except that no further macro expansion is performed. -If such a directive would not satisfy the syntactic requirements -of a \tcode{\#include} directive, the program is ill-formed. -The \grammarterm{has-include-expression} evaluates -to \tcode{1} if the search for the source file succeeds, and -to \tcode{0} if the search fails. - -\pnum -Each \grammarterm{has-attribute-expression} is replaced by -a non-zero \grammarterm{pp-number} -matching the form of an \grammarterm{integer-literal} -if the implementation supports an attribute -with the name specified by interpreting -the \grammarterm{pp-tokens}, after macro expansion, -as an \grammarterm{attribute-token}, -and by \tcode{0} otherwise. -The program is ill-formed if the \grammarterm{pp-tokens} -do not match the form of an \grammarterm{attribute-token}. - -\pnum -For an attribute specified in this document, -it is \impldef{value of \grammarterm{has-attribute-expression} -for standard attributes} -whether the value of the \grammarterm{has-attribute-expression} -is \tcode{0} or is given by \tref{cpp.cond.ha}. -For other attributes recognized by the implementation, -the value is -\impldef{value of \grammarterm{has-attribute-expression} -for non-standard attributes}. -\begin{note} -It is expected -that the availability of an attribute can be detected by any non-zero result. -\end{note} - -\begin{floattable}{\xname{has_cpp_attribute} values}{cpp.cond.ha} -{ll} -\topline -\lhdr{Attribute} & \rhdr{Value} \\ \rowsep -\tcode{assume} & \tcode{202207L} \\ -\tcode{carries_dependency} & \tcode{200809L} \\ -\tcode{deprecated} & \tcode{201309L} \\ -\tcode{fallthrough} & \tcode{201603L} \\ -\tcode{likely} & \tcode{201803L} \\ -\tcode{maybe_unused} & \tcode{201603L} \\ -\tcode{no_unique_address} & \tcode{201803L} \\ -\tcode{nodiscard} & \tcode{201907L} \\ -\tcode{noreturn} & \tcode{200809L} \\ -\tcode{unlikely} & \tcode{201803L} \\ -\end{floattable} - -\pnum -The -\tcode{\#ifdef}, \tcode{\#ifndef}, \tcode{\#elifdef}, and \tcode{\#elifndef} -directives, and -the \tcode{defined} conditional inclusion operator, -shall treat \xname{has_include} and \xname{has_cpp_attribute} -as if they were the names of defined macros. -The identifiers \xname{has_include} and \xname{has_cpp_attribute} -shall not appear in any context not mentioned in this subclause. - -\pnum -Each preprocessing token that remains (in the list of preprocessing tokens that -will become the controlling expression) -after all macro replacements have occurred -shall be in the lexical form of a token\iref{lex.token}. - -\pnum -Preprocessing directives of the forms -\begin{ncsimplebnf}\obeyspaces -\indextext{\idxcode{\#if}}% -\terminal{\# if } constant-expression new-line \opt{group}\br -\indextext{\idxcode{\#elif}}% -\terminal{\# elif } constant-expression new-line \opt{group} -\end{ncsimplebnf} -check whether the controlling constant expression evaluates to nonzero. - -\pnum -Prior to evaluation, -macro invocations in the list of preprocessing tokens -that will become the controlling constant expression -are replaced -(except for those macro names modified by the -\tcode{defined} -unary operator), -just as in normal text. -If the token -\tcode{defined} -is generated as a result of this replacement process -or use of the -\tcode{defined} -unary operator does not match one of the two specified forms -prior to macro replacement, -the behavior is undefined. - -\pnum -After all replacements due to macro expansion and -evaluations of -\grammarterm{defined-macro-expression}s, -\grammarterm{has-include-expression}s, and -\grammarterm{has-attribute-expression}s -have been performed, -all remaining identifiers and keywords, -except for -\tcode{true} -and -\tcode{false}, -are replaced with the \grammarterm{pp-number} -\tcode{0}, -and then each preprocessing token is converted into a token. -\begin{note} -An alternative -token\iref{lex.operators} is not an identifier, -even when its spelling consists entirely of letters and underscores. -Therefore it is not subject to this replacement. -\end{note} - -\pnum -The resulting tokens comprise the controlling constant expression -which is evaluated according to the rules of~\ref{expr.const} -using arithmetic that has at least the ranges specified -in~\ref{support.limits}. For the purposes of this token conversion and evaluation -all signed and unsigned integer types -act as if they have the same representation as, respectively, -\tcode{intmax_t} or \tcode{uintmax_t}\iref{cstdint.syn}. -\begin{note} -Thus on an -implementation where \tcode{std::numeric_limits::max()} is \tcode{0x7FFF} -and \tcode{std::numeric_limits::max()} is \tcode{0xFFFF}, -the integer literal \tcode{0x8000} is signed and positive within a \tcode{\#if} -expression even though it is unsigned in translation phase -7\iref{lex.phases}. -\end{note} -This includes interpreting \grammarterm{character-literal}s -according to the rules in \ref{lex.ccon}. -\begin{note} -The associated character encodings of literals are the same -in \tcode{\#if} and \tcode{\#elif} directives and in any expression. -\end{note} -Each subexpression with type -\tcode{bool} -is subjected to integral promotion before processing continues. - -\pnum -Preprocessing directives of the forms -\begin{ncsimplebnf}\obeyspaces -\terminal{\# ifdef } identifier new-line \opt{group}\br -\indextext{\idxcode{\#ifdef}}% -\terminal{\# ifndef } identifier new-line \opt{group}\br -\indextext{\idxcode{\#ifndef}}% -\terminal{\# elifdef } identifier new-line \opt{group}\br -\indextext{\idxcode{\#elifdef}}% -\terminal{\# elifndef} identifier new-line \opt{group} -\indextext{\idxcode{\#elifndef}}% -\end{ncsimplebnf} -check whether the identifier is or is not currently defined as a macro name. -Their conditions are equivalent to -\tcode{\#if} \tcode{defined} \grammarterm{identifier}, -\tcode{\#if} \tcode{!defined} \grammarterm{identifier}, -\tcode{\#elif} \tcode{defined} \grammarterm{identifier}, and -\tcode{\#elif} \tcode{!defined} \grammarterm{identifier}, -respectively. - -\pnum -Each directive's condition is checked in order. -If it evaluates to false (zero), -the group that it controls is skipped: -directives are processed only through the name that determines -the directive in order to keep track of the level -of nested conditionals; -the rest of the directives' preprocessing tokens are ignored, -as are the other preprocessing tokens in the group. -Only the first group -whose control condition evaluates to true (nonzero) is processed; -any following groups are skipped and their controlling directives -are processed as if they were in a group that is skipped. -If none of the conditions evaluates to true, -and there is a -\tcode{\#else} -\indextext{\idxcode{\#else}}% -directive, -the group controlled by the -\tcode{\#else} -is processed; lacking a -\tcode{\#else} -directive, all the groups until the -\tcode{\#endif} -\indextext{\idxcode{\#endif}}% -are skipped.% -\begin{footnote} -As indicated by the syntax, -a preprocessing token cannot follow a -\tcode{\#else} -or -\tcode{\#endif} -directive before the terminating new-line character. -However, -comments can appear anywhere in a source file, -including within a preprocessing directive. -\end{footnote} - -\pnum -\begin{example} -This demonstrates a way to include a library \tcode{optional} facility -only if it is available: - -\begin{codeblock} -#if __has_include() -# include -# if __cpp_lib_optional >= 201603 -# define have_optional 1 -# endif -#elif __has_include() -# include -# if __cpp_lib_experimental_optional >= 201411 -# define have_optional 1 -# define experimental_optional 1 -# endif -#endif -#ifndef have_optional -# define have_optional 0 -#endif -\end{codeblock} -\end{example} - -\pnum -\begin{example} -This demonstrates a way to use the attribute \tcode{[[acme::deprecated]]} -only if it is available. -\begin{codeblock} -#if __has_cpp_attribute(acme::deprecated) -# define ATTR_DEPRECATED(msg) [[acme::deprecated(msg)]] -#else -# define ATTR_DEPRECATED(msg) [[deprecated(msg)]] -#endif -ATTR_DEPRECATED("This function is deprecated") void anvil(); -\end{codeblock} -\end{example} - -\rSec2[cpp.include]{Source file inclusion} -\indextext{preprocessing directive!header inclusion} -\indextext{preprocessing directive!source-file inclusion} -\indextext{inclusion!source file|see{preprocessing directive, source-file inclusion}}% -\indextext{\idxcode{\#include}}% - -\pnum -A -\tcode{\#include} -directive shall identify a header or source file -that can be processed by the implementation. - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# include <} h-char-sequence \terminal{>} new-line -\end{ncsimplebnf} -searches a sequence of -\impldef{sequence of places searched for a header} -places -for a header identified uniquely by the specified sequence -between the -\tcode{<} -and -\tcode{>} -delimiters, -and causes the replacement of that -directive by the entire contents of the header. -How the places are specified -or the header identified -is \impldef{search locations for \tcode{<>} header}. - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# include "} q-char-sequence \terminal{"} new-line -\end{ncsimplebnf} -causes the replacement of that -directive by the entire contents of the -source file identified by the specified sequence between the -\tcode{"} -delimiters. -The named source file is searched for in an -\impldef{manner of search for included source file} -manner. -If this search is not supported, -or if the search fails, -the directive is reprocessed as if it read -\begin{ncsimplebnf} -\terminal{\# include <} h-char-sequence \terminal{>} new-line -\end{ncsimplebnf} -with the identical contained sequence (including -\tcode{>} -characters, if any) from the original directive. - -\pnum -A preprocessing directive of the form -\begin{ncsimplebnf} -\terminal{\# include} pp-tokens new-line -\end{ncsimplebnf} -(that does not match one of the two previous forms) is permitted. -The preprocessing tokens after -\tcode{include} -in the directive are processed just as in normal text -(i.e., each identifier currently defined as a macro name is replaced by its -replacement list of preprocessing tokens). -If the directive resulting after all replacements does not match -one of the two previous forms, the behavior is -undefined. -\begin{footnote} -Note that adjacent \grammarterm{string-literal}s are not concatenated into -a single \grammarterm{string-literal} -(see the translation phases in~\ref{lex.phases}); -thus, an expansion that results in two \grammarterm{string-literal}s is an -invalid directive. -\end{footnote} -The method by which a sequence of preprocessing tokens between a -\tcode{<} -and a -\tcode{>} -preprocessing token pair or a pair of -\tcode{"} -characters is combined into a single header name -preprocessing token is \impldef{search locations for \tcode{""""} header}. - -\pnum -The implementation shall provide unique mappings for -sequences consisting of one or more -\grammarterm{nondigit}{s} or \grammarterm{digit}{s}\iref{lex.name} -followed by a period -(\tcode{.}) -and a single -\grammarterm{nondigit}. -The first character shall not be a \grammarterm{digit}. -The implementation may ignore distinctions of alphabetical case. - -\pnum -A -\tcode{\#include} -preprocessing directive may appear -in a source file that has been read because of a -\tcode{\#include} -directive in another file, -up to an \impldef{nesting limit for \tcode{\#include} directives} nesting limit. - -\pnum -If the header identified by the \grammarterm{header-name} -denotes an importable header\iref{module.import}, -it is -\impldef{whether source file inclusion of importable header -is replaced with \tcode{import} directive} -whether the \tcode{\#include} preprocessing directive -is instead replaced by an \tcode{import} directive\iref{cpp.import} of the form -\begin{ncbnf} -\terminal{import} header-name \terminal{;} new-line -\end{ncbnf} - -\pnum -\begin{note} -An implementation can provide a mechanism for making arbitrary -source files available to the \tcode{< >} search. -However, using the \tcode{< >} form for headers provided -with the implementation and the \tcode{" "} form for sources -outside the control of the implementation -achieves wider portability. For instance: - -\begin{codeblock} -#include -#include -#include "usefullib.h" -#include "myprog.h" -\end{codeblock} - -\end{note} - -\pnum -\begin{example} -This illustrates macro-replaced -\tcode{\#include} -directives: - -\begin{codeblock} -#if VERSION == 1 - #define INCFILE "vers1.h" -#elif VERSION == 2 - #define INCFILE "vers2.h" // and so on -#else - #define INCFILE "versN.h" -#endif -#include INCFILE -\end{codeblock} -\end{example} - -\rSec1[lex.tutokenize]{Translation unit tokenization} -\rSec2[lex.token]{Tokens} - -\indextext{token|(}% -\begin{bnf} -\nontermdef{token}\br - identifier\br - keyword\br - literal\br - operator-or-punctuator -\end{bnf} - -\pnum -\indextext{\idxgram{token}}% -There are five kinds of tokens: identifiers, keywords, literals,% -\begin{footnote} -Literals include strings and character and numeric literals. -\end{footnote} -operators, and other separators. -\indextext{whitespace}% -Blanks, horizontal and vertical tabs, newlines, formfeeds, and comments -(collectively, ``whitespace''), are ignored except -as they serve to separate tokens. -\begin{note} -Whitespace can separate otherwise adjacent identifiers, keywords, numeric -literals, and alternative tokens containing alphabetic characters. -\end{note} -\indextext{token|)} - -\rSec2[lex.key]{Keywords} - -\begin{bnf} -\nontermdef{keyword}\br - \textnormal{any identifier listed in \tref{lex.key}}\br - \grammarterm{import-keyword}\br - \grammarterm{module-keyword}\br - \grammarterm{export-keyword} -\end{bnf} - -\pnum -\indextext{keyword|(}% -The identifiers shown in \tref{lex.key} are reserved for use -as keywords (that is, they are unconditionally treated as keywords in -phase 7) except in an \grammarterm{attribute-token}\iref{dcl.attr.grammar}. -\begin{note} -The \keyword{register} keyword is unused but -is reserved for future use. -\end{note} - -\begin{multicolfloattable}{Keywords}{lex.key} -{lllll} -\keyword{alignas} \\ -\keyword{alignof} \\ -\keyword{asm} \\ -\keyword{auto} \\ -\keyword{bool} \\ -\keyword{break} \\ -\keyword{case} \\ -\keyword{catch} \\ -\keyword{char} \\ -\keyword{char8_t} \\ -\keyword{char16_t} \\ -\keyword{char32_t} \\ -\keyword{class} \\ -\keyword{concept} \\ -\keyword{const} \\ -\keyword{consteval} \\ -\keyword{constexpr} \\ -\columnbreak -\keyword{constinit} \\ -\keyword{const_cast} \\ -\keyword{continue} \\ -\keyword{co_await} \\ -\keyword{co_return} \\ -\keyword{co_yield} \\ -\keyword{decltype} \\ -\keyword{default} \\ -\keyword{delete} \\ -\keyword{do} \\ -\keyword{double} \\ -\keyword{dynamic_cast} \\ -\keyword{else} \\ -\keyword{enum} \\ -\keyword{explicit} \\ -\keyword{export} \\ -\keyword{extern} \\ -\columnbreak -\keyword{false} \\ -\keyword{float} \\ -\keyword{for} \\ -\keyword{friend} \\ -\keyword{goto} \\ -\keyword{if} \\ -\keyword{inline} \\ -\keyword{int} \\ -\keyword{long} \\ -\keyword{mutable} \\ -\keyword{namespace} \\ -\keyword{new} \\ -\keyword{noexcept} \\ -\keyword{nullptr} \\ -\keyword{operator} \\ -\keyword{private} \\ -\keyword{protected} \\ -\columnbreak -\keyword{public} \\ -\keyword{register} \\ -\keyword{reinterpret_cast} \\ -\keyword{requires} \\ -\keyword{return} \\ -\keyword{short} \\ -\keyword{signed} \\ -\keyword{sizeof} \\ -\keyword{static} \\ -\keyword{static_assert} \\ -\keyword{static_cast} \\ -\keyword{struct} \\ -\keyword{switch} \\ -\keyword{template} \\ -\keyword{this} \\ -\keyword{thread_local} \\ -\keyword{throw} \\ -\columnbreak -\keyword{true} \\ -\keyword{try} \\ -\keyword{typedef} \\ -\keyword{typeid} \\ -\keyword{typename} \\ -\keyword{union} \\ -\keyword{unsigned} \\ -\keyword{using} \\ -\keyword{virtual} \\ -\keyword{void} \\ -\keyword{volatile} \\ -\keyword{wchar_t} \\ -\keyword{while} \\ -\end{multicolfloattable} - -\pnum -\indextext{\idxcode{import}}% -\indextext{\idxcode{final}}% -\indextext{\idxcode{module}}% -\indextext{\idxcode{override}}% -The identifiers in \tref{lex.name.special} have a special meaning when -appearing in a certain context. When referred to in the grammar, these identifiers -are used explicitly rather than using the \grammarterm{identifier} grammar production. -Unless otherwise specified, any ambiguity as to whether a given -\grammarterm{identifier} has a special meaning is resolved to interpret the -token as a regular \grammarterm{identifier}. - -\begin{multicolfloattable}{Identifiers with special meaning}{lex.name.special} -{llll} -\keyword{final} \\ -\columnbreak -\keyword{import} \\ -\columnbreak -\keyword{module} \\ -\columnbreak -\keyword{override} \\ -\end{multicolfloattable} - -\pnum -\indextext{unit!translation}% -A translation unit shall not \tcode{\#define} or \tcode{\#undef} -names lexically identical -to keywords, -to the identifiers listed in \tref{lex.name.special}, or -to the \grammarterm{attribute-token}{s} described in~\ref{dcl.attr}, -except that the names \tcode{likely} and \tcode{unlikely} may be -defined as function-like macros~\iref{cpp.replace}. - -\pnum -Furthermore, the alternative representations shown in -\tref{lex.key.digraph} for certain operators and -punctuators\iref{lex.operators} are reserved and shall not be used -otherwise. - -\begin{floattable}{Alternative representations}{lex.key.digraph} -{llllll} -\topline -\keyword{and} & \keyword{and_eq} & \keyword{bitand} & \keyword{bitor} & \keyword{compl} & \keyword{not} \\ -\keyword{not_eq} & \keyword{or} & \keyword{or_eq} & \keyword{xor} & \keyword{xor_eq} & \\ -\end{floattable}% -\indextext{keyword|)}% - -\rSec2[lex.literal]{Literals}% -\indextext{literal|(} - -\rSec3[lex.literal.kinds]{Kinds of literals} - -\pnum -\indextext{constant}% -\indextext{literal!constant}% -There are several kinds of literals. -\begin{footnote} -The term ``literal'' generally designates, in this -document, those tokens that are called ``constants'' in C. -\end{footnote} - -\begin{bnf} -\nontermdef{literal}\br - integer-literal\br - character-literal\br - floating-point-literal\br - string-literal\br - boolean-literal\br - pointer-literal\br - user-defined-literal -\end{bnf} -\begin{note} -When appearing as an \grammarterm{expression}, -a literal has a type and a value category\iref{expr.prim.literal}. -\end{note} - -\rSec3[lex.icon]{Integer literals} - -\indextext{literal!integer}% -\begin{bnf} -\nontermdef{integer-literal}\br - binary-literal \opt{integer-suffix}\br - octal-literal \opt{integer-suffix}\br - decimal-literal \opt{integer-suffix}\br - hexadecimal-literal \opt{integer-suffix} -\end{bnf} - -\begin{bnf} -\nontermdef{binary-literal}\br - \terminal{0b} binary-digit\br - \terminal{0B} binary-digit\br - binary-literal \opt{\terminal{'}} binary-digit -\end{bnf} - -\begin{bnf} -\nontermdef{octal-literal}\br - \terminal{0}\br - octal-literal \opt{\terminal{'}} octal-digit -\end{bnf} - -\begin{bnf} -\nontermdef{decimal-literal}\br - nonzero-digit\br - decimal-literal \opt{\terminal{'}} digit -\end{bnf} - -\begin{bnf} -\nontermdef{hexadecimal-literal}\br - hexadecimal-prefix hexadecimal-digit-sequence -\end{bnf} - -\begin{bnf} -\nontermdef{binary-digit} \textnormal{one of}\br - \terminal{0 1} -\end{bnf} - -\begin{bnf} -\nontermdef{octal-digit} \textnormal{one of}\br - \terminal{0 1 2 3 4 5 6 7} -\end{bnf} - -\begin{bnf} -\nontermdef{nonzero-digit} \textnormal{one of}\br - \terminal{1 2 3 4 5 6 7 8 9} -\end{bnf} - -\begin{bnf} -\nontermdef{hexadecimal-prefix} \textnormal{one of}\br - \terminal{0x 0X} -\end{bnf} - -\begin{bnf} -\nontermdef{hexadecimal-digit-sequence}\br - hexadecimal-digit\br - hexadecimal-digit-sequence \opt{\terminal{'}} hexadecimal-digit -\end{bnf} - -\begin{bnf} -\nontermdef{hexadecimal-digit} \textnormal{one of}\br - \terminal{0 1 2 3 4 5 6 7 8 9}\br - \terminal{a b c d e f}\br - \terminal{A B C D E F} -\end{bnf} - -\begin{bnf} -\nontermdef{integer-suffix}\br - unsigned-suffix \opt{long-suffix} \br - unsigned-suffix \opt{long-long-suffix} \br - unsigned-suffix \opt{size-suffix} \br - long-suffix \opt{unsigned-suffix} \br - long-long-suffix \opt{unsigned-suffix} \br - size-suffix \opt{unsigned-suffix} -\end{bnf} - -\begin{bnf} -\nontermdef{unsigned-suffix} \textnormal{one of}\br - \terminal{u U} -\end{bnf} - -\begin{bnf} -\nontermdef{long-suffix} \textnormal{one of}\br - \terminal{l L} -\end{bnf} - -\begin{bnf} -\nontermdef{long-long-suffix} \textnormal{one of}\br - \terminal{ll LL} -\end{bnf} - -\begin{bnf} -\nontermdef{size-suffix} \textnormal{one of}\br - \terminal{z Z} -\end{bnf} - -\pnum -\indextext{literal!\idxcode{unsigned}}% -\indextext{literal!\idxcode{long}}% -\indextext{literal!base of integer}% -In an \grammarterm{integer-literal}, -the sequence of -\grammarterm{binary-digit}s, -\grammarterm{octal-digit}s, -\grammarterm{digit}s, or -\grammarterm{hexadecimal-digit}s -is interpreted as a base $N$ integer as shown in table \tref{lex.icon.base}; -the lexically first digit of the sequence of digits is the most significant. -\begin{note} -The prefix and any optional separating single quotes are ignored -when determining the value. -\end{note} - -\begin{simpletypetable} -{Base of \grammarterm{integer-literal}{s}} -{lex.icon.base} -{lr} -\topline -\lhdr{Kind of \grammarterm{integer-literal}} & \rhdr{base $N$} \\ \capsep -\grammarterm{binary-literal} & 2 \\ -\grammarterm{octal-literal} & 8 \\ -\grammarterm{decimal-literal} & 10 \\ -\grammarterm{hexadecimal-literal} & 16 \\ -\end{simpletypetable} - -\pnum -The \grammarterm{hexadecimal-digit}s -\tcode{a} through \tcode{f} and \tcode{A} through \tcode{F} -have decimal values ten through fifteen. -\begin{example} -The number twelve can be written \tcode{12}, \tcode{014}, -\tcode{0XC}, or \tcode{0b1100}. The \grammarterm{integer-literal}s \tcode{1048576}, -\tcode{1'048'576}, \tcode{0X100000}, \tcode{0x10'0000}, and -\tcode{0'004'000'000} all have the same value. -\end{example} - -\pnum -\indextext{literal!\idxcode{long}}% -\indextext{literal!\idxcode{unsigned}}% -\indextext{literal!integer}% -\indextext{literal!type of integer}% -\indextext{suffix!\idxcode{L}}% -\indextext{suffix!\idxcode{U}}% -\indextext{suffix!\idxcode{l}}% -\indextext{suffix!\idxcode{u}}% -The type of an \grammarterm{integer-literal} is -the first type in the list in \tref{lex.icon.type} -corresponding to its optional \grammarterm{integer-suffix} -in which its value can be represented. - -\begin{floattable}{Types of \grammarterm{integer-literal}s}{lex.icon.type}{l|l|l} -\topline -\lhdr{\grammarterm{integer-suffix}} & \chdr{\grammarterm{decimal-literal}} & \rhdr{\grammarterm{integer-literal} other than \grammarterm{decimal-literal}} \\ \capsep -none & - \tcode{int} & - \tcode{int}\\ - & - \tcode{long int} & - \tcode{unsigned int}\\ - & - \tcode{long long int} & - \tcode{long int}\\ - & - & - \tcode{unsigned long int}\\ - & - & - \tcode{long long int}\\ - & - & - \tcode{unsigned long long int}\\\hline -\tcode{u} or \tcode{U} & - \tcode{unsigned int} & - \tcode{unsigned int}\\ - & - \tcode{unsigned long int} & - \tcode{unsigned long int}\\ - & - \tcode{unsigned long long int} & - \tcode{unsigned long long int}\\\hline -\tcode{l} or \tcode{L} & - \tcode{long int} & - \tcode{long int}\\ - & - \tcode{long long int} & - \tcode{unsigned long int}\\ - & - & - \tcode{long long int}\\ - & - & - \tcode{unsigned long long int}\\\hline -Both \tcode{u} or \tcode{U} & - \tcode{unsigned long int} & - \tcode{unsigned long int}\\ -and \tcode{l} or \tcode{L} & - \tcode{unsigned long long int} & - \tcode{unsigned long long int}\\\hline -\tcode{ll} or \tcode{LL} & - \tcode{long long int} & - \tcode{long long int}\\ - & - & - \tcode{unsigned long long int}\\\hline -Both \tcode{u} or \tcode{U} & - \tcode{unsigned long long int} & - \tcode{unsigned long long int}\\ -and \tcode{ll} or \tcode{LL} & - & - \\\hline -\tcode{z} or \tcode{Z} & - the signed integer type corresponding & - the signed integer type \\ - & - \qquad to \tcode{std::size_t}\iref{support.types.layout} & - \qquad corresponding to \tcode{std::size_t} \\ - & - & - \tcode{std::size_t}\\\hline -Both \tcode{u} or \tcode{U} & - \tcode{std::size_t} & - \tcode{std::size_t} \\ -and \tcode{z} or \tcode{Z} & - & - \\ -\end{floattable} - -\pnum -Except for \grammarterm{integer-literal}{s} containing -a \grammarterm{size-suffix}, -if the value of an \grammarterm{integer-literal} -cannot be represented by any type in its list and -an extended integer type\iref{basic.fundamental} can represent its value, -it may have that extended integer type. -If all of the types in the list for the \grammarterm{integer-literal} -are signed, -the extended integer type is signed. -If all of the types in the list for the \grammarterm{integer-literal} -are unsigned, -the extended integer type is unsigned. -If the list contains both signed and unsigned types, -the extended integer type may be signed or unsigned. -If an \grammarterm{integer-literal} -cannot be represented by any of the allowed types, -the program is ill-formed. -\begin{note} -An \grammarterm{integer-literal} with a \tcode{z} or \tcode{Z} suffix -is ill-formed if it cannot be represented by \tcode{std::size_t}. -\end{note} - -\rSec3[lex.fcon]{Floating-point literals} - -\indextext{literal!floating-point}% -\begin{bnf} -\nontermdef{floating-point-literal}\br - decimal-floating-point-literal\br - hexadecimal-floating-point-literal -\end{bnf} - -\begin{bnf} -\nontermdef{decimal-floating-point-literal}\br - fractional-constant \opt{exponent-part} \opt{floating-point-suffix}\br - digit-sequence exponent-part \opt{floating-point-suffix} -\end{bnf} - -\begin{bnf} -\nontermdef{hexadecimal-floating-point-literal}\br - hexadecimal-prefix hexadecimal-fractional-constant binary-exponent-part \opt{floating-point-suffix}\br - hexadecimal-prefix hexadecimal-digit-sequence binary-exponent-part \opt{floating-point-suffix} -\end{bnf} - -\begin{bnf} -\nontermdef{fractional-constant}\br - \opt{digit-sequence} \terminal{.} digit-sequence\br - digit-sequence \terminal{.} -\end{bnf} - -\begin{bnf} -\nontermdef{hexadecimal-fractional-constant}\br - \opt{hexadecimal-digit-sequence} \terminal{.} hexadecimal-digit-sequence\br - hexadecimal-digit-sequence \terminal{.} -\end{bnf} - -\begin{bnf} -\nontermdef{exponent-part}\br - \terminal{e} \opt{sign} digit-sequence\br - \terminal{E} \opt{sign} digit-sequence -\end{bnf} - -\begin{bnf} -\nontermdef{binary-exponent-part}\br - \terminal{p} \opt{sign} digit-sequence\br - \terminal{P} \opt{sign} digit-sequence -\end{bnf} - -\begin{bnf} -\nontermdef{sign} \textnormal{one of}\br - \terminal{+ -} -\end{bnf} - -\begin{bnf} -\nontermdef{digit-sequence}\br - digit\br - digit-sequence \opt{\terminal{'}} digit -\end{bnf} - -\begin{bnf} -\nontermdef{floating-point-suffix} \textnormal{one of}\br - \terminal{f l f16 f32 f64 f128 bf16 F L F16 F32 F64 F128 BF16} -\end{bnf} - -\pnum -\indextext{literal!type of floating-point}% -\indextext{literal!\idxcode{float}}% -\indextext{suffix!\idxcode{F}}% -\indextext{suffix!\idxcode{f}}% -\indextext{suffix!\idxcode{L}}% -\indextext{suffix!\idxcode{l}}% -\indextext{literal!\idxcode{long double}}% -The type of -a \grammarterm{floating-point-literal}\iref{basic.fundamental,basic.extended.fp} -is determined by -its \grammarterm{floating-point-suffix} as specified in \tref{lex.fcon.type}. -\begin{note} -The floating-point suffixes -\tcode{f16}, \tcode{f32}, \tcode{f64}, \tcode{f128}, \tcode{bf16}, -\tcode{F16}, \tcode{F32}, \tcode{F64}, \tcode{F128}, and \tcode{BF16} -are conditionally-supported. See \ref{basic.extended.fp}. -\end{note} -\begin{simpletypetable} -{Types of \grammarterm{floating-point-literal}{s}} -{lex.fcon.type} -{ll} -\topline -\lhdr{\grammarterm{floating-point-suffix}} & \rhdr{type} \\ \capsep -none & \keyword{double} \\ -\tcode{f} or \tcode{F} & \keyword {float} \\ -\tcode{l} or \tcode{L} & \keyword{long} \keyword{double} \\ -\tcode{f16} or \tcode{F16} & \tcode{std::float16_t} \\ -\tcode{f32} or \tcode{F32} & \tcode{std::float32_t} \\ -\tcode{f64} or \tcode{F64} & \tcode{std::float64_t} \\ -\tcode{f128} or \tcode{F128} & \tcode{std::float128_t} \\ -\tcode{bf16} or \tcode{BF16} & \tcode{std::bfloat16_t} \\ -\end{simpletypetable} - -\pnum -\indextext{literal!floating-point}% -The \defn{significand} of a \grammarterm{floating-point-literal} -is the \grammarterm{fractional-constant} or \grammarterm{digit-sequence} -of a \grammarterm{decimal-floating-point-literal} -or the \grammarterm{hexadecimal-fractional-constant} -or \grammarterm{hexadecimal-digit-sequence} -of a \grammarterm{hexadecimal-floating-point-literal}. -In the significand, -the sequence of \grammarterm{digit}s or \grammarterm{hexadecimal-digit}s -and optional period are interpreted as a base $N$ real number $s$, -where $N$ is 10 for a \grammarterm{decimal-floating-point-literal} and -16 for a \grammarterm{hexadecimal-floating-point-literal}. -\begin{note} -Any optional separating single quotes are ignored when determining the value. -\end{note} -If an \grammarterm{exponent-part} or \grammarterm{binary-exponent-part} -is present, -the exponent $e$ of the \grammarterm{floating-point-literal} -is the result of interpreting -the sequence of an optional \grammarterm{sign} and the \grammarterm{digit}s -as a base 10 integer. -Otherwise, the exponent $e$ is 0. -The scaled value of the literal is -$s \times 10^e$ for a \grammarterm{decimal-floating-point-literal} and -$s \times 2^e$ for a \grammarterm{hexadecimal-floating-point-literal}. -\begin{example} -The \grammarterm{floating-point-literal}{s} -\tcode{49.625} and \tcode{0xC.68p+2} have the same value. -The \grammarterm{floating-point-literal}{s} -\tcode{1.602'176'565e-19} and \tcode{1.602176565e-19} -have the same value. -\end{example} - -\pnum -If the scaled value is not in the range of representable -values for its type, the program is ill-formed. -Otherwise, the value of a \grammarterm{floating-point-literal} -is the scaled value if representable, -else the larger or smaller representable value nearest the scaled value, -chosen in an \impldef{choice of larger or smaller value of -\grammarterm{floating-point-literal}} manner. - -\rSec3[lex.string.uneval]{Unevaluated strings} - -\begin{bnf} -\nontermdef{unevaluated-string}\br - string-literal -\end{bnf} - -\pnum -An \grammarterm{unevaluated-string} shall have no \grammarterm{encoding-prefix}. - -\pnum -Each \grammarterm{universal-character-name} and each \grammarterm{simple-escape-sequence} in an \grammarterm{unevaluated-string} is -replaced by the member of the translation character set it denotes. -An \grammarterm{unevaluated-string} that contains -a \grammarterm{numeric-escape-sequence} or -a \grammarterm{conditional-escape-sequence} -is ill-formed. - -\pnum -An \grammarterm{unevaluated-string} is never evaluated and -its interpretation depends on the context in which it appears. - -\rSec3[lex.bool]{Boolean literals} - -\indextext{literal!boolean}% -\begin{bnf} -\nontermdef{boolean-literal}\br - \terminal{false}\br - \terminal{true} -\end{bnf} - -\pnum -\indextext{Boolean literal}% -The Boolean literals are the keywords \tcode{false} and \tcode{true}. -Such literals have type \tcode{bool}. - -\rSec3[lex.nullptr]{Pointer literals} - -\indextext{literal!pointer}% -\begin{bnf} -\nontermdef{pointer-literal}\br - \terminal{nullptr} -\end{bnf} - -\pnum -The pointer literal is the keyword \keyword{nullptr}. It has type -\tcode{std::nullptr_t}. -\begin{note} -\tcode{std::nullptr_t} is a distinct type that is neither a pointer type nor a pointer-to-member type; -rather, a prvalue of this type is a null pointer constant and can be -converted to a null pointer value or null member pointer value. See~\ref{conv.ptr} -and~\ref{conv.mem}. -\end{note} - -\rSec3[lex.ext]{User-defined literals} - -\indextext{literal!user-defined}% -\begin{bnf} -\nontermdef{user-defined-literal}\br - user-defined-integer-literal\br - user-defined-floating-point-literal\br - user-defined-string-literal\br - user-defined-character-literal -\end{bnf} - -\begin{bnf} -\nontermdef{user-defined-integer-literal}\br - decimal-literal ud-suffix\br - octal-literal ud-suffix\br - hexadecimal-literal ud-suffix\br - binary-literal ud-suffix -\end{bnf} - -\begin{bnf} -\nontermdef{user-defined-floating-point-literal}\br - fractional-constant \opt{exponent-part} ud-suffix\br - digit-sequence exponent-part ud-suffix\br - hexadecimal-prefix hexadecimal-fractional-constant binary-exponent-part ud-suffix\br - hexadecimal-prefix hexadecimal-digit-sequence binary-exponent-part ud-suffix -\end{bnf} - -\begin{bnf} -\nontermdef{user-defined-string-literal}\br - string-literal ud-suffix -\end{bnf} - -\begin{bnf} -\nontermdef{user-defined-character-literal}\br - character-literal ud-suffix -\end{bnf} - -\begin{bnf} -\nontermdef{ud-suffix}\br - identifier -\end{bnf} - -\pnum -If a token matches both \grammarterm{user-defined-literal} and another \grammarterm{literal} kind, it -is treated as the latter. -\begin{example} -\tcode{123_km} -is a \grammarterm{user-defined-literal}, but \tcode{12LL} is an -\grammarterm{integer-literal}. -\end{example} -The syntactic non-terminal preceding the \grammarterm{ud-suffix} in a -\grammarterm{user-defined-literal} is taken to be the longest sequence of -characters that could match that non-terminal. - -\pnum -A \grammarterm{user-defined-literal} is treated as a call to a literal operator or -literal operator template\iref{over.literal}. -To determine the form of this call for -a given \grammarterm{user-defined-literal} \placeholder{L} -with \grammarterm{ud-suffix} \placeholder{X}, -first let \placeholder{S} be the set of declarations -found by unqualified lookup for the \grammarterm{literal-operator-id} -whose literal suffix identifier is \placeholder{X}\iref{basic.lookup.unqual}. -\placeholder{S} shall not be empty. - -\pnum -If \placeholder{L} is a \grammarterm{user-defined-integer-literal}, let \placeholder{n} be the literal -without its \grammarterm{ud-suffix}. If \placeholder{S} contains a literal operator with -parameter type \tcode{unsigned long long}, the literal \placeholder{L} is treated as a call of -the form -\begin{codeblock} -operator ""@\placeholder{X}@(@\placeholder{n}@ULL) -\end{codeblock} -Otherwise, \placeholder{S} shall contain a raw literal operator -or a numeric literal operator template\iref{over.literal} but not both. -If \placeholder{S} contains a raw literal operator, -the literal \placeholder{L} is treated as a call of the form -\begin{codeblock} -operator ""@\placeholder{X}@("@\placeholder{n}@") -\end{codeblock} -Otherwise (\placeholder{S} contains a numeric literal operator template), -\placeholder{L} is treated as a call of the form -\begin{codeblock} -operator ""@\placeholder{X}@<'@$c_1$@', '@$c_2$@', ... '@$c_k$@'>() -\end{codeblock} -where \placeholder{n} is the source character sequence $c_1c_2...c_k$. -\begin{note} -The sequence -$c_1c_2...c_k$ can only contain characters from the basic character set. -\end{note} - -\pnum -If \placeholder{L} is a \grammarterm{user-defined-floating-point-literal}, let \placeholder{f} be the -literal without its \grammarterm{ud-suffix}. If \placeholder{S} contains a literal operator -with parameter type \tcode{long double}, the literal \placeholder{L} is treated as a call of -the form -\begin{codeblock} -operator ""@\placeholder{X}@(@\placeholder{f}@L) -\end{codeblock} -Otherwise, \placeholder{S} shall contain a raw literal operator -or a numeric literal operator template\iref{over.literal} but not both. -If \placeholder{S} contains a raw literal operator, -the \grammarterm{literal} \placeholder{L} is treated as a call of the form -\begin{codeblock} -operator ""@\placeholder{X}@("@\placeholder{f}@") -\end{codeblock} -Otherwise (\placeholder{S} contains a numeric literal operator template), -\placeholder{L} is treated as a call of the form -\begin{codeblock} -operator ""@\placeholder{X}@<'@$c_1$@', '@$c_2$@', ... '@$c_k$@'>() -\end{codeblock} -where \placeholder{f} is the source character sequence $c_1c_2...c_k$. -\begin{note} -The sequence -$c_1c_2...c_k$ can only contain characters from the basic character set. -\end{note} - -\pnum -If \placeholder{L} is a \grammarterm{user-defined-string-literal}, -let \placeholder{str} be the literal without its \grammarterm{ud-suffix} -and let \placeholder{len} be the number of code units in \placeholder{str} -(i.e., its length excluding the terminating null character). -If \placeholder{S} contains a literal operator template with -a non-type template parameter for which \placeholder{str} is -a well-formed \grammarterm{template-argument}, -the literal \placeholder{L} is treated as a call of the form -\begin{codeblock} -operator ""@\placeholder{X}@<@\placeholder{str}{}@>() -\end{codeblock} -Otherwise, the literal \placeholder{L} is treated as a call of the form -\begin{codeblock} -operator ""@\placeholder{X}@(@\placeholder{str}{}@, @\placeholder{len}{}@) -\end{codeblock} - -\pnum -If \placeholder{L} is a \grammarterm{user-defined-character-literal}, let \placeholder{ch} be the -literal without its \grammarterm{ud-suffix}. -\placeholder{S} shall contain a literal operator\iref{over.literal} whose only parameter has -the type of \placeholder{ch} and the -literal \placeholder{L} is treated as a call -of the form -\begin{codeblock} -operator ""@\placeholder{X}@(@\placeholder{ch}{}@) -\end{codeblock} - -\pnum -\begin{example} -\begin{codeblock} -long double operator ""_w(long double); -std::string operator ""_w(const char16_t*, std::size_t); -unsigned operator ""_w(const char*); -int main() { - 1.2_w; // calls \tcode{operator ""_w(1.2L)} - u"one"_w; // calls \tcode{operator ""_w(u"one", 3)} - 12_w; // calls \tcode{operator ""_w("12")} - "two"_w; // error: no applicable literal operator -} -\end{codeblock} -\end{example} - -\pnum -In translation phase 6\iref{lex.phases}, adjacent \grammarterm{string-literal}s are concatenated and -\grammarterm{user-defined-string-literal}{s} are considered \grammarterm{string-literal}s for that -purpose. During concatenation, \grammarterm{ud-suffix}{es} are removed and ignored and -the concatenation process occurs as described in~\ref{lex.string}. At the end of phase -6, if a \grammarterm{string-literal} is the result of a concatenation involving at least one -\grammarterm{user-defined-string-literal}, all the participating -\grammarterm{user-defined-string-literal}{s} shall have the same \grammarterm{ud-suffix} -and that suffix is applied to the result of the concatenation. - -\pnum -\begin{example} -\begin{codeblock} -int main() { - L"A" "B" "C"_x; // OK, same as \tcode{L"ABC"_x} - "P"_x "Q" "R"_y; // error: two different \grammarterm{ud-suffix}{es} -} -\end{codeblock} -\end{example} -\indextext{literal|)}% - -\rSec1[basic.link]{Names and linkage}% -\indextext{linkage|(} - -\pnum -\indextext{type}% -\indextext{object}% -\indextext{storage class}% -\indextext{scope}% -\indextext{linkage}% -A \defn{name} is an \grammarterm{identifier}\iref{lex.name}, -\grammarterm{operator-function-id}\iref{over.oper}, -\grammarterm{literal-operator-id}\iref{over.literal}, or -\grammarterm{conversion-function-id}\iref{class.conv.fct}. - -\pnum -Two names are \defnx{the same}{name!same} if -\begin{itemize} -\item they are \grammarterm{identifier}{s} composed of the same character sequence, or -\item they are \grammarterm{operator-function-id}{s} formed with the same operator, or -\item they are \grammarterm{literal-operator-id}{s} formed with the same -literal suffix identifier, or -\item they are \grammarterm{conversion-function-id}{s} formed with -equivalent\iref{temp.over.link} types. -\end{itemize} - -\pnum -Every name is introduced by a \defn{declaration}, which is a -\begin{itemize} -\item -\grammarterm{name-declaration}, -\grammarterm{block-declaration}, or -\grammarterm{member-declaration}\iref{dcl.pre,class.mem}, -\item -\grammarterm{init-capture}\iref{expr.prim.lambda.capture}, -\item -\grammarterm{condition} with a \grammarterm{declarator}\iref{stmt.pre}, -\item -\grammarterm{exception-declaration}\iref{except.pre}, -\item -\grammarterm{elaborated-type-specifier} -that introduces a name\iref{dcl.type.elab}, -\item -\grammarterm{init-declarator}\iref{dcl.decl}, -\item -\grammarterm{parameter-declaration}\iref{dcl.fct}, -\item -\grammarterm{identifier} -in a structured binding declaration\iref{dcl.struct.bind}, -\item -\grammarterm{enum-specifier} or -\grammarterm{enumerator-definition}\iref{dcl.enum}, -\item -\grammarterm{using-declarator}\iref{namespace.udecl}, -\item -\grammarterm{class-specifier}\iref{class.pre}, -\item -implicit declaration of an injected-class-name\iref{class.pre}, -\item -\grammarterm{member-declarator}\iref{class.mem}, or -\item -\grammarterm{type-parameter}\iref{temp.param}. -\end{itemize} -\begin{note} -The interpretation of a \grammarterm{for-range-declaration} produces -one or more of the above\iref{stmt.ranged}. -\end{note} - -\pnum -An \defn{entity} is a value, object, reference, structured binding, function, -enumerator, type, class member, bit-field, template, template specialization, -namespace, or pack. An entity $E$ is denoted by the name (if any) that is -introduced by a declaration of $E$ or by a \grammarterm{typedef-name} -introduced by a declaration specifying $E$. - -\pnum -Some names denote types or templates. In general, whenever a name is -encountered it is necessary to determine whether that name denotes one of these -entities before continuing to parse the program that contains it. The process -that determines this is called -\defnx{name lookup}{lookup!name}\iref{basic.lookup}. - -\pnum -A \defn{variable} is introduced by the -declaration of -a reference other than a non-static data member or of -an object. The variable's name, if any, denotes the reference or object. - -\pnum -A name can have -\defnadj{external}{linkage}, -\defnadj{module}{linkage}, -\defnadj{internal}{linkage}, or -\defnadj{no}{linkage}, -as determined by the rules below. -\begin{note} -All declarations of an entity with a name with internal linkage -appear in the same translation unit. -All declarations of an entity with module linkage -are attached to the same module. -\end{note} - -\pnum -\indextext{linkage!\idxcode{static} and}% -\indextext{\idxcode{static}!linkage of}% -\indextext{linkage!\idxcode{const} and}% -\indextext{\idxcode{const}!linkage of}% -\indextext{linkage!\idxcode{inline} and}% -\indextext{\idxcode{inline}!linkage of}% -The name of an entity -that belongs to a namespace scope\iref{basic.scope.namespace} -has internal linkage if it is the name of -\begin{itemize} -\item - a variable, variable template, function, or function template that is - explicitly declared \keyword{static}; or -\item - a non-template variable of non-volatile const-qualified type, unless - \begin{itemize} - \item it is declared in the purview of a module interface unit - (outside the \grammarterm{private-module-fragment}, if any) or - module partition, or - \item it is explicitly declared \keyword{extern}, or - \item it is inline, or - \item it was previously declared and the prior declaration did - not have internal linkage; or - \end{itemize} -\item - a data member of an anonymous union. -\end{itemize} -\begin{note} -An instantiated variable template that has const-qualified type -can have external or module linkage, even if not declared \keyword{extern}. -\end{note} - -\pnum -An unnamed namespace or a namespace declared directly or indirectly within an -unnamed namespace has internal linkage. All other namespaces have external linkage. -The name of an entity that belongs to a namespace scope -that has not been given internal linkage above -and that is the name of -\begin{itemize} -\item a variable; or -\item a function; or -\item -\indextext{class!linkage of}% -a named class\iref{class.pre}, or an unnamed class defined in a -typedef declaration in which the class has the typedef name for linkage -purposes\iref{dcl.typedef}; or -\item -\indextext{enumeration!linkage of}% -a named enumeration\iref{dcl.enum}, or an unnamed enumeration defined -in a typedef declaration in which the enumeration has the typedef name -for linkage purposes\iref{dcl.typedef}; or -\item an unnamed enumeration -that has an enumerator as a name for linkage purposes\iref{dcl.enum}; or -\item a template -\end{itemize} -has its linkage determined as follows: -\begin{itemize} -\item -\indextext{friend function!linkage of}% -if the entity is a function or function template -first declared in a friend declaration and -that declaration is a definition and -the enclosing class is defined within an \grammarterm{export-declaration}, -the name has the same linkage, if any, -as the name of the enclosing class\iref{class.friend}; -\item -otherwise, -\indextext{friend function!linkage of}% -if the entity is a function or function template -declared in a friend declaration and -a corresponding non-friend declaration is reachable, -%FIXME: Which declaration is "that prior declaration"? -%FIXME: "prior" with respect to what? And what about dependent lookup? -the name has the linkage determined from that prior declaration, -\item -otherwise, -if the enclosing namespace has internal linkage, -the name has internal linkage; -\item -otherwise, -if the declaration of the name is -attached to a named module\iref{module.unit} -and is not exported\iref{module.interface}, -the name has module linkage; -\item -otherwise, -the name has external linkage. -\end{itemize} - -\pnum -In addition, -a member function, -a static data member, -a named class or enumeration that inhabits a class scope, or -an unnamed class or enumeration defined in a typedef declaration -that inhabits a class scope -such that the class or enumeration -has the typedef name for linkage purposes\iref{dcl.typedef}, -has the same linkage, if any, as the name of the class of which it is a member. - -\pnum -\begin{example} -\begin{codeblock} -static void f(); -extern "C" void h(); -static int i = 0; // \#1 -void q() { - extern void f(); // internal linkage - extern void g(); // \tcode{::g}, external linkage - extern void h(); // C language linkage - int i; // \#2: \tcode{i} has no linkage - { - extern void f(); // internal linkage - extern int i; // \#3: internal linkage - } -} -\end{codeblock} -Even though the declaration at line \#2 hides the declaration at line \#1, -the declaration at line \#3 still redeclares \#1 and receives internal linkage. -\end{example} - -\pnum -\indextext{linkage!no}% -Names not covered by these rules have no linkage. Moreover, except as -noted, a name declared at block scope\iref{basic.scope.block} has no -linkage. - -\pnum -\indextext{translation unit!name and}% -\indextext{linkage}% -A name used in more than one translation unit can potentially -refer to the same entity in these translation units depending on the -linkage of the name specified in each translation unit. - -\pnum -Two declarations of entities declare the same entity -if, considering declarations of unnamed types to introduce their names -for linkage purposes, if any\iref{dcl.typedef,dcl.enum}, -they correspond\iref{basic.scope.scope}, -have the same target scope that is not a function or template parameter scope, -neither is a name-independent declaration, -and either -\begin{itemize} -\item -they appear in the same translation unit, or -\item -they both declare names with module linkage and are attached to the same module, or -\item -they both declare names with external linkage. -\end{itemize} -\begin{note} -There are other circumstances in which declarations declare the same entity% -\iref{dcl.link,temp.type,temp.spec.partial}. -\end{note} - -\pnum -If a declaration $H$ that declares a name with internal linkage -precedes a declaration $D$ in another translation unit $U$ and -would declare the same entity as $D$ if it appeared in $U$, -the program is ill-formed. -\begin{note} -Such an $H$ can appear only in a header unit. -\end{note} - -\pnum -If two declarations of an entity are -attached to different modules, the program is ill-formed; -no diagnostic is required if neither is reachable from the other. -\begin{example} -\begin{codeblocktu}{\tcode{"decls.h"}} -int f(); // \#1, attached to the global module -int g(); // \#2, attached to the global module -\end{codeblocktu} - -\begin{codeblocktu}{Module interface of \tcode{M}} -module; -#include "decls.h" -export module M; -export using ::f; // OK, does not declare an entity, exports \#1 -int g(); // error: matches \#2, but attached to \tcode{M} -export int h(); // \#3 -export int k(); // \#4 -\end{codeblocktu} - -\begin{codeblocktu}{Other translation unit} -import M; -static int h(); // error: matches \#3 -int k(); // error: matches \#4 -\end{codeblocktu} -\end{example} -As a consequence of these rules, -all declarations of an entity are attached to the same module; -the entity is said to be \defnx{attached}{attached!entity} to that module. - -\pnum -\indextext{consistency!type declaration}% -\indextext{declaration!multiple}% -For any two declarations of an entity $E$: -\begin{itemize} -\item -If one declares $E$ to be a variable or function, -the other shall declare $E$ as one of the same type. -\item -If one declares $E$ to be an enumerator, the other shall do so. -\item -If one declares $E$ to be a namespace, the other shall do so. -\item -If one declares $E$ to be a type, -the other shall declare $E$ to be a type of the same kind\iref{dcl.type.elab}. -\item -If one declares $E$ to be a class template, -the other shall do so with the same kind and -an equivalent \grammarterm{template-head}\iref{temp.over.link}. -\begin{note} -The declarations can supply different default template arguments. -\end{note} -\item -If one declares $E$ to be a function template or -a (partial specialization of a) variable template, -the other shall declare $E$ to be one -with an equivalent \grammarterm{template-head} and type. -\item -If one declares $E$ to be an alias template, -the other shall declare $E$ to be one with -an equivalent \grammarterm{template-head} and \grammarterm{defining-type-id}. -\item -If one declares $E$ to be a concept, the other shall do so. -\end{itemize} -Types are compared after all adjustments of types (during which -typedefs\iref{dcl.typedef} are replaced by their definitions); -declarations for an array -object can specify array types that differ by the presence or absence of -a major array bound\iref{dcl.array}. -No diagnostic is required if neither declaration is reachable from the other. -\begin{example} -\begin{codeblock} -int f(int x, int x); // error: different entities for \tcode{x} -void g(); // \#1 -void g(int); // OK, different entity from \#1 -int g(); // error: same entity as \#1 with different type -void h(); // \#2 -namespace h {} // error: same entity as \#2, but not a function -\end{codeblock} -\end{example} - -\pnum -\begin{note} -Linkage to non-\Cpp{} declarations can be achieved using a -\grammarterm{linkage-specification}\iref{dcl.link}. -\end{note} -\indextext{linkage|)} - -\pnum -A declaration $D$ \defnx{names}{name} an entity $E$ if -\begin{itemize} -\item -$D$ contains a \grammarterm{lambda-expression} whose closure type is $E$, -\item -$E$ is not a function or function template and $D$ contains an -\grammarterm{id-expression}, -\grammarterm{type-specifier}, -\grammarterm{nested-name-specifier}, -\grammarterm{template-name}, or -\grammarterm{concept-name} -denoting $E$, or -\item -$E$ is a function or function template and -$D$ contains an expression that names $E$\iref{basic.def.odr} or -an \grammarterm{id-expression} -that refers to a set of overloads that contains $E$. -\begin{note} -Non-dependent names in an instantiated declaration -do not refer to a set of overloads\iref{temp.res}. -\end{note} -\end{itemize} - -\pnum -A declaration is an \defn{exposure} -if it either names a TU-local entity (defined below), ignoring -\begin{itemize} -\item -the \grammarterm{function-body} -for a non-inline function or function template -(but not the deduced return type -for a (possibly instantiated) definition of a function -with a declared return type that uses a placeholder type\iref{dcl.spec.auto}), -\item -the \grammarterm{initializer} -for a variable or variable template (but not the variable's type), -\item -friend declarations in a class definition, and -\item -any reference to a non-volatile const object or reference -with internal or no linkage initialized with a constant expression -that is not an odr-use\iref{term.odr.use}, -\end{itemize} -or defines a constexpr variable initialized to a TU-local value (defined below). -\begin{note} -An inline function template can be an exposure even though -certain explicit specializations of it would be usable in other translation units. -\end{note} - -\pnum -An entity is \defnx{TU-local}{TU-local!entity} if it is -\begin{itemize} -\item -a type, function, variable, or template that -\begin{itemize} -\item -has a name with internal linkage, or -\item -does not have a name with linkage and is declared, -or introduced by a \grammarterm{lambda-expression}, -within the definition of a TU-local entity, -\end{itemize} -\item -a type with no name that is defined outside a -\grammarterm{class-specifier}, -function body, or -\grammarterm{initializer} -or is introduced by a \grammarterm{defining-type-specifier} -that is used to declare only TU-local entities, -\item -a specialization of a TU-local template, -\item -a specialization of a template with any TU-local template argument, or -\item -a specialization of a template -whose (possibly instantiated) declaration is an exposure. -\begin{note} -A specialization can be produced by implicit or explicit instantiation. -\end{note} -\end{itemize} - -\pnum -A value or object is \defnx{TU-local}{TU-local!value or object} if either -\begin{itemize} -\item -it is, or is a pointer to, -a TU-local function or the object associated with a TU-local variable, or -\item -it is an object of class or array type and -any of its subobjects or -any of the objects or functions -to which its non-static data members of reference type refer -is TU-local and is usable in constant expressions. -\end{itemize} - -\pnum -If a (possibly instantiated) declaration of, or a deduction guide for, -a non-TU-local entity in a module interface unit -(outside the \grammarterm{private-module-fragment}, if any) or -module partition\iref{module.unit} is an exposure, -the program is ill-formed. -Such a declaration in any other context is deprecated\iref{depr.local}. - -\pnum -If a declaration that appears in one translation unit -names a TU-local entity declared -in another translation unit that is not a header unit, -the program is ill-formed. -A declaration instantiated for a template specialization\iref{temp.spec} -appears at the point of instantiation of the specialization\iref{temp.point}. - -\pnum -\begin{example} -\begin{codeblocktu}{Translation unit \#1} -export module A; -static void f() {} -inline void it() { f(); } // error: is an exposure of \tcode{f} -static inline void its() { f(); } // OK -template void g() { its(); } // OK -template void g<0>(); - -decltype(f) *fp; // error: \tcode{f} (though not its type) is TU-local -auto &fr = f; // OK -constexpr auto &fr2 = fr; // error: is an exposure of \tcode{f} -constexpr static auto fp2 = fr; // OK - -struct S { void (&ref)(); } s{f}; // OK, value is TU-local -constexpr extern struct W { S &s; } wrap{s}; // OK, value is not TU-local - -static auto x = []{f();}; // OK -auto x2 = x; // error: the closure type is TU-local -int y = ([]{f();}(),0); // error: the closure type is not TU-local -int y2 = (x,0); // OK - -namespace N { - struct A {}; - void adl(A); - static void adl(int); -} -void adl(double); - -inline void h(auto x) { adl(x); } // OK, but certain specializations are exposures -\end{codeblocktu} -\begin{codeblocktu}{Translation unit \#2} -module A; -void other() { - g<0>(); // OK, specialization is explicitly instantiated - g<1>(); // error: instantiation uses TU-local \tcode{its} - h(N::A{}); // error: overload set contains TU-local \tcode{N::adl(int)} - h(0); // OK, calls \tcode{adl(double)} - adl(N::A{}); // OK; \tcode{N::adl(int)} not found, calls \tcode{N::adl(N::A)} - fr(); // OK, calls \tcode{f} - constexpr auto ptr = fr; // error: \tcode{fr} is not usable in constant expressions here -} -\end{codeblocktu} -\end{example} - -\rSec1[basic.exec]{Program execution} - -\rSec2[intro.execution]{Sequential execution} -\indextext{program execution|(} - -\pnum -An instance of each object with automatic storage -duration\iref{basic.stc.auto} is associated with each entry into its -block\iref{defns.block.stmt}. Such an object exists and retains its last-stored value during -the execution of the block and while the block is suspended (by a call -of a function, suspension of a coroutine\iref{expr.await}, or receipt of a signal). - -\pnum -A \defn{constituent expression} is defined as follows: -\begin{itemize} -\item -The constituent expression of an expression is that expression. -\item -The constituent expression of a conversion is -the corresponding implicit function call, if any, or -the converted expression otherwise. -\item -The constituent expressions of a \grammarterm{braced-init-list} or -of a (possibly parenthesized) \grammarterm{expression-list} -are the constituent expressions of the elements of the respective list. -\item -The constituent expressions of a \grammarterm{brace-or-equal-initializer} -of the form \tcode{=}~\grammarterm{initializer-clause} -are the constituent expressions of the \grammarterm{initializer-clause}. -\end{itemize} -\begin{example} -\begin{codeblock} -struct A { int x; }; -struct B { int y; struct A a; }; -B b = { 5, { 1+1 } }; -\end{codeblock} -The constituent expressions of the \grammarterm{initializer} -used for the initialization of \tcode{b} are \tcode{5} and \tcode{1+1}. -\end{example} - -\pnum -The \defnx{immediate subexpressions}{immediate subexpression} of an expression $E$ are -\begin{itemize} -\item -the constituent expressions of $E$'s operands\iref{expr.prop}, -\item -any function call that $E$ implicitly invokes, -\item -if $E$ is a \grammarterm{lambda-expression}\iref{expr.prim.lambda}, -the initialization of the entities captured by copy and -the constituent expressions of the \grammarterm{initializer} of the \grammarterm{init-capture}{s}, -\item -if $E$ is a function call\iref{expr.call} or implicitly invokes a function, -the constituent expressions of each default argument\iref{dcl.fct.default} -used in the call, or -\item -if $E$ creates an aggregate object\iref{dcl.init.aggr}, -the constituent expressions of each default member initializer\iref{class.mem} -used in the initialization. -\end{itemize} - -\pnum -A \defn{subexpression} of an expression $E$ is -an immediate subexpression of $E$ or -a subexpression of an immediate subexpression of $E$. -\begin{note} -Expressions appearing in the \grammarterm{compound-statement} of a \grammarterm{lambda-expression} -are not subexpressions of the \grammarterm{lambda-expression}. -\end{note} -The \defnadjx{potentially-evaluated}{subexpressions}{subexpression} of -an expression, conversion, or \grammarterm{initializer} $E$ are -\begin{itemize} -\item -the constituent expressions of $E$ and -\item -the subexpressions thereof that -are not subexpressions of a nested unevaluated operand\iref{term.unevaluated.operand}. -\end{itemize} - -\pnum -A \defn{full-expression} is -\begin{itemize} -\item -an unevaluated operand\iref{expr.context}, -\item -a \grammarterm{constant-expression}\iref{expr.const}, -\item -an immediate invocation\iref{expr.const}, -\item -an \grammarterm{init-declarator}\iref{dcl.decl} -(including such introduced by a structured binding\iref{dcl.struct.bind}) or -a \grammarterm{mem-initializer}\iref{class.base.init}, -including the constituent expressions of the initializer, -\item -an invocation of a destructor generated at the end of the lifetime -of an object other than a temporary object\iref{class.temporary} -whose lifetime has not been extended, or -\item -an expression that is not a subexpression of another expression and -that is not otherwise part of a full-expression. -\end{itemize} -If a language construct is defined to produce an implicit call of a function, -a use of the language construct is considered to be an expression -for the purposes of this definition. -Conversions applied to the result of an expression in order to satisfy the requirements -of the language construct in which the expression appears -are also considered to be part of the full-expression. -For an initializer, performing the initialization of the entity -(including evaluating default member initializers of an aggregate) -is also considered part of the full-expression. -\begin{example} -\begin{codeblock} -struct S { - S(int i): I(i) { } // full-expression is initialization of \tcode{I} - int& v() { return I; } - ~S() noexcept(false) { } -private: - int I; -}; - -S s1(1); // full-expression comprises call of \tcode{S::S(int)} -void f() { - S s2 = 2; // full-expression comprises call of \tcode{S::S(int)} - if (S(3).v()) // full-expression includes lvalue-to-rvalue and \tcode{int} to \tcode{bool} conversions, - // performed before temporary is deleted at end of full-expression - { } - bool b = noexcept(S(4)); // exception specification of destructor of \tcode{S} considered for \keyword{noexcept} - - // full-expression is destruction of \tcode{s2} at end of block -} -struct B { - B(S = S(0)); -}; -B b[2] = { B(), B() }; // full-expression is the entire initialization - // including the destruction of temporaries -\end{codeblock} -\end{example} - -\pnum -\begin{note} -The evaluation of a full-expression can include the -evaluation of subexpressions that are not lexically part of the -full-expression. For example, subexpressions involved in evaluating -default arguments\iref{dcl.fct.default} are considered to -be created in the expression that calls the function, not the expression -that defines the default argument. -\end{note} - -\pnum -\indextext{value computation|(}% -Reading an object designated by a \keyword{volatile} -glvalue\iref{basic.lval}, modifying an object, calling a library I/O -function, or calling a function that does any of those operations are -all -\defn{side effects}, which are changes in the state of the execution -environment. \defnx{Evaluation}{evaluation} 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 volatile 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 \keyword{volatile} access -may not have completed yet. - -\pnum -\defnx{Sequenced before}{sequenced before} is an asymmetric, transitive, pair-wise relation between -evaluations executed by a single thread\iref{intro.multithread}, which induces -a partial order among those evaluations. Given any two evaluations \placeholder{A} and -\placeholder{B}, if \placeholder{A} is sequenced before \placeholder{B} -(or, equivalently, \placeholder{B} is \defn{sequenced after} \placeholder{A}), -then the execution of -\placeholder{A} shall precede the execution of \placeholder{B}. If \placeholder{A} is not sequenced -before \placeholder{B} and \placeholder{B} is not sequenced before \placeholder{A}, then \placeholder{A} and -\placeholder{B} are \defn{unsequenced}. -\begin{note} -The execution of unsequenced -evaluations can overlap. -\end{note} -Evaluations \placeholder{A} and \placeholder{B} are -\defn{indeterminately sequenced} when either \placeholder{A} is sequenced before -\placeholder{B} or \placeholder{B} is sequenced before \placeholder{A}, but it is unspecified which. -\begin{note} -Indeterminately sequenced evaluations cannot overlap, but either -can be executed first. -\end{note} -An expression \placeholder{X} -is said to be sequenced before -an expression \placeholder{Y} if -every value computation and every side effect -associated with the expression \placeholder{X} -is sequenced before -every value computation and every side effect -associated with the expression \placeholder{Y}. - -\pnum -Every -\indextext{value computation}% -value computation and -\indextext{side effects}% -side effect associated with a full-expression is -sequenced before every value computation and side effect associated with the -next full-expression to be evaluated. -\begin{footnote} -As specified -in~\ref{class.temporary}, after a full-expression is evaluated, a sequence of -zero or more invocations of destructor functions for temporary objects takes -place, usually in reverse order of the construction of each temporary object. -\end{footnote} - -\pnum -\indextext{evaluation!unspecified order of}% -Except where noted, evaluations of operands of individual operators and -of subexpressions of individual expressions are unsequenced. -\begin{note} -In an expression that is evaluated more than once during the execution -of a program, unsequenced and indeterminately sequenced evaluations of -its subexpressions need not be performed consistently in different -evaluations. -\end{note} -The value computations of the operands of an -operator are sequenced before the value computation of the result of the -operator. If a -\indextext{side effects}% -side effect on a memory location\iref{intro.memory} is unsequenced -relative to either another side effect on the same memory location or -a value computation using the value of any object in the same memory location, -and they are not potentially concurrent\iref{intro.multithread}, -the behavior is undefined. -\begin{note} -The next subclause imposes similar, but more complex restrictions on -potentially concurrent computations. -\end{note} - -\begin{example} -\begin{codeblock} -void g(int i) { - i = 7, i++, i++; // \tcode{i} becomes \tcode{9} - - i = i++ + 1; // the value of \tcode{i} is incremented - i = i++ + i; // undefined behavior - i = i + 1; // the value of \tcode{i} is incremented -} -\end{codeblock} -\end{example} - -\pnum -When invoking a function (whether or not the function is inline), -every argument expression and -the postfix expression designating the called function -are sequenced before every expression or statement -in the body of the called function. -For each function invocation or -evaluation of an \grammarterm{await-expression} \placeholder{F}, -each evaluation that does not occur within \placeholder{F} but -is evaluated on the same thread and as part of the same signal handler (if any) -is either sequenced before all evaluations that occur within \placeholder{F} -or sequenced after all evaluations that occur within \placeholder{F}; -\begin{footnote} -In other words, -function executions do not interleave with each other. -\end{footnote} -if \placeholder{F} invokes or resumes a coroutine\iref{expr.await}, -only evaluations -subsequent to the previous suspension (if any) and -prior to the next suspension (if any) -are considered to occur within \placeholder{F}. - -Several contexts in \Cpp{} cause evaluation of a function call, even -though no corresponding function call syntax appears in the translation -unit. -\begin{example} -Evaluation of a \grammarterm{new-expression} invokes one or more allocation -and constructor functions; see~\ref{expr.new}. For another example, -invocation of a conversion function\iref{class.conv.fct} can arise in -contexts in which no function call syntax appears. -\end{example} -The sequencing constraints on the execution of the called function (as -described above) are features of the function calls as evaluated, -regardless of the syntax of the expression that calls the function.% -\indextext{value computation|)}% - -\indextext{behavior!on receipt of signal}% -\indextext{signal}% -\pnum -If a signal handler is executed as a result of a call to the \tcode{std::raise} -function, then the execution of the handler is sequenced after the invocation -of the \tcode{std::raise} function and before its return. -\begin{note} -When a signal is received for another reason, the execution of the -signal handler is usually unsequenced with respect to the rest of the program. -\end{note} - -\rSec2[intro.multithread]{Multi-threaded executions and data races} - -\rSec3[intro.multithread.general]{General} - -\pnum -\indextext{threads!multiple|(}% -\indextext{atomic!operation|(}% -A \defn{thread of execution} (also known as a \defn{thread}) is a single flow of -control within a program, including the initial invocation of a specific -top-level function, and recursively including every function invocation -subsequently executed by the thread. -\begin{note} -When one thread creates another, -the initial call to the top-level function of the new thread is executed by the -new thread, not by the creating thread. -\end{note} -Every thread in a program can -potentially access every object and function in a program. -\begin{footnote} -An object -with automatic or thread storage duration\iref{basic.stc} is associated with -one specific thread, and can be accessed by a different thread only indirectly -through a pointer or reference\iref{basic.compound}. -\end{footnote} -Under a hosted -implementation, a \Cpp{} program can have more than one thread running -concurrently. The execution of each thread proceeds as defined by the remainder -of this document. The execution of the entire program consists of an execution -of all of its threads. -\begin{note} -Usually the execution can be viewed as an -interleaving of all its threads. However, some kinds of atomic operations, for -example, allow executions inconsistent with a simple interleaving, as described -below. -\end{note} -\indextext{implementation!freestanding}% -Under a freestanding implementation, it is \impldef{number of -threads in a program under a freestanding implementation} whether a program can -have more than one thread of execution. +Each \grammarterm{universal-character-name} and each \grammarterm{simple-escape-sequence} in an \grammarterm{unevaluated-string} is +replaced by the member of the translation character set it denotes. +An \grammarterm{unevaluated-string} that contains +a \grammarterm{numeric-escape-sequence} or +a \grammarterm{conditional-escape-sequence} +is ill-formed. \pnum -For a signal handler that is not executed as a result of a call to the -\tcode{std::raise} function, it is unspecified which thread of execution -contains the signal handler invocation. +An \grammarterm{unevaluated-string} is never evaluated and +its interpretation depends on the context in which it appears. -\rSec3[intro.races]{Data races} +\rSec3[lex.bool]{Boolean literals} -\pnum -The value of an object visible to a thread $T$ at a particular point is the -initial value of the object, a value assigned to the object by $T$, or a -value assigned to the object by another thread, according to the rules below. -\begin{note} -In some cases, there might instead be undefined behavior. Much of this -subclause is motivated by the desire to support atomic operations with explicit -and detailed visibility constraints. However, it also implicitly supports a -simpler view for more restricted programs. -\end{note} +\indextext{literal!boolean}% +\begin{bnf} +\nontermdef{boolean-literal}\br + \terminal{false}\br + \terminal{true} +\end{bnf} \pnum -Two expression evaluations \defn{conflict} if one of them modifies a memory -location\iref{intro.memory} and the other one reads or modifies the same -memory location. +\indextext{Boolean literal}% +The Boolean literals are the keywords \tcode{false} and \tcode{true}. +Such literals have type \tcode{bool}. -\pnum -The library defines a number of atomic operations\iref{atomics} and -operations on mutexes\iref{thread} that are specially identified as -synchronization operations. These operations play a special role in making -assignments in one thread visible to another. A synchronization operation on one -or more memory locations is either a consume operation, an acquire operation, a -release operation, or both an acquire and release operation. A synchronization -operation without an associated memory location is a fence and can be either an -acquire fence, a release fence, or both an acquire and release fence. In -addition, there are relaxed atomic operations, which are not synchronization -operations, and atomic read-modify-write operations, which have special -characteristics. -\begin{note} -For example, a call that acquires a mutex will -perform an acquire operation on the locations comprising the mutex. -Correspondingly, a call that releases the same mutex will perform a release -operation on those same locations. Informally, performing a release operation on -$A$ forces prior -\indextext{side effects}% -side effects on other memory locations to become visible -to other threads that later perform a consume or an acquire operation on -$A$. ``Relaxed'' atomic operations are not synchronization operations even -though, like synchronization operations, they cannot contribute to data races. -\end{note} +\rSec3[lex.nullptr]{Pointer literals} + +\indextext{literal!pointer}% +\begin{bnf} +\nontermdef{pointer-literal}\br + \terminal{nullptr} +\end{bnf} \pnum -All modifications to a particular atomic object $M$ occur in some -particular total order, called the \defn{modification order} of $M$. +The pointer literal is the keyword \keyword{nullptr}. It has type +\tcode{std::nullptr_t}. \begin{note} -There is a separate order for each -atomic object. There is no requirement that these can be combined into a single -total order for all objects. In general this will be impossible since different -threads can observe modifications to different objects in inconsistent orders. +\tcode{std::nullptr_t} is a distinct type that is neither a pointer type nor a pointer-to-member type; +rather, a prvalue of this type is a null pointer constant and can be +converted to a null pointer value or null member pointer value. See~\ref{conv.ptr} +and~\ref{conv.mem}. \end{note} -\pnum -A \defn{release sequence} headed -by a release operation $A$ on an atomic object $M$ -is a maximal contiguous sub-sequence of -\indextext{side effects}% -side effects in the modification order of $M$, -where the first operation is $A$, and -every subsequent operation is an atomic read-modify-write operation. +\rSec3[lex.ext]{User-defined literals} -\pnum -Certain library calls \defn{synchronize with} other library calls performed by -another thread. For example, an atomic store-release synchronizes with a -load-acquire that takes its value from the store\iref{atomics.order}. -\begin{note} -Except in the specified cases, reading a later value does not -necessarily ensure visibility as described below. Such a requirement would -sometimes interfere with efficient implementation. -\end{note} -\begin{note} -The -specifications of the synchronization operations define when one reads the value -written by another. For atomic objects, the definition is clear. All operations -on a given mutex occur in a single total order. Each mutex acquisition ``reads -the value written'' by the last mutex release. -\end{note} +\indextext{literal!user-defined}% +\begin{bnf} +\nontermdef{user-defined-literal}\br + user-defined-integer-literal\br + user-defined-floating-point-literal\br + user-defined-string-literal\br + user-defined-character-literal +\end{bnf} -\pnum -An evaluation $A$ \defn{carries a dependency} to an evaluation $B$ if -\begin{itemize} -\item -the value of $A$ is used as an operand of $B$, unless: -\begin{itemize} -\item -$B$ is an invocation of any specialization of -\tcode{std::kill_dependency}\iref{atomics.order}, or -\item -$A$ is the left operand of a built-in logical \logop{and} (\tcode{\&\&}, -see~\ref{expr.log.and}) or logical \logop{or} (\tcode{||}, see~\ref{expr.log.or}) -operator, or -\item -$A$ is the left operand of a conditional (\tcode{?:}, see~\ref{expr.cond}) -operator, or -\item -$A$ is the left operand of the built-in comma (\tcode{,}) -operator\iref{expr.comma}; \end{itemize} or -\item -$A$ writes a scalar object or bit-field $M$, $B$ reads the value -written by $A$ from $M$, and $A$ is sequenced before $B$, or -\item -for some evaluation $X$, $A$ carries a dependency to $X$, and -$X$ carries a dependency to $B$. -\end{itemize} -\begin{note} -``Carries a dependency to'' is a subset of ``is sequenced before'', -and is similarly strictly intra-thread. -\end{note} +\begin{bnf} +\nontermdef{user-defined-integer-literal}\br + decimal-literal ud-suffix\br + octal-literal ud-suffix\br + hexadecimal-literal ud-suffix\br + binary-literal ud-suffix +\end{bnf} -\pnum -An evaluation $A$ is \defn{dependency-ordered before} an evaluation -$B$ if -\begin{itemize} -\item -$A$ performs a release operation on an atomic object $M$, and, in -another thread, $B$ performs a consume operation on $M$ and reads -the value written by $A$, or +\begin{bnf} +\nontermdef{user-defined-floating-point-literal}\br + fractional-constant \opt{exponent-part} ud-suffix\br + digit-sequence exponent-part ud-suffix\br + hexadecimal-prefix hexadecimal-fractional-constant binary-exponent-part ud-suffix\br + hexadecimal-prefix hexadecimal-digit-sequence binary-exponent-part ud-suffix +\end{bnf} -\item -for some evaluation $X$, $A$ is dependency-ordered before $X$ and -$X$ carries a dependency to $B$. +\begin{bnf} +\nontermdef{user-defined-string-literal}\br + string-literal ud-suffix +\end{bnf} -\end{itemize} -\begin{note} -The relation ``is dependency-ordered before'' is analogous to -``synchronizes with'', but uses release/consume in place of release/acquire. -\end{note} +\begin{bnf} +\nontermdef{user-defined-character-literal}\br + character-literal ud-suffix +\end{bnf} -\pnum -An evaluation $A$ \defn{inter-thread happens before} an evaluation $B$ -if -\begin{itemize} -\item - $A$ synchronizes with $B$, or -\item - $A$ is dependency-ordered before $B$, or -\item - for some evaluation $X$ - \begin{itemize} - \item - $A$ synchronizes with $X$ and $X$ - is sequenced before $B$, or - \item - $A$ is sequenced before $X$ and $X$ - inter-thread happens before $B$, or - \item - $A$ inter-thread happens before $X$ and $X$ - inter-thread happens before $B$. - \end{itemize} -\end{itemize} -\begin{note} -The ``inter-thread happens before'' relation describes arbitrary -concatenations of ``sequenced before'', ``synchronizes with'' and -``dependency-ordered before'' relationships, with two exceptions. The first -exception is that a concatenation never ends with -``dependency-ordered before'' followed by ``sequenced before''. The reason for -this limitation is that a consume operation participating in a -``dependency-ordered before'' relationship provides ordering only with respect -to operations to which this consume operation actually carries a dependency. The -reason that this limitation applies only to the end of such a concatenation is -that any subsequent release operation will provide the required ordering for a -prior consume operation. The second exception is that a concatenation never -consist entirely of ``sequenced before''. The reasons for this -limitation are (1) to permit ``inter-thread happens before'' to be transitively -closed and (2) the ``happens before'' relation, defined below, provides for -relationships consisting entirely of ``sequenced before''. -\end{note} +\begin{bnf} +\nontermdef{ud-suffix}\br + identifier +\end{bnf} \pnum -An evaluation $A$ \defn{happens before} an evaluation $B$ -(or, equivalently, $B$ \defn{happens after} $A$) if -\begin{itemize} -\item $A$ is sequenced before $B$, or -\item $A$ inter-thread happens before $B$. -\end{itemize} -The implementation shall ensure that no program execution demonstrates a cycle -in the ``happens before'' relation. -\begin{note} -This cycle would otherwise be -possible only through the use of consume operations. -\end{note} +If a token matches both \grammarterm{user-defined-literal} and another \grammarterm{literal} kind, it +is treated as the latter. +\begin{example} +\tcode{123_km} +is a \grammarterm{user-defined-literal}, but \tcode{12LL} is an +\grammarterm{integer-literal}. +\end{example} +The syntactic non-terminal preceding the \grammarterm{ud-suffix} in a +\grammarterm{user-defined-literal} is taken to be the longest sequence of +characters that could match that non-terminal. \pnum -An evaluation $A$ \defn{simply happens before} an evaluation $B$ -if either -\begin{itemize} -\item $A$ is sequenced before $B$, or -\item $A$ synchronizes with $B$, or -\item $A$ simply happens before $X$ and -$X$ simply happens before $B$. -\end{itemize} -\begin{note} -In the absence of consume operations, -the happens before and simply happens before relations are identical. -\end{note} +A \grammarterm{user-defined-literal} is treated as a call to a literal operator or +literal operator template\iref{over.literal}. +To determine the form of this call for +a given \grammarterm{user-defined-literal} \placeholder{L} +with \grammarterm{ud-suffix} \placeholder{X}, +first let \placeholder{S} be the set of declarations +found by unqualified lookup for the \grammarterm{literal-operator-id} +whose literal suffix identifier is \placeholder{X}\iref{basic.lookup.unqual}. +\placeholder{S} shall not be empty. \pnum -An evaluation $A$ \defn{strongly happens before} -an evaluation $D$ if, either -\begin{itemize} -\item $A$ is sequenced before $D$, or -\item $A$ synchronizes with $D$, and -both $A$ and $D$ are -sequentially consistent atomic operations\iref{atomics.order}, or -\item there are evaluations $B$ and $C$ -such that $A$ is sequenced before $B$, -$B$ simply happens before $C$, and -$C$ is sequenced before $D$, or -\item there is an evaluation $B$ such that -$A$ strongly happens before $B$, and -$B$ strongly happens before $D$. -\end{itemize} +If \placeholder{L} is a \grammarterm{user-defined-integer-literal}, let \placeholder{n} be the literal +without its \grammarterm{ud-suffix}. If \placeholder{S} contains a literal operator with +parameter type \tcode{unsigned long long}, the literal \placeholder{L} is treated as a call of +the form +\begin{codeblock} +operator ""@\placeholder{X}@(@\placeholder{n}@ULL) +\end{codeblock} +Otherwise, \placeholder{S} shall contain a raw literal operator +or a numeric literal operator template\iref{over.literal} but not both. +If \placeholder{S} contains a raw literal operator, +the literal \placeholder{L} is treated as a call of the form +\begin{codeblock} +operator ""@\placeholder{X}@("@\placeholder{n}@") +\end{codeblock} +Otherwise (\placeholder{S} contains a numeric literal operator template), +\placeholder{L} is treated as a call of the form +\begin{codeblock} +operator ""@\placeholder{X}@<'@$c_1$@', '@$c_2$@', ... '@$c_k$@'>() +\end{codeblock} +where \placeholder{n} is the source character sequence $c_1c_2...c_k$. \begin{note} -Informally, if $A$ strongly happens before $B$, -then $A$ appears to be evaluated before $B$ -in all contexts. Strongly happens before excludes consume operations. +The sequence +$c_1c_2...c_k$ can only contain characters from the basic character set. \end{note} \pnum -A \defnadjx{visible}{side effect}{side effects} $A$ on a scalar object or bit-field $M$ -with respect to a value computation $B$ of $M$ satisfies the -conditions: -\begin{itemize} -\item $A$ happens before $B$ and -\item there is no other -\indextext{side effects}% -side effect $X$ to $M$ such that $A$ -happens before $X$ and $X$ happens before $B$. -\end{itemize} - -The value of a non-atomic scalar object or bit-field $M$, as determined by -evaluation $B$, is the value stored by the -\indextext{side effects!visible}% -visible side effect $A$. -\begin{note} -If there is ambiguity about which side effect to a -non-atomic object or bit-field is visible, then the behavior is either -unspecified or undefined. -\end{note} +If \placeholder{L} is a \grammarterm{user-defined-floating-point-literal}, let \placeholder{f} be the +literal without its \grammarterm{ud-suffix}. If \placeholder{S} contains a literal operator +with parameter type \tcode{long double}, the literal \placeholder{L} is treated as a call of +the form +\begin{codeblock} +operator ""@\placeholder{X}@(@\placeholder{f}@L) +\end{codeblock} +Otherwise, \placeholder{S} shall contain a raw literal operator +or a numeric literal operator template\iref{over.literal} but not both. +If \placeholder{S} contains a raw literal operator, +the \grammarterm{literal} \placeholder{L} is treated as a call of the form +\begin{codeblock} +operator ""@\placeholder{X}@("@\placeholder{f}@") +\end{codeblock} +Otherwise (\placeholder{S} contains a numeric literal operator template), +\placeholder{L} is treated as a call of the form +\begin{codeblock} +operator ""@\placeholder{X}@<'@$c_1$@', '@$c_2$@', ... '@$c_k$@'>() +\end{codeblock} +where \placeholder{f} is the source character sequence $c_1c_2...c_k$. \begin{note} -This states that operations on -ordinary objects are not visibly reordered. This is not actually detectable -without data races, but is needed to ensure that data races, as defined -below, and with suitable restrictions on the use of atomics, correspond to data -races in a simple interleaved (sequentially consistent) execution. +The sequence +$c_1c_2...c_k$ can only contain characters from the basic character set. \end{note} \pnum -The value of an -atomic object $M$, as determined by evaluation $B$, is the value -stored by some unspecified -side effect $A$ that modifies $M$, where $B$ does not happen -before $A$. -\begin{note} -The set of such side effects is also restricted by the rest of the rules -described here, and in particular, by the coherence requirements below. -\end{note} +If \placeholder{L} is a \grammarterm{user-defined-string-literal}, +let \placeholder{str} be the literal without its \grammarterm{ud-suffix} +and let \placeholder{len} be the number of code units in \placeholder{str} +(i.e., its length excluding the terminating null character). +If \placeholder{S} contains a literal operator template with +a non-type template parameter for which \placeholder{str} is +a well-formed \grammarterm{template-argument}, +the literal \placeholder{L} is treated as a call of the form +\begin{codeblock} +operator ""@\placeholder{X}@<@\placeholder{str}{}@>() +\end{codeblock} +Otherwise, the literal \placeholder{L} is treated as a call of the form +\begin{codeblock} +operator ""@\placeholder{X}@(@\placeholder{str}{}@, @\placeholder{len}{}@) +\end{codeblock} \pnum -\indextext{coherence!write-write}% -If an operation $A$ that modifies an atomic object $M$ happens before -an operation $B$ that modifies $M$, then $A$ is earlier -than $B$ in the modification order of $M$. -\begin{note} -This requirement is known as write-write coherence. -\end{note} +If \placeholder{L} is a \grammarterm{user-defined-character-literal}, let \placeholder{ch} be the +literal without its \grammarterm{ud-suffix}. +\placeholder{S} shall contain a literal operator\iref{over.literal} whose only parameter has +the type of \placeholder{ch} and the +literal \placeholder{L} is treated as a call +of the form +\begin{codeblock} +operator ""@\placeholder{X}@(@\placeholder{ch}{}@) +\end{codeblock} \pnum -\indextext{coherence!read-read}% -If a -\indextext{value computation}% -value computation $A$ of an atomic object $M$ happens before a -value computation $B$ of $M$, and $A$ takes its value from a side -effect $X$ on $M$, then the value computed by $B$ is either -the value stored by $X$ or the value stored by a -\indextext{side effects}% -side effect $Y$ on $M$, -where $Y$ follows $X$ in the modification order of $M$. -\begin{note} -This requirement is known as read-read coherence. -\end{note} +\begin{example} +\begin{codeblock} +long double operator ""_w(long double); +std::string operator ""_w(const char16_t*, std::size_t); +unsigned operator ""_w(const char*); +int main() { + 1.2_w; // calls \tcode{operator ""_w(1.2L)} + u"one"_w; // calls \tcode{operator ""_w(u"one", 3)} + 12_w; // calls \tcode{operator ""_w("12")} + "two"_w; // error: no applicable literal operator +} +\end{codeblock} +\end{example} \pnum -\indextext{coherence!read-write}% -If a -\indextext{value computation}% -value computation $A$ of an atomic object $M$ happens before an -operation $B$ that modifies $M$, then $A$ takes its value from a side -effect $X$ on $M$, where $X$ precedes $B$ in the -modification order of $M$. -\begin{note} -This requirement is known as -read-write coherence. -\end{note} +In translation phase 6\iref{lex.phases}, adjacent \grammarterm{string-literal}s are concatenated and +\grammarterm{user-defined-string-literal}{s} are considered \grammarterm{string-literal}s for that +purpose. During concatenation, \grammarterm{ud-suffix}{es} are removed and ignored and +the concatenation process occurs as described in~\ref{lex.string}. At the end of phase +6, if a \grammarterm{string-literal} is the result of a concatenation involving at least one +\grammarterm{user-defined-string-literal}, all the participating +\grammarterm{user-defined-string-literal}{s} shall have the same \grammarterm{ud-suffix} +and that suffix is applied to the result of the concatenation. \pnum -\indextext{coherence!write-read}% -If a -\indextext{side effects}% -side effect $X$ on an atomic object $M$ happens before a value -computation $B$ of $M$, then the evaluation $B$ takes its -value from $X$ or from a -\indextext{side effects}% -side effect $Y$ that follows $X$ in the modification order of $M$. -\begin{note} -This requirement is known as write-read coherence. -\end{note} +\begin{example} +\begin{codeblock} +int main() { + L"A" "B" "C"_x; // OK, same as \tcode{L"ABC"_x} + "P"_x "Q" "R"_y; // error: two different \grammarterm{ud-suffix}{es} +} +\end{codeblock} +\end{example} +\indextext{literal|)}% + +\rSec1[basic.link]{Names and linkage}% +\indextext{linkage|(} \pnum -\begin{note} -The four preceding coherence requirements effectively disallow -compiler reordering of atomic operations to a single object, even if both -operations are relaxed loads. This effectively makes the cache coherence -guarantee provided by most hardware available to \Cpp{} atomic operations. -\end{note} +\indextext{type}% +\indextext{object}% +\indextext{storage class}% +\indextext{scope}% +\indextext{linkage}% +A \defn{name} is an \grammarterm{identifier}\iref{lex.name}, +\grammarterm{operator-function-id}\iref{over.oper}, +\grammarterm{literal-operator-id}\iref{over.literal}, or +\grammarterm{conversion-function-id}\iref{class.conv.fct}. \pnum -\begin{note} -The value observed by a load of an atomic depends on the ``happens -before'' relation, which depends on the values observed by loads of atomics. -The intended reading is that there must exist an -association of atomic loads with modifications they observe that, together with -suitably chosen modification orders and the ``happens before'' relation derived -as described above, satisfy the resulting constraints as imposed here. -\end{note} +Two names are \defnx{the same}{name!same} if +\begin{itemize} +\item they are \grammarterm{identifier}{s} composed of the same character sequence, or +\item they are \grammarterm{operator-function-id}{s} formed with the same operator, or +\item they are \grammarterm{literal-operator-id}{s} formed with the same +literal suffix identifier, or +\item they are \grammarterm{conversion-function-id}{s} formed with +equivalent\iref{temp.over.link} types. +\end{itemize} \pnum -Two actions are \defn{potentially concurrent} if +Every name is introduced by a \defn{declaration}, which is a \begin{itemize} -\item they are performed by different threads, or -\item they are unsequenced, at least one is performed by a signal handler, and -they are not both performed by the same signal handler invocation. +\item +\grammarterm{name-declaration}, +\grammarterm{block-declaration}, or +\grammarterm{member-declaration}\iref{dcl.pre,class.mem}, +\item +\grammarterm{init-capture}\iref{expr.prim.lambda.capture}, +\item +\grammarterm{condition} with a \grammarterm{declarator}\iref{stmt.pre}, +\item +\grammarterm{exception-declaration}\iref{except.pre}, +\item +\grammarterm{elaborated-type-specifier} +that introduces a name\iref{dcl.type.elab}, +\item +\grammarterm{init-declarator}\iref{dcl.decl}, +\item +\grammarterm{parameter-declaration}\iref{dcl.fct}, +\item +\grammarterm{identifier} +in a structured binding declaration\iref{dcl.struct.bind}, +\item +\grammarterm{enum-specifier} or +\grammarterm{enumerator-definition}\iref{dcl.enum}, +\item +\grammarterm{using-declarator}\iref{namespace.udecl}, +\item +\grammarterm{class-specifier}\iref{class.pre}, +\item +implicit declaration of an injected-class-name\iref{class.pre}, +\item +\grammarterm{member-declarator}\iref{class.mem}, or +\item +\grammarterm{type-parameter}\iref{temp.param}. \end{itemize} -The execution of a program contains a \defn{data race} if it contains two -potentially concurrent conflicting actions, at least one of which is not atomic, -and neither happens before the other, -except for the special case for signal handlers described below. -Any such data race results in undefined -behavior. \begin{note} -It can be shown that programs that correctly use mutexes -and \tcode{memory_order::seq_cst} operations to prevent all data races and use no -other synchronization operations behave as if the operations executed by their -constituent threads were simply interleaved, with each -\indextext{value computation}% -value computation of an -object being taken from the last -\indextext{side effects}% -side effect on that object in that -interleaving. This is normally referred to as ``sequential consistency''. -However, this applies only to data-race-free programs, and data-race-free -programs cannot observe most program transformations that do not change -single-threaded program semantics. In fact, most single-threaded program -transformations remain possible, since any program that behaves -differently as a result has undefined behavior. +The interpretation of a \grammarterm{for-range-declaration} produces +one or more of the above\iref{stmt.ranged}. \end{note} \pnum -Two accesses to the same object of type \tcode{\keyword{volatile} std::sig_atomic_t} 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 \tcode{\keyword{volatile} std::sig_atomic_t} 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$. +An \defn{entity} is a value, object, reference, structured binding, function, +enumerator, type, class member, bit-field, template, template specialization, +namespace, or pack. An entity $E$ is denoted by the name (if any) that is +introduced by a declaration of $E$ or by a \grammarterm{typedef-name} +introduced by a declaration specifying $E$. \pnum -\begin{note} -Compiler transformations that introduce assignments to a potentially -shared memory location that would not be modified by the abstract machine are -generally precluded by this document, since such an assignment might overwrite -another assignment by a different thread in cases in which an abstract machine -execution would not have encountered a data race. This includes implementations -of data member assignment that overwrite adjacent members in separate memory -locations. Reordering of atomic loads in cases in which the atomics in question -might alias is also generally precluded, since this could violate the coherence -rules. -\end{note} +Some names denote types or templates. In general, whenever a name is +encountered it is necessary to determine whether that name denotes one of these +entities before continuing to parse the program that contains it. The process +that determines this is called +\defnx{name lookup}{lookup!name}\iref{basic.lookup}. \pnum +A \defn{variable} is introduced by the +declaration of +a reference other than a non-static data member or of +an object. The variable's name, if any, denotes the reference or object. + +\pnum +A name can have +\defnadj{external}{linkage}, +\defnadj{module}{linkage}, +\defnadj{internal}{linkage}, or +\defnadj{no}{linkage}, +as determined by the rules below. \begin{note} -It is possible that transformations that introduce a speculative read of a potentially -shared memory location do not preserve the semantics of the \Cpp{} program as -defined in this document, since they potentially introduce a data race. However, -they are typically valid in the context of an optimizing compiler that targets a -specific machine with well-defined semantics for data races. They would be -invalid for a hypothetical machine that is not tolerant of races or provides -hardware race detection. +All declarations of an entity with a name with internal linkage +appear in the same translation unit. +All declarations of an entity with module linkage +are attached to the same module. \end{note} -\rSec3[intro.progress]{Forward progress} - \pnum -The implementation may assume that any thread will eventually do one of the -following: +\indextext{linkage!\idxcode{static} and}% +\indextext{\idxcode{static}!linkage of}% +\indextext{linkage!\idxcode{const} and}% +\indextext{\idxcode{const}!linkage of}% +\indextext{linkage!\idxcode{inline} and}% +\indextext{\idxcode{inline}!linkage of}% +The name of an entity +that belongs to a namespace scope\iref{basic.scope.namespace} +has internal linkage if it is the name of \begin{itemize} -\item terminate, -\item invoke the function \tcode{std::this_thread::yield}\iref{thread.thread.this}, -\item make a call to a library I/O function, -\item perform an access through a volatile glvalue, -\item perform a synchronization operation or an atomic operation, or -\item continue execution of a trivial infinite loop\iref{stmt.iter.general}. +\item + a variable, variable template, function, or function template that is + explicitly declared \keyword{static}; or +\item + a non-template variable of non-volatile const-qualified type, unless + \begin{itemize} + \item it is declared in the purview of a module interface unit + (outside the \grammarterm{private-module-fragment}, if any) or + module partition, or + \item it is explicitly declared \keyword{extern}, or + \item it is inline, or + \item it was previously declared and the prior declaration did + not have internal linkage; or + \end{itemize} +\item + a data member of an anonymous union. \end{itemize} \begin{note} -This is intended to allow compiler transformations -such as removal, merging, and reordering of empty loops, -even when termination cannot be proven. -An affordance is made for trivial infinite loops, -which cannot be removed nor reordered. +An instantiated variable template that has const-qualified type +can have external or module linkage, even if not declared \keyword{extern}. \end{note} \pnum -Executions of atomic functions -that are either defined to be lock-free\iref{atomics.flag} -or indicated as lock-free\iref{atomics.lockfree} -are \defnx{lock-free executions}{lock-free execution}. +An unnamed namespace or a namespace declared directly or indirectly within an +unnamed namespace has internal linkage. All other namespaces have external linkage. +The name of an entity that belongs to a namespace scope +that has not been given internal linkage above +and that is the name of \begin{itemize} +\item a variable; or +\item a function; or \item - If there is only one thread that is not blocked\iref{defns.block} - in a standard library function, - a lock-free execution in that thread shall complete. - \begin{note} - Concurrently executing threads - might prevent progress of a lock-free execution. - For example, - this situation can occur - with load-locked store-conditional implementations. - This property is sometimes termed obstruction-free. - \end{note} +\indextext{class!linkage of}% +a named class\iref{class.pre}, or an unnamed class defined in a +typedef declaration in which the class has the typedef name for linkage +purposes\iref{dcl.typedef}; or \item - When one or more lock-free executions run concurrently, - at least one should complete. - \begin{note} - It is difficult for some implementations - to provide absolute guarantees to this effect, - since repeated and particularly inopportune interference - from other threads - could prevent forward progress, - e.g., - by repeatedly stealing a cache line - for unrelated purposes - between load-locked and store-conditional instructions. - For implementations that follow this recommendation and - ensure that such effects cannot indefinitely delay progress - under expected operating conditions, - such anomalies - can therefore safely be ignored by programmers. - Outside this document, - this property is sometimes termed lock-free. - \end{note} +\indextext{enumeration!linkage of}% +a named enumeration\iref{dcl.enum}, or an unnamed enumeration defined +in a typedef declaration in which the enumeration has the typedef name +for linkage purposes\iref{dcl.typedef}; or +\item an unnamed enumeration +that has an enumerator as a name for linkage purposes\iref{dcl.enum}; or +\item a template \end{itemize} - -\pnum -During the execution of a thread of execution, each of the following is termed -an \defn{execution step}: +has its linkage determined as follows: \begin{itemize} -\item termination of the thread of execution, -\item performing an access through a volatile glvalue, or -\item completion of a call to a library I/O function, a - synchronization operation, or an atomic operation. +\item +\indextext{friend function!linkage of}% +if the entity is a function or function template +first declared in a friend declaration and +that declaration is a definition and +the enclosing class is defined within an \grammarterm{export-declaration}, +the name has the same linkage, if any, +as the name of the enclosing class\iref{class.friend}; +\item +otherwise, +\indextext{friend function!linkage of}% +if the entity is a function or function template +declared in a friend declaration and +a corresponding non-friend declaration is reachable, +%FIXME: Which declaration is "that prior declaration"? +%FIXME: "prior" with respect to what? And what about dependent lookup? +the name has the linkage determined from that prior declaration, +\item +otherwise, +if the enclosing namespace has internal linkage, +the name has internal linkage; +\item +otherwise, +if the declaration of the name is +attached to a named module\iref{module.unit} +and is not exported\iref{module.interface}, +the name has module linkage; +\item +otherwise, +the name has external linkage. \end{itemize} \pnum -An invocation of a standard library function that blocks\iref{defns.block} -is considered to continuously execute execution steps while waiting for the -condition that it blocks on to be satisfied. -\begin{example} -A library I/O function that blocks until the I/O operation is complete can -be considered to continuously check whether the operation is complete. Each -such check consists of one or more execution steps, for example using -observable behavior of the abstract machine. -\end{example} - -\pnum -\begin{note} -Because of this and the preceding requirement regarding what threads of execution -have to perform eventually, it follows that no thread of execution can execute -forever without an execution step occurring. -\end{note} - -\pnum -A thread of execution \defnx{makes progress}{make progress!thread} -when an execution step occurs or a -lock-free execution does not complete because there are other concurrent threads -that are not blocked in a standard library function (see above). - -\pnum -\indextext{forward progress guarantees!concurrent}% -For a thread of execution providing \defn{concurrent forward progress guarantees}, -the implementation ensures that the thread will eventually make progress for as -long as it has not terminated. -\begin{note} -This applies regardless of whether or not other threads of execution (if any) -have been or are making progress. To eventually fulfill this requirement means that -this will happen in an unspecified but finite amount of time. -\end{note} - -\pnum -It is \impldef{whether the thread that executes \tcode{main} and the threads created -by \tcode{std::thread} or \tcode{std::jthread} provide concurrent forward progress guarantees} whether the -implementation-created thread of execution that executes -\tcode{main}\iref{basic.start.main} and the threads of execution created by -\tcode{std::thread}\iref{thread.thread.class} -or \tcode{std::jthread}\iref{thread.jthread.class} -provide concurrent forward progress guarantees. -General-purpose implementations should provide these guarantees. - -\pnum -\indextext{forward progress guarantees!parallel}% -For a thread of execution providing \defn{parallel forward progress guarantees}, -the implementation is not required to ensure that the thread will eventually make -progress if it has not yet executed any execution step; once this thread has -executed a step, it provides concurrent forward progress guarantees. - -\pnum -\begin{note} -This does not specify a requirement for when to start this thread of execution, -which will typically be specified by the entity that creates this thread of -execution. For example, a thread of execution that provides concurrent forward -progress guarantees and executes tasks from a set of tasks in an arbitrary order, -one after the other, satisfies the requirements of parallel forward progress for -these tasks. -\end{note} - -\pnum -\indextext{forward progress guarantees!weakly parallel}% -For a thread of execution providing \defn{weakly parallel forward progress -guarantees}, the implementation does not ensure that the thread will eventually -make progress. - -\pnum -\begin{note} -Threads of execution providing weakly parallel forward progress guarantees cannot -be expected to make progress regardless of whether other threads make progress or -not; however, blocking with forward progress guarantee delegation, as defined below, -can be used to ensure that such threads of execution make progress eventually. -\end{note} +In addition, +a member function, +a static data member, +a named class or enumeration that inhabits a class scope, or +an unnamed class or enumeration defined in a typedef declaration +that inhabits a class scope +such that the class or enumeration +has the typedef name for linkage purposes\iref{dcl.typedef}, +has the same linkage, if any, as the name of the class of which it is a member. \pnum -Concurrent forward progress guarantees are stronger than parallel forward progress -guarantees, which in turn are stronger than weakly parallel forward progress -guarantees. -\begin{note} -For example, some kinds of synchronization between threads of execution might only -make progress if the respective threads of execution provide parallel forward progress -guarantees, but will fail to make progress under weakly parallel guarantees. -\end{note} +\begin{example} +\begin{codeblock} +static void f(); +extern "C" void h(); +static int i = 0; // \#1 +void q() { + extern void f(); // internal linkage + extern void g(); // \tcode{::g}, external linkage + extern void h(); // C language linkage + int i; // \#2: \tcode{i} has no linkage + { + extern void f(); // internal linkage + extern int i; // \#3: internal linkage + } +} +\end{codeblock} +Even though the declaration at line \#2 hides the declaration at line \#1, +the declaration at line \#3 still redeclares \#1 and receives internal linkage. +\end{example} \pnum -\indextext{forward progress guarantees!delegation of}% -When a thread of execution $P$ is specified to -\defnx{block with forward progress guarantee delegation} -{block (execution)!with forward progress guarantee delegation} -on the completion of a set $S$ of threads of execution, -then throughout the whole time of $P$ being blocked on $S$, -the implementation shall ensure that the forward progress guarantees -provided by at least one thread of execution in $S$ -is at least as strong as $P$'s forward progress guarantees. -\begin{note} -It is unspecified which thread or threads of execution in $S$ are chosen -and for which number of execution steps. The strengthening is not permanent and -not necessarily in place for the rest of the lifetime of the affected thread of -execution. As long as $P$ is blocked, the implementation has to eventually -select and potentially strengthen a thread of execution in $S$. -\end{note} -Once a thread of execution in $S$ terminates, it is removed from $S$. -Once $S$ is empty, $P$ is unblocked. +\indextext{linkage!no}% +Names not covered by these rules have no linkage. Moreover, except as +noted, a name declared at block scope\iref{basic.scope.block} has no +linkage. \pnum -\begin{note} -A thread of execution $B$ thus can temporarily provide an effectively -stronger forward progress guarantee for a certain amount of time, due to a -second thread of execution $A$ being blocked on it with forward -progress guarantee delegation. In turn, if $B$ then blocks with -forward progress guarantee delegation on $C$, this can also temporarily -provide a stronger forward progress guarantee to $C$. -\end{note} +\indextext{translation unit!name and}% +\indextext{linkage}% +A name used in more than one translation unit can potentially +refer to the same entity in these translation units depending on the +linkage of the name specified in each translation unit. \pnum +Two declarations of entities declare the same entity +if, considering declarations of unnamed types to introduce their names +for linkage purposes, if any\iref{dcl.typedef,dcl.enum}, +they correspond\iref{basic.scope.scope}, +have the same target scope that is not a function or template parameter scope, +neither is a name-independent declaration, +and either +\begin{itemize} +\item +they appear in the same translation unit, or +\item +they both declare names with module linkage and are attached to the same module, or +\item +they both declare names with external linkage. +\end{itemize} \begin{note} -If all threads of execution in $S$ finish executing (e.g., they terminate -and do not use blocking synchronization incorrectly), then $P$'s execution -of the operation that blocks with forward progress guarantee delegation will not -result in $P$'s progress guarantee being effectively weakened. +There are other circumstances in which declarations declare the same entity% +\iref{dcl.link,temp.type,temp.spec.partial}. \end{note} \pnum +If a declaration $H$ that declares a name with internal linkage +precedes a declaration $D$ in another translation unit $U$ and +would declare the same entity as $D$ if it appeared in $U$, +the program is ill-formed. \begin{note} -This does not remove any constraints regarding blocking synchronization for -threads of execution providing parallel or weakly parallel forward progress -guarantees because the implementation is not required to strengthen a particular -thread of execution whose too-weak progress guarantee is preventing overall progress. +Such an $H$ can appear only in a header unit. \end{note} \pnum -An implementation should ensure that the last value (in modification order) -assigned by an atomic or synchronization operation will become visible to all -other threads in a finite period of time.% -\indextext{atomic!operation|)}% -\indextext{threads!multiple|)} - -\rSec2[basic.start]{Start and termination} - -\rSec3[basic.start.main]{\tcode{main} function} -\indextext{\idxcode{main} function|(} +If two declarations of an entity are +attached to different modules, the program is ill-formed; +no diagnostic is required if neither is reachable from the other. +\begin{example} +\begin{codeblocktu}{\tcode{"decls.h"}} +int f(); // \#1, attached to the global module +int g(); // \#2, attached to the global module +\end{codeblocktu} -\pnum -\indextext{program!startup|(}% -A program shall contain exactly one function called \tcode{main} -that belongs to the global scope. -Executing a program starts a main thread of execution\iref{intro.multithread,thread.threads} -in which the \tcode{main} function is invoked. -\indextext{implementation!freestanding}% -It is \impldef{defining \tcode{main} in freestanding environment} -whether a program in a freestanding environment is required to define a \tcode{main} -function. -\begin{note} -In a freestanding environment, startup and termination is -\impldef{startup and termination in freestanding environment}; startup contains the -execution of constructors for non-local objects with static storage duration; -termination contains the execution of destructors for objects with static storage -duration. -\end{note} +\begin{codeblocktu}{Module interface of \tcode{M}} +module; +#include "decls.h" +export module M; +export using ::f; // OK, does not declare an entity, exports \#1 +int g(); // error: matches \#2, but attached to \tcode{M} +export int h(); // \#3 +export int k(); // \#4 +\end{codeblocktu} -\pnum -An implementation shall not predefine the \tcode{main} function. -Its type shall have \Cpp{} language linkage -and it shall have a declared return type of type -\keyword{int}, but otherwise its type is \impldef{parameters to \tcode{main}}. -\indextext{\idxcode{main} function!implementation-defined parameters to}% -An implementation shall allow both -\begin{itemize} -\item a function of \tcode{()} returning \keyword{int} and -\item a function of \tcode{(\keyword{int}}, pointer to pointer to \tcode{\keyword{char})} returning \keyword{int} -\end{itemize} -\indextext{\idxcode{argc}}% -\indextext{\idxcode{argv}}% -as the type of \tcode{main}\iref{dcl.fct}. -\indextext{\idxcode{main} function!parameters to}% -\indextext{environment!program}% -In the latter form, for purposes of exposition, the first function -parameter is called \tcode{argc} and the second function parameter is -called \tcode{argv}, where \tcode{argc} shall be the number of -arguments passed to the program from the environment in which the -program is run. If -\tcode{argc} is nonzero these arguments shall be supplied in -\tcode{argv[0]} through \tcode{argv[argc-1]} as pointers to the initial -characters of null-terminated multibyte strings (\ntmbs{}s)\iref{multibyte.strings} -and \tcode{argv[0]} shall be the pointer to -the initial character of an \ntmbs{} that represents the name used to -invoke the program or \tcode{""}. The value of \tcode{argc} shall be -non-negative. The value of \tcode{argv[argc]} shall be 0. - -\recommended -Any further (optional) parameters should be added after \tcode{argv}. +\begin{codeblocktu}{Other translation unit} +import M; +static int h(); // error: matches \#3 +int k(); // error: matches \#4 +\end{codeblocktu} +\end{example} +As a consequence of these rules, +all declarations of an entity are attached to the same module; +the entity is said to be \defnx{attached}{attached!entity} to that module. \pnum -The function \tcode{main} shall not be named by an expression. -\indextext{\idxcode{main} function!implementation-defined linkage of}% -The linkage\iref{basic.link} of \tcode{main} is -\impldef{linkage of \tcode{main}}. A program that defines \tcode{main} as -deleted or that declares \tcode{main} to be -\keyword{inline}, \keyword{static}, \keyword{constexpr}, or \keyword{consteval} is ill-formed. -The function \tcode{main} shall not be a coroutine\iref{dcl.fct.def.coroutine}. -The \tcode{main} function shall not be declared with a -\grammarterm{linkage-specification}\iref{dcl.link}. -A program that declares +\indextext{consistency!type declaration}% +\indextext{declaration!multiple}% +For any two declarations of an entity $E$: \begin{itemize} \item -a variable \tcode{main} that belongs to the global scope, or +If one declares $E$ to be a variable or function, +the other shall declare $E$ as one of the same type. +\item +If one declares $E$ to be an enumerator, the other shall do so. +\item +If one declares $E$ to be a namespace, the other shall do so. +\item +If one declares $E$ to be a type, +the other shall declare $E$ to be a type of the same kind\iref{dcl.type.elab}. +\item +If one declares $E$ to be a class template, +the other shall do so with the same kind and +an equivalent \grammarterm{template-head}\iref{temp.over.link}. +\begin{note} +The declarations can supply different default template arguments. +\end{note} \item -a function \tcode{main} that belongs to the global scope and -is attached to a named module, or +If one declares $E$ to be a function template or +a (partial specialization of a) variable template, +the other shall declare $E$ to be one +with an equivalent \grammarterm{template-head} and type. \item -a function template \tcode{main} that belongs to the global scope, or +If one declares $E$ to be an alias template, +the other shall declare $E$ to be one with +an equivalent \grammarterm{template-head} and \grammarterm{defining-type-id}. \item -an entity named \tcode{main} -with C language linkage (in any namespace) +If one declares $E$ to be a concept, the other shall do so. \end{itemize} -is ill-formed. -The name \tcode{main} is -not otherwise reserved. +Types are compared after all adjustments of types (during which +typedefs\iref{dcl.typedef} are replaced by their definitions); +declarations for an array +object can specify array types that differ by the presence or absence of +a major array bound\iref{dcl.array}. +No diagnostic is required if neither declaration is reachable from the other. \begin{example} -Member functions, classes, and -enumerations can be called \tcode{main}, as can entities in other -namespaces. +\begin{codeblock} +int f(int x, int x); // error: different entities for \tcode{x} +void g(); // \#1 +void g(int); // OK, different entity from \#1 +int g(); // error: same entity as \#1 with different type +void h(); // \#2 +namespace h {} // error: same entity as \#2, but not a function +\end{codeblock} \end{example} \pnum -\indextext{\idxcode{exit}}% -\indexlibraryglobal{exit}% -\indextext{termination!program}% -Terminating the program -without leaving the current block (e.g., by calling the function -\tcode{std::exit(int)}\iref{support.start.term}) does not destroy any -objects with automatic storage duration\iref{class.dtor}. If -\tcode{std::exit} is invoked during the destruction of -an object with static or thread storage duration, the program has undefined -behavior. - -\pnum -\indextext{termination!program}% -\indextext{\idxcode{main} function!return from}% -A \keyword{return} statement\iref{stmt.return} in \tcode{main} has the effect of leaving the main -function (destroying any objects with automatic storage duration) and -calling \tcode{std::exit} with the return value as the argument. -If control flows off the end of -the \grammarterm{compound-statement} of \tcode{main}, -the effect is equivalent to a \keyword{return} with operand \tcode{0} -(see also \ref{except.handle}). -\indextext{\idxcode{main} function|)} - -\rSec3[basic.start.static]{Static initialization} - -\pnum -\indextext{initialization}% -\indextext{initialization!static and thread}% -Variables with static storage duration -are initialized as a consequence of program initiation. Variables with -thread storage duration are initialized as a consequence of thread execution. -Within each of these phases of initiation, initialization occurs as follows. - -\pnum -\indextext{initialization!constant}% -\defnx{Constant initialization}{constant initialization} is performed -if a variable or temporary object with static or thread storage duration -is constant-initialized\iref{expr.const}. -\indextext{initialization!zero-initialization}% -If constant initialization is not performed, a variable with static -storage duration\iref{basic.stc.static} or thread storage -duration\iref{basic.stc.thread} is zero-initialized\iref{dcl.init}. -Together, zero-initialization and constant initialization are called -\defnadj{static}{initialization}; -all other initialization is \defnadj{dynamic}{initialization}. -All static initialization strongly happens before\iref{intro.races} -any dynamic initialization. \begin{note} -The dynamic initialization of non-block variables is described -in~\ref{basic.start.dynamic}; that of static block variables is described -in~\ref{stmt.dcl}. +Linkage to non-\Cpp{} declarations can be achieved using a +\grammarterm{linkage-specification}\iref{dcl.link}. \end{note} +\indextext{linkage|)} \pnum -An implementation is permitted to perform the initialization of a -variable with static or thread storage duration as a static -initialization even if such initialization is not required to be done -statically, provided that +A declaration $D$ \defnx{names}{name} an entity $E$ if \begin{itemize} \item -the dynamic version of the initialization does not change the -value of any other object of static or thread storage duration -prior to its initialization, and - +$D$ contains a \grammarterm{lambda-expression} whose closure type is $E$, \item -the static version of the initialization produces the same value -in the initialized variable as would be produced by the dynamic -initialization if all variables not required to be initialized statically -were initialized dynamically. -\end{itemize} -\begin{note} -As a consequence, if the initialization of an object \tcode{obj1} refers to an -object \tcode{obj2} potentially requiring dynamic initialization and defined -later in the same translation unit, it is unspecified whether the value of \tcode{obj2} used -will be the value of the fully initialized \tcode{obj2} (because \tcode{obj2} was statically -initialized) or will be the value of \tcode{obj2} merely zero-initialized. For example, -\begin{codeblock} -inline double fd() { return 1.0; } -extern double d1; -double d2 = d1; // unspecified: - // either statically initialized to \tcode{0.0} or - // dynamically initialized to \tcode{0.0} if \tcode{d1} is - // dynamically initialized, or \tcode{1.0} otherwise -double d1 = fd(); // either initialized statically or dynamically to \tcode{1.0} -\end{codeblock} -\end{note} - -\rSec3[basic.start.dynamic]{Dynamic initialization of non-block variables} - -\pnum -\indextext{initialization!dynamic non-block}% -\indextext{start!program}% -\indextext{initialization!order of}% -Dynamic initialization of a non-block variable with static storage duration is -unordered if the variable is an implicitly or explicitly instantiated -specialization, is partially-ordered if the variable -is an inline variable that is not an implicitly or explicitly instantiated -specialization, and otherwise is ordered. +$E$ is not a function or function template and $D$ contains an +\grammarterm{id-expression}, +\grammarterm{type-specifier}, +\grammarterm{nested-name-specifier}, +\grammarterm{template-name}, or +\grammarterm{concept-name} +denoting $E$, or +\item +$E$ is a function or function template and +$D$ contains an expression that names $E$\iref{basic.def.odr} or +an \grammarterm{id-expression} +that refers to a set of overloads that contains $E$. \begin{note} -A non-inline explicit specialization of a templated variable -has ordered initialization. +Non-dependent names in an instantiated declaration +do not refer to a set of overloads\iref{temp.res}. \end{note} +\end{itemize} \pnum -A declaration \tcode{D} is -\defn{appearance-ordered} before a declaration \tcode{E} if +A declaration is an \defn{exposure} +if it either names a TU-local entity (defined below), ignoring \begin{itemize} -\item \tcode{D} appears in the same translation unit as \tcode{E}, or -\item the translation unit containing \tcode{E} -has an interface dependency on the translation unit containing \tcode{D}, +\item +the \grammarterm{function-body} +for a non-inline function or function template +(but not the deduced return type +for a (possibly instantiated) definition of a function +with a declared return type that uses a placeholder type\iref{dcl.spec.auto}), +\item +the \grammarterm{initializer} +for a variable or variable template (but not the variable's type), +\item +friend declarations in a class definition, and +\item +any reference to a non-volatile const object or reference +with internal or no linkage initialized with a constant expression +that is not an odr-use\iref{term.odr.use}, \end{itemize} -in either case prior to \tcode{E}. +or defines a constexpr variable initialized to a TU-local value (defined below). +\begin{note} +An inline function template can be an exposure even though +certain explicit specializations of it would be usable in other translation units. +\end{note} \pnum -Dynamic initialization of non-block variables \tcode{V} and \tcode{W} -with static storage duration are ordered as follows: +An entity is \defnx{TU-local}{TU-local!entity} if it is \begin{itemize} \item -If \tcode{V} and \tcode{W} have ordered initialization and -the definition of \tcode{V} -is appearance-ordered before the definition of \tcode{W}, or -if \tcode{V} has partially-ordered initialization, -\tcode{W} does not have unordered initialization, and -for every definition \tcode{E} of \tcode{W} -there exists a definition \tcode{D} of \tcode{V} -such that \tcode{D} is appearance-ordered before \tcode{E}, then +a type, function, variable, or template that \begin{itemize} \item -if the program does not start a thread\iref{intro.multithread} -other than the main thread\iref{basic.start.main} -or \tcode{V} and \tcode{W} have ordered initialization and -they are defined in the same translation unit, -the initialization of \tcode{V} -is sequenced before -the initialization of \tcode{W}; +has a name with internal linkage, or \item -otherwise, -the initialization of \tcode{V} -strongly happens before -the initialization of \tcode{W}. +does not have a name with linkage and is declared, +or introduced by a \grammarterm{lambda-expression}, +within the definition of a TU-local entity, \end{itemize} - \item -Otherwise, if the program starts a thread -other than the main thread -before either \tcode{V} or \tcode{W} is initialized, -it is unspecified in which threads -the initializations of \tcode{V} and \tcode{W} occur; -the initializations are unsequenced if they occur in the same thread. - +a type with no name that is defined outside a +\grammarterm{class-specifier}, +function body, or +\grammarterm{initializer} +or is introduced by a \grammarterm{defining-type-specifier} +that is used to declare only TU-local entities, \item -Otherwise, the initializations of \tcode{V} and \tcode{W} are indeterminately sequenced. -\end{itemize} -\begin{note} -This definition permits initialization of a sequence of -ordered variables concurrently with another sequence. -\end{note} - -\pnum -\indextext{non-initialization odr-use|see{odr-use, non-initialization}}% -A \defnx{non-initialization odr-use}{odr-use!non-initialization} -is an odr-use\iref{term.odr.use} not caused directly or indirectly by -the initialization of a non-block static or thread storage duration variable. - -\pnum -\indextext{evaluation!unspecified order of}% -It is \impldef{dynamic initialization of static variables before \tcode{main}} -whether the dynamic initialization of a -non-block non-inline variable with static storage duration -is sequenced before the first statement of \tcode{main} or is deferred. -If it is deferred, it strongly happens before -any non-initialization odr-use -of any non-inline function or non-inline variable -defined in the same translation unit as the variable to be initialized. -\begin{footnote} -A non-block variable with static storage duration -having initialization -with side effects is initialized in this case, -even if it is not itself odr-used\iref{term.odr.use,basic.stc.static}. -\end{footnote} -It is \impldef{threads and program points at which deferred dynamic initialization is performed} -in which threads and at which points in the program such deferred dynamic initialization occurs. - -\recommended -An implementation should choose such points in a way -that allows the programmer to avoid deadlocks. -\begin{example} -\begin{codeblock} -// - File 1 - -#include "a.h" -#include "b.h" -B b; -A::A() { - b.Use(); -} - -// - File 2 - -#include "a.h" -A a; - -// - File 3 - -#include "a.h" -#include "b.h" -extern A a; -extern B b; - -int main() { - a.Use(); - b.Use(); -} -\end{codeblock} - -It is \impldef{dynamic initialization of static variables before \tcode{main}} -whether either \tcode{a} or \tcode{b} is -initialized before \tcode{main} is entered or whether the -initializations are delayed until \tcode{a} is first odr-used in -\tcode{main}. In particular, if \tcode{a} is initialized before -\tcode{main} is entered, it is not guaranteed that \tcode{b} will be -initialized before it is odr-used by the initialization of \tcode{a}, that -is, before \tcode{A::A} is called. If, however, \tcode{a} is initialized -at some point after the first statement of \tcode{main}, \tcode{b} will -be initialized prior to its use in \tcode{A::A}. -\end{example} - -\pnum -It is \impldef{dynamic initialization of static inline variables before \tcode{main}} -whether the dynamic initialization of a -non-block inline variable with static storage duration -is sequenced before the first statement of \tcode{main} or is deferred. -If it is deferred, it strongly happens before -any non-initialization odr-use -of that variable. -It is \impldef{threads and program points at which deferred dynamic initialization is performed} -in which threads and at which points in the program such deferred dynamic initialization occurs. - -\pnum -It is \impldef{dynamic initialization of thread-local variables before entry} -whether the dynamic initialization of a -non-block non-inline variable with thread storage duration -is sequenced before the first statement of the initial function of a thread or is deferred. -If it is deferred, -the initialization associated with the entity for thread \placeholder{t} -is sequenced before the first non-initialization odr-use by \placeholder{t} -of any non-inline variable with thread storage duration -defined in the same translation unit as the variable to be initialized. -It is \impldef{threads and program points at which deferred dynamic initialization is performed} -in which threads and at which points in the program such deferred dynamic initialization occurs. - -\pnum -If the initialization of -a non-block variable with static or thread storage duration -exits via an exception, -the function \tcode{std::terminate} is called\iref{except.terminate}.% -\indextext{program!startup|)} - -\rSec3[basic.start.term]{Termination} - -\pnum -\indextext{program!termination|(}% -\indextext{object!destructor static}% -\indextext{\idxcode{main} function!return from}% -Constructed objects\iref{dcl.init} -with static storage duration are destroyed -and functions registered with \tcode{std::atexit} -are called as part of a call to -\indextext{\idxcode{exit}}% -\indexlibraryglobal{exit}% -\tcode{std::exit}\iref{support.start.term}. -The call to \tcode{std::exit} is sequenced before -the destructions and the registered functions. +a specialization of a TU-local template, +\item +a specialization of a template with any TU-local template argument, or +\item +a specialization of a template +whose (possibly instantiated) declaration is an exposure. \begin{note} -Returning from \tcode{main} invokes \tcode{std::exit}\iref{basic.start.main}. +A specialization can be produced by implicit or explicit instantiation. \end{note} +\end{itemize} \pnum -Constructed objects with thread storage duration within a given thread -are destroyed as a result of returning from the initial function of that thread and as a -result of that thread calling \tcode{std::exit}. -The destruction of all constructed objects with thread storage -duration within that thread strongly happens before destroying -any object with static storage duration. +A value or object is \defnx{TU-local}{TU-local!value or object} if either +\begin{itemize} +\item +it is, or is a pointer to, +a TU-local function or the object associated with a TU-local variable, or +\item +it is an object of class or array type and +any of its subobjects or +any of the objects or functions +to which its non-static data members of reference type refer +is TU-local and is usable in constant expressions. +\end{itemize} \pnum -If the completion of the constructor or dynamic initialization of an object with static -storage duration strongly happens before that of another, the completion of the destructor -of the second is sequenced before the initiation of the destructor of the first. -If the completion of the constructor or dynamic initialization of an object with thread -storage duration is sequenced before that of another, the completion of the destructor -of the second is sequenced before the initiation of the destructor of the first. -If an object is -initialized statically, the object is destroyed in the same order as if -the object was dynamically initialized. For an object of array or class -type, all subobjects of that object are destroyed before any block -variable with static storage duration initialized during the construction -of the subobjects is destroyed. -If the destruction of an object with static or thread storage duration -exits via an exception, -the function \tcode{std::terminate} is called\iref{except.terminate}. +If a (possibly instantiated) declaration of, or a deduction guide for, +a non-TU-local entity in a module interface unit +(outside the \grammarterm{private-module-fragment}, if any) or +module partition\iref{module.unit} is an exposure, +the program is ill-formed. +Such a declaration in any other context is deprecated\iref{depr.local}. \pnum -If a function contains a block variable of static or thread storage duration that has been -destroyed and the function is called during the destruction of an object with static or -thread storage duration, the program has undefined behavior if the flow of control -passes through the definition of the previously destroyed block variable. -\begin{note} -Likewise, the behavior is undefined -if the block variable is used indirectly (e.g., through a pointer) -after its destruction. -\end{note} +If a declaration that appears in one translation unit +names a TU-local entity declared +in another translation unit that is not a header unit, +the program is ill-formed. +A declaration instantiated for a template specialization\iref{temp.spec} +appears at the point of instantiation of the specialization\iref{temp.point}. \pnum -\indextext{\idxcode{atexit}}% -\indexlibraryglobal{atexit}% -If the completion of the initialization of an object with static storage -duration strongly happens before a call to \tcode{std::atexit}~(see -\libheader{cstdlib}, \ref{support.start.term}), the call to the function passed to -\tcode{std::atexit} is sequenced before the call to the destructor for the object. If a -call to \tcode{std::atexit} strongly happens before the completion of the initialization of -an object with static storage duration, the call to the destructor for the -object is sequenced before the call to the function passed to \tcode{std::atexit}. If a -call to \tcode{std::atexit} strongly happens before another call to \tcode{std::atexit}, the -call to the function passed to the second \tcode{std::atexit} call is sequenced before -the call to the function passed to the first \tcode{std::atexit} call. +\begin{example} +\begin{codeblocktu}{Translation unit \#1} +export module A; +static void f() {} +inline void it() { f(); } // error: is an exposure of \tcode{f} +static inline void its() { f(); } // OK +template void g() { its(); } // OK +template void g<0>(); -\pnum -If there is a use of a standard library object or function not permitted within signal -handlers\iref{support.runtime} that does not happen before\iref{intro.multithread} -completion of destruction of objects with static storage duration and execution of -\tcode{std::atexit} registered functions\iref{support.start.term}, the program has -undefined behavior. -\begin{note} -If there is a use of an object with static storage -duration that does not happen before the object's destruction, the program has undefined -behavior. Terminating every thread before a call to \tcode{std::exit} or the exit from -\tcode{main} is sufficient, but not necessary, to satisfy these requirements. These -requirements permit thread managers as static-storage-duration objects. -\end{note} +decltype(f) *fp; // error: \tcode{f} (though not its type) is TU-local +auto &fr = f; // OK +constexpr auto &fr2 = fr; // error: is an exposure of \tcode{f} +constexpr static auto fp2 = fr; // OK -\pnum -\indextext{\idxcode{abort}}% -\indexlibraryglobal{abort}% -\indextext{termination!program}% -Calling the function \tcode{std::abort()} declared in -\libheaderref{cstdlib} terminates the program without executing any destructors -and without calling -the functions passed to \tcode{std::atexit()} or \tcode{std::at_quick_exit()}.% -\indextext{program!termination|)} +struct S { void (&ref)(); } s{f}; // OK, value is TU-local +constexpr extern struct W { S &s; } wrap{s}; // OK, value is not TU-local -\rSec3[except.terminate]{The \tcode{std::terminate} function} +static auto x = []{f();}; // OK +auto x2 = x; // error: the closure type is TU-local +int y = ([]{f();}(),0); // error: the closure type is not TU-local +int y2 = (x,0); // OK -\pnum -\indextext{\idxcode{terminate}}% -In some situations the \Cpp{} runtime encounters an error that cannot be recovered, -such as when an exception is not handled, or a thread is destroyed while still running. -In such cases, -the function \tcode{std::terminate} is invoked\iref{exception.terminate}. -\begin{note} -These situations are: -\indextext{\idxcode{terminate}!called}% -\begin{itemize} -\item% -when initialization of a non-block -variable with static or thread storage duration\iref{basic.start.dynamic} -exits via an exception, or - -\item% -when destruction of an object with static or thread storage duration exits -via an exception\iref{basic.start.term}, or - -\item% -when a -\grammarterm{throw-expression}\iref{expr.throw} -with no operand attempts to rethrow an exception and no exception is being -handled\iref{except.throw}, or - -\item% -when the exception handling mechanism, after completing -the initialization of the exception object -but before -activation of a handler for the exception\iref{except.throw}, -calls a function that exits -via an exception, or - -\item% -when the destruction of an object during stack unwinding\iref{except.ctor} -terminates by throwing an exception, or - -\item when the search for a handler\iref{except.handle} encounters the -outermost block of a function -with a non-throwing exception specification, or - -\item% -when the exception handling mechanism cannot find a handler for a thrown exception\iref{except.handle}, or - -\item% -when execution of a function registered with -\tcode{std::atexit} or \tcode{std::at_quick_exit} -exits via an exception\iref{support.start.term}, or - -\item% -when the function \tcode{std::nested_exception::rethrow_nested} is called for an object -that has captured no exception\iref{except.nested}, or - -\item% -for a parallel algorithm whose \tcode{ExecutionPolicy} specifies such -behavior\iref{execpol.seq,execpol.par,execpol.parunseq}, -when execution of an element access function\iref{algorithms.parallel.defns} -of the parallel algorithm exits via an exception\iref{algorithms.parallel.exceptions}, or - -\item% -when a callback invocation exits via an exception -when requesting stop on -a \tcode{std::stop_source} or -a \tcode{std::in\-place_stop_source}\iref{stopsource.mem,stopsource.inplace.mem}, -or in the constructor of -\tcode{std::stop_callback} or -\tcode{std::inplace_stop_callback}\iref{stopcallback.cons,stopcallback.inplace.cons} -when a callback invocation exits via an exception, or - -\item% -when execution of the initial function of a thread exits via -an exception\iref{thread.thread.constr}, or - -\item% -when the destructor or the move assignment operator is invoked on an object -of type \tcode{std::thread} that refers to -a joinable thread\iref{thread.thread.destr,thread.thread.assign}, or - -\item% -when a call to a \tcode{wait()}, \tcode{wait_until()}, or \tcode{wait_for()} -function on a condition variable\iref{thread.condition.condvar,thread.condition.condvarany} -fails to meet a postcondition, or - -\item% -when a \tcode{run_loop} object is destroyed -that is still in the \tcode{running} state\iref{exec.run.loop}, or - -\item% -when \tcode{unhandled_stopped} is called on -a \tcode{with_awaitable_senders} object\iref{exec.with.awaitable.senders} -whose continuation is not a handle to a coroutine -whose promise type has an \tcode{unhandled_stopped} member function. +namespace N { + struct A {}; + void adl(A); + static void adl(int); +} +void adl(double); -\end{itemize} -\end{note} +inline void h(auto x) { adl(x); } // OK, but certain specializations are exposures +\end{codeblocktu} +\begin{codeblocktu}{Translation unit \#2} +module A; +void other() { + g<0>(); // OK, specialization is explicitly instantiated + g<1>(); // error: instantiation uses TU-local \tcode{its} + h(N::A{}); // error: overload set contains TU-local \tcode{N::adl(int)} + h(0); // OK, calls \tcode{adl(double)} + adl(N::A{}); // OK; \tcode{N::adl(int)} not found, calls \tcode{N::adl(N::A)} + fr(); // OK, calls \tcode{f} + constexpr auto ptr = fr; // error: \tcode{fr} is not usable in constant expressions here +} +\end{codeblocktu} +\end{example} -\pnum -In the situation where no matching handler is found, it is -\impldef{stack unwinding before invocation of \tcode{std::terminate}} -whether or not the stack is unwound -before \tcode{std::terminate} is invoked. -In the situation where the search for a handler\iref{except.handle} encounters the -outermost block of a function -with a non-throwing exception specification, it is -\impldef{whether stack is unwound before invoking the function \tcode{std::terminate} -when a \tcode{noexcept} specification is violated} -whether the stack is unwound, unwound partially, or not unwound at all -before the function \tcode{std::terminate} is invoked. -In all other situations, the stack shall not be unwound before -the function \tcode{std::terminate} -is invoked. -An implementation is not permitted to finish stack unwinding -prematurely based on a determination that the unwind process -will eventually cause an invocation of the function -\tcode{std::terminate}. -\indextext{program execution|)} \indextext{conventions!lexical|)} diff --git a/source/preprocessor.tex b/source/preprocessor.tex new file mode 100644 index 0000000000..c149eed4d5 --- /dev/null +++ b/source/preprocessor.tex @@ -0,0 +1,2009 @@ +%!TEX root = std.tex +\rSec0[cpp]{Preprocessing directives}% +\indextext{preprocessing directive|(} + +\indextext{compiler control line|see{preprocessing directive}}% +\indextext{control line|see{preprocessing directive}}% +\indextext{directive, preprocessing|see{preprocessing directive}} + +\gramSec[gram.cpp]{Preprocessing directives} + +\rSec1[cpp.pre]{Preamble} + +\begin{bnf} +\nontermdef{preprocessing-file}\br + \opt{group}\br + module-file +\end{bnf} + +\begin{bnf} +\nontermdef{module-file}\br + \opt{pp-global-module-fragment} pp-module \opt{group} \opt{pp-private-module-fragment} +\end{bnf} + +\begin{bnf} +\nontermdef{pp-global-module-fragment}\br + \keyword{module} \terminal{;} new-line \opt{group} +\end{bnf} + +\begin{bnf} +\nontermdef{pp-private-module-fragment}\br + \keyword{module} \terminal{:} \keyword{private} \terminal{;} new-line \opt{group} +\end{bnf} + +\begin{bnf} +\nontermdef{group}\br + group-part\br + group group-part +\end{bnf} + +\begin{bnf} +\nontermdef{group-part}\br + control-line\br + if-section\br + text-line\br + \terminal{\#} conditionally-supported-directive +\end{bnf} + +\begin{bnf}\obeyspaces +\nontermdef{control-line}\br + \terminal{\# include} pp-tokens new-line\br + pp-import\br + \terminal{\# define } identifier replacement-list new-line\br + \terminal{\# define } identifier lparen \opt{identifier-list} \terminal{)} replacement-list new-line\br + \terminal{\# define } identifier lparen \terminal{... )} replacement-list new-line\br + \terminal{\# define } identifier lparen identifier-list \terminal{, ... )} replacement-list new-line\br + \terminal{\# undef } identifier new-line\br + \terminal{\# line } pp-tokens new-line\br + \terminal{\# error } \opt{pp-tokens} new-line\br + \terminal{\# warning} \opt{pp-tokens} new-line\br + \terminal{\# pragma } \opt{pp-tokens} new-line\br + \terminal{\# }new-line +\end{bnf} + +\begin{bnf} +\nontermdef{if-section}\br + if-group \opt{elif-groups} \opt{else-group} endif-line +\end{bnf} + +\begin{bnf}\obeyspaces +\nontermdef{if-group}\br + \terminal{\# if } constant-expression new-line \opt{group}\br + \terminal{\# ifdef } identifier new-line \opt{group}\br + \terminal{\# ifndef } identifier new-line \opt{group} +\end{bnf} + +\begin{bnf} +\nontermdef{elif-groups}\br + elif-group\br + elif-groups elif-group +\end{bnf} + +\begin{bnf}\obeyspaces +\nontermdef{elif-group}\br + \terminal{\# elif } constant-expression new-line \opt{group}\br + \terminal{\# elifdef } identifier new-line \opt{group}\br + \terminal{\# elifndef} identifier new-line \opt{group} +\end{bnf} + +\begin{bnf}\obeyspaces +\nontermdef{else-group}\br + \terminal{\# else } new-line \opt{group} +\end{bnf} + +\begin{bnf}\obeyspaces +\nontermdef{endif-line}\br + \terminal{\# endif } new-line +\end{bnf} + +\begin{bnf} +\nontermdef{text-line}\br + \opt{pp-tokens} new-line +\end{bnf} + +\begin{bnf} +\nontermdef{conditionally-supported-directive}\br + pp-tokens new-line +\end{bnf} + +\begin{bnf} +\nontermdef{lparen}\br + \descr{a \terminal{(} character not immediately preceded by whitespace} +\end{bnf} + +\begin{bnf} +\nontermdef{identifier-list}\br + identifier\br + identifier-list \terminal{,} identifier +\end{bnf} + +\begin{bnf} +\nontermdef{replacement-list}\br + \opt{pp-tokens} +\end{bnf} + +\begin{bnf} +\nontermdef{pp-tokens}\br + preprocessing-token\br + pp-tokens preprocessing-token +\end{bnf} + +\begin{bnf} +\nontermdef{new-line}\br + \descr{the new-line character} +\end{bnf} + +\pnum +A \defn{preprocessing directive} consists of a sequence of preprocessing tokens +that satisfies the following constraints: +At the start of translation phase 4, +the first token in the sequence, +referred to as a \defnadj{directive-introducing}{token}, +begins with the first character in the source file +(optionally after whitespace containing no new-line characters) or +follows whitespace containing at least one new-line character, +and is + +\begin{itemize} +\item +a \tcode{\#} preprocessing token, or + +\item +an \keyword{import} preprocessing token +immediately followed on the same logical source line by a +\grammarterm{header-name}, +\tcode{<}, +\grammarterm{identifier}, +\grammarterm{string-literal}, or +\tcode{:} +preprocessing token, or + +\item +a \keyword{module} preprocessing token +immediately followed on the same logical source line by an +\grammarterm{identifier}, +\tcode{:}, or +\tcode{;} +preprocessing token, or + +\item +an \keyword{export} preprocessing token +immediately followed on the same logical source line by +one of the two preceding forms. +\end{itemize} + +The last token in the sequence is the first token within the sequence that +is immediately followed by whitespace containing a new-line character. +\begin{footnote} +Thus, +preprocessing directives are commonly called ``lines''. +These ``lines'' have no other syntactic significance, +as all whitespace is equivalent except in certain situations +during preprocessing (see the +\tcode{\#} +character string literal creation operator in~\ref{cpp.stringize}, for example). +\end{footnote} +\begin{note} +A new-line character ends the preprocessing directive even if it occurs +within what would otherwise be an invocation of a function-like macro. +\end{note} + +\begin{example} +\begin{codeblock} +# // preprocessing directive +module ; // preprocessing directive +export module leftpad; // preprocessing directive +import ; // preprocessing directive +export import "squee"; // preprocessing directive +import rightpad; // preprocessing directive +import :part; // preprocessing directive + +module // not a preprocessing directive +; // not a preprocessing directive + +export // not a preprocessing directive +import // not a preprocessing directive +foo; // not a preprocessing directive + +export // not a preprocessing directive +import foo; // preprocessing directive (ill-formed at phase 7) + +import :: // not a preprocessing directive +import -> // not a preprocessing directive +\end{codeblock} +\end{example} + +\pnum +A sequence of preprocessing tokens is only a \grammarterm{text-line} +if it does not begin with a directive-introducing token. +A sequence of preprocessing tokens is only a \grammarterm{conditionally-supported-directive} +if it does not begin with any of the directive names +appearing after a \tcode{\#} in the syntax. +A \grammarterm{conditionally-supported-directive} is +conditionally-supported with +\impldef{additional supported forms of preprocessing directive} +semantics. + +\pnum +At the start of phase 4 of translation, +the \grammarterm{group} of a \grammarterm{pp-global-module-fragment} shall +contain neither a \grammarterm{text-line} nor a \grammarterm{pp-import}. + +\pnum +When in a group that is skipped\iref{cpp.cond}, the directive +syntax is relaxed to allow any sequence of preprocessing tokens to occur between +the directive name and the following new-line character. + +\pnum +The only whitespace characters that shall appear +between preprocessing tokens +within a preprocessing directive +(from just after the directive-introducing token +through just before the terminating new-line character) +are space and horizontal-tab +(including spaces that have replaced comments +or possibly other whitespace characters +in translation phase 3). + +\pnum +The implementation can +process and skip sections of source files conditionally, +include other source files, +import macros from header units, +and replace macros. +These capabilities are called +\defn{preprocessing}, +because conceptually they occur +before translation of the resulting translation unit. + +\pnum +The preprocessing tokens within a preprocessing directive +are not subject to macro expansion unless otherwise stated. + +\begin{example} +In: +\begin{codeblock} +#define EMPTY +EMPTY # include +\end{codeblock} +the sequence of preprocessing tokens on the second line is \textit{not} +a preprocessing directive, because it does not begin with a \tcode{\#} at the start of +translation phase 4, even though it will do so after the macro \tcode{EMPTY} +has been replaced. +\end{example} + +\rSec1[cpp.module]{Module directive} +\indextext{preprocessing directive!module}% + +\begin{bnf} +\nontermdef{pp-module}\br + \opt{\keyword{export}} \keyword{module} \opt{pp-tokens} \terminal{;} new-line +\end{bnf} + +\pnum +A \grammarterm{pp-module} shall not +appear in a context where \tcode{module} +or (if it is the first token of the \grammarterm{pp-module}) \tcode{export} +is an identifier defined as an object-like macro. + +\pnum +The \grammarterm{pp-tokens}, if any, of a \grammarterm{pp-module} +shall be of the form: +\begin{ncsimplebnf} +pp-module-name \opt{pp-module-partition} \opt{pp-tokens} +\end{ncsimplebnf} +where the \grammarterm{pp-tokens} (if any) shall not begin with +a \tcode{(} preprocessing token and +the grammar non-terminals are defined as: +\begin{ncbnf} +\nontermdef{pp-module-name}\br + \opt{pp-module-name-qualifier} identifier +\end{ncbnf} +\begin{ncbnf} +\nontermdef{pp-module-partition}\br + \terminal{:} \opt{pp-module-name-qualifier} identifier +\end{ncbnf} +\begin{ncbnf} +\nontermdef{pp-module-name-qualifier}\br + identifier \terminal{.}\br + pp-module-name-qualifier identifier \terminal{.} +\end{ncbnf} +No \grammarterm{identifier} in +the \grammarterm{pp-module-name} or \grammarterm{pp-module-partition} +shall currently be defined as an object-like macro. + +\pnum +Any preprocessing tokens after the \tcode{module} preprocessing token +in the \tcode{module} directive are processed just as in normal text. +\begin{note} +Each identifier currently defined as a macro name +is replaced by its replacement list of preprocessing tokens. +\end{note} + +\pnum +The \tcode{module} and \tcode{export} (if it exists) preprocessing tokens +are replaced by the \grammarterm{module-keyword} and +\grammarterm{export-keyword} preprocessing tokens respectively. +\begin{note} +This makes the line no longer a directive +so it is not removed at the end of phase 4. +\end{note} + +\rSec1[cpp.import]{Header unit importation} +\indextext{header unit!preprocessing}% +\indextext{preprocessing directive!import}% +\indextext{macro!import|(}% + +\begin{bnf} +\nontermdef{pp-import}\br + \opt{\keyword{export}} \keyword{import} header-name \opt{pp-tokens} \terminal{;} new-line\br + \opt{\keyword{export}} \keyword{import} header-name-tokens \opt{pp-tokens} \terminal{;} new-line\br + \opt{\keyword{export}} \keyword{import} pp-tokens \terminal{;} new-line +\end{bnf} + +\pnum +A \grammarterm{pp-import} shall not +appear in a context where \tcode{import} +or (if it is the first token of the \grammarterm{pp-import}) \tcode{export} +is an identifier defined as an object-like macro. + +\pnum +The preprocessing tokens after the \tcode{import} preprocessing token +in the \tcode{import} \grammarterm{control-line} +are processed just as in normal text +(i.e., each identifier currently defined as a macro name +is replaced by its replacement list of preprocessing tokens). +\begin{note} +An \tcode{import} directive +matching the first two forms of a \grammarterm{pp-import} +instructs the preprocessor to import macros +from the header unit\iref{module.import} +denoted by the \grammarterm{header-name}, +as described below. +\end{note} +\indextext{point of!macro import|see{macro, point of import}}% +The \defnx{point of macro import}{macro!point of import} for the +first two forms of \grammarterm{pp-import} is +immediately after the \grammarterm{new-line} terminating +the \grammarterm{pp-import}. +The last form of \grammarterm{pp-import} is only considered +if the first two forms did not match, and +does not have a point of macro import. + +\pnum +If a \grammarterm{pp-import} is produced by source file inclusion +(including by the rewrite produced +when a \tcode{\#include} directive names an importable header) +while processing the \grammarterm{group} of a \grammarterm{module-file}, +the program is ill-formed. + +\pnum +In all three forms of \grammarterm{pp-import}, +the \tcode{import} and \tcode{export} (if it exists) preprocessing tokens +are replaced by the \grammarterm{import-keyword} and +\grammarterm{export-keyword} preprocessing tokens respectively. +\begin{note} +This makes the line no longer a directive +so it is not removed at the end of phase 4. +\end{note} +Additionally, in the second form of \grammarterm{pp-import}, +a \grammarterm{header-name} token is formed as if +the \grammarterm{header-name-tokens} +were the \grammarterm{pp-tokens} of a \tcode{\#include} directive. +The \grammarterm{header-name-tokens} are replaced by +the \grammarterm{header-name} token. +\begin{note} +This ensures that imports are treated consistently by +the preprocessor and later phases of translation. +\end{note} + +\pnum +Each \tcode{\#define} directive encountered when preprocessing +each translation unit in a program results in a distinct +\defnx{macro definition}{macro!definition}. +\begin{note} +A predefined macro name\iref{cpp.predefined} +is not introduced by a \tcode{\#define} directive. +Implementations providing mechanisms to predefine additional macros +are encouraged to not treat them +as being introduced by a \tcode{\#define} directive. +\end{note} +Each macro definition has at most one point of definition in +each translation unit and at most one point of undefinition, as follows: +\begin{itemize} +\item +\indextext{point of!macro definition|see{macro, point of definition}}% +The \defnx{point of definition}{macro!point of definition} +of a macro definition within a translation unit $T$ is +\begin{itemize} +\item +if the \tcode{\#define} directive of the macro definition occurs within $T$, +the point at which that directive occurs, or otherwise, +\item +if the macro name is not lexically identical to a keyword\iref{lex.key} +or to the \grammarterm{identifier}{s} \tcode{module} or \tcode{import}, +the first point of macro import in $T$ of a header unit +containing a point of definition for the macro definition, if any. +\end{itemize} +In the latter case, the macro is said +to be \defnx{imported}{macro!import} from the header unit. + +\item +\indextext{point of!macro undefinition|see{macro, point of undefinition}}% +The \defnx{point of undefinition}{macro!point of undefinition} +of a macro definition within a translation unit +is the first point at which a \tcode{\#undef} directive naming the macro occurs +after its point of definition, or the first point +of macro import of a header unit containing a point of undefinition for the +macro definition, whichever (if any) occurs first. +\end{itemize} + +\pnum +\indextext{active macro directive|see{macro, active}}% +A macro directive is \defnx{active}{macro!active} at a source location +if it has a point of definition in that translation unit preceding the location, +and does not have a point of undefinition in that translation unit preceding +the location. + +\pnum +If a macro would be replaced or redefined, and multiple macro definitions +are active for that macro name, the active macro definitions shall all be +valid redefinitions of the same macro\iref{cpp.replace}. +\begin{note} +The relative order of \grammarterm{pp-import}{s} has no bearing on whether a +particular macro definition is active. +\end{note} + +\pnum +\begin{example} +\begin{codeblocktu}{Importable header \tcode{"a.h"}} +#define X 123 // \#1 +#define Y 45 // \#2 +#define Z a // \#3 +#undef X // point of undefinition of \#1 in \tcode{"a.h"} +\end{codeblocktu} + +\begin{codeblocktu}{Importable header \tcode{"b.h"}} +import "a.h"; // point of definition of \#1, \#2, and \#3, point of undefinition of \#1 in \tcode{"b.h"} +#define X 456 // OK, \#1 is not active +#define Y 6 // error: \#2 is active +\end{codeblocktu} + +\begin{codeblocktu}{Importable header \tcode{"c.h"}} +#define Y 45 // \#4 +#define Z c // \#5 +\end{codeblocktu} + +\begin{codeblocktu}{Importable header \tcode{"d.h"}} +import "c.h"; // point of definition of \#4 and \#5 in \tcode{"d.h"} +\end{codeblocktu} + +\begin{codeblocktu}{Importable header \tcode{"e.h"}} +import "a.h"; // point of definition of \#1, \#2, and \#3, point of undefinition of \#1 in \tcode{"e.h"} +import "d.h"; // point of definition of \#4 and \#5 in \tcode{"e.h"} +int a = Y; // OK, active macro definitions \#2 and \#4 are valid redefinitions +int c = Z; // error: active macro definitions \#3 and \#5 are not valid redefinitions of \tcode{Z} +\end{codeblocktu} + +\begin{codeblocktu}{Module unit \tcode{f}} +export module f; +export import "a.h"; + +int a = Y; // OK +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \tcode{\#1}} +import f; +int x = Y; // error: \tcode{Y} is neither a defined macro nor a declared name +\end{codeblocktu} +\end{example} +\indextext{macro!import|)} + +\rSec1[cpp.null]{Null directive}% +\indextext{preprocessing directive!null} + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\#} new-line +\end{ncsimplebnf} +has no effect. + +\rSec1[cpp.error]{Diagnostic directives}% +\indextext{preprocessing directive!error}% +\indextext{preprocessing directive!diagnostic}% +\indextext{preprocessing directive!warning}% +\indextext{\idxcode{\#error}|see{preprocessing directive, error}} + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# error} \opt{pp-tokens} new-line +\end{ncsimplebnf} +renders the program ill-formed. +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# warning} \opt{pp-tokens} new-line +\end{ncsimplebnf} +requires the implementation to produce at least one diagnostic message +for the preprocessing translation unit\iref{intro.compliance.general}. +\recommended +Any diagnostic message caused by either of these directives +should include the specified sequence of preprocessing tokens. + +\rSec1[cpp.line]{Line control}% +\indextext{preprocessing directive!line control}% +\indextext{\idxcode{\#line}|see{preprocessing directive, line control}} + +\pnum +The \grammarterm{string-literal} of a +\tcode{\#line} +directive, if present, +shall be a character string literal. + +\pnum +The +\defn{line number} +of the current source line is one greater than +the number of new-line characters read or introduced +in translation phase 1\iref{lex.phases} +while processing the source file to the current token. + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# line} digit-sequence new-line +\end{ncsimplebnf} +causes the implementation to behave as if +the following sequence of source lines begins with a +source line that has a line number as specified +by the digit sequence (interpreted as a decimal integer). +If the digit sequence specifies zero +or a number greater than 2147483647, +the behavior is undefined. + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# line} digit-sequence \terminal{"} \opt{s-char-sequence} \terminal{"} new-line +\end{ncsimplebnf} +sets the presumed line number similarly and changes the +presumed name of the source file to be the contents +of the character string literal. + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# line} pp-tokens new-line +\end{ncsimplebnf} +(that does not match one of the two previous forms) +is permitted. +The preprocessing tokens after +\tcode{line} +on the directive are processed just as in normal text +(each identifier currently defined as a macro name is replaced by its +replacement list of preprocessing tokens). +If the directive resulting after all replacements does not match +one of the two previous forms, the behavior is undefined; +otherwise, the result is processed as appropriate. + +\rSec1[cpp.pragma]{Pragma directive}% +\indextext{preprocessing directive!pragma}% +\indextext{\idxcode{\#pragma}|see{preprocessing directive, pragma}} + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# pragma} \opt{pp-tokens} new-line +\end{ncsimplebnf} +causes the implementation to behave +in an \impldef{\tcode{\#pragma}} manner. +The behavior may cause translation to fail or cause the translator or +the resulting program to behave in a non-conforming manner. +Any pragma that is not recognized by the implementation is ignored. + +\rSec1[cpp.pragma.op]{Pragma operator}% +\indextext{macro!pragma operator}% +\indextext{operator!pragma|see{macro, pragma operator}} + +\pnum +A unary operator expression of the form: +\begin{ncbnf} +\terminal{_Pragma} \terminal{(} string-literal \terminal{)} +\end{ncbnf} +is processed as follows: The \grammarterm{string-literal} is \defnx{destringized}{destringization} +by deleting the \tcode{L} prefix, if present, deleting the leading and trailing +double-quotes, replacing each escape sequence \tcode{\textbackslash"} by a double-quote, and +replacing each escape sequence \tcode{\textbackslash\textbackslash} by a single +backslash. The resulting sequence of characters is processed through translation phase 3 +to produce preprocessing tokens that are executed as if they were the +\grammarterm{pp-tokens} in a pragma directive. The original four preprocessing +tokens in the unary operator expression are removed. + +\pnum +\begin{example} +\begin{codeblock} +#pragma listing on "..\listing.dir" +\end{codeblock} +can also be expressed as: +\begin{codeblock} +_Pragma ( "listing on \"..\\listing.dir\"" ) +\end{codeblock} +The latter form is processed in the same way whether it appears literally +as shown, or results from macro replacement, as in: +\begin{codeblock} +#define LISTING(x) PRAGMA(listing on #x) +#define PRAGMA(x) _Pragma(#x) + +LISTING( ..\listing.dir ) +\end{codeblock} +\end{example} +\indextext{preprocessing directive|)} + +\rSec1[cpp.replace]{Macro replacement}% + +\rSec2[cpp.replace.general]{General}% +\indextext{macro!replacement|(}% +\indextext{replacement!macro|see{macro, replacement}}% +\indextext{preprocessing directive!macro replacement|see{macro, replacement}} + +\pnum +\indextext{macro!replacement list}% +Two replacement lists are identical if and only if +the preprocessing tokens in both have +the same number, ordering, spelling, and whitespace separation, +where all whitespace separations are considered identical. + +\pnum +An identifier currently defined as an +\indextext{macro!object-like}% +object-like macro (see below) may be redefined by another +\tcode{\#define} +preprocessing directive provided that the second definition is an +object-like macro definition and the two replacement lists +are identical, otherwise the program is ill-formed. +Likewise, an identifier currently defined as a +\indextext{macro!function-like}% +function-like macro (see below) may be redefined by another +\tcode{\#define} +preprocessing directive provided that the second definition is a +function-like macro definition that has the same number and spelling +of parameters, +and the two replacement lists are identical, +otherwise the program is ill-formed. + +\pnum +\begin{example} +The following sequence is valid: +\begin{codeblock} +#define OBJ_LIKE (1-1) +#define OBJ_LIKE @\tcode{/* whitespace */ (1-1) /* other */}@ +#define FUNC_LIKE(a) ( a ) +#define FUNC_LIKE( a )( @\tcode{/* note the whitespace */ \textbackslash}@ + a @\tcode{/* other stuff on this line}@ + @\tcode{*/}@ ) +\end{codeblock} +But the following redefinitions are invalid: +\begin{codeblock} +#define OBJ_LIKE (0) // different token sequence +#define OBJ_LIKE (1 - 1) // different whitespace +#define FUNC_LIKE(b) ( a ) // different parameter usage +#define FUNC_LIKE(b) ( b ) // different parameter spelling +\end{codeblock} +\end{example} + +\pnum +\indextext{macro!replacement list}% +There shall be whitespace between the identifier and the replacement list +in the definition of an object-like macro. + +\pnum +If the \grammarterm{identifier-list} in the macro definition does not end with +an ellipsis, the number of arguments (including those arguments consisting +of no preprocessing tokens) +in an invocation of a function-like macro shall +equal the number of parameters in the macro definition. +Otherwise, there shall be at least as many arguments in the invocation as there are +parameters in the macro definition (excluding the \tcode{...}). There +shall exist a +\tcode{)} +preprocessing token that terminates the invocation. + +\pnum +\indextext{__va_args__@\mname{VA_ARGS}}% +\indextext{__va_opt__@\mname{VA_OPT}}% +The identifiers \mname{VA_ARGS} and \mname{VA_OPT} +shall occur only in the \grammarterm{replacement-list} +of a function-like macro that uses the ellipsis notation in the parameters. + +\pnum +A parameter identifier in a function-like macro +shall be uniquely declared within its scope. + +\pnum +The identifier immediately following the +\tcode{define} +is called the +\indextext{name!macro|see{macro, name}}% +\defnx{macro name}{macro!name}. +There is one name space for macro names. +Any whitespace characters preceding or following the +replacement list of preprocessing tokens are not considered +part of the replacement list for either form of macro. + +\pnum +If a +\indextext{\#\#0 operator@\tcode{\#} operator} +\tcode{\#} +preprocessing token, +followed by an identifier, +occurs lexically +at the point at which a preprocessing directive can begin, +the identifier is not subject to macro replacement. + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# define} identifier replacement-list new-line +\indextext{\idxcode{\#define}}% +\end{ncsimplebnf} +defines an +\defnadj{object-like}{macro} that +causes each subsequent instance of the macro name +\begin{footnote} +Since, by macro-replacement time, +all \grammarterm{character-literal}s and \grammarterm{string-literal}s are preprocessing tokens, +not sequences possibly containing identifier-like subsequences +(see \ref{lex.phases}, translation phases), +they are never scanned for macro names or parameters. +\end{footnote} +to be replaced by the replacement list of preprocessing tokens +that constitute the remainder of the directive. +\begin{footnote} +An alternative token\iref{lex.operators} is not an identifier, +even when its spelling consists entirely of letters and underscores. +Therefore it is not possible to define a macro +whose name is the same as that of an alternative token. +\end{footnote} +The replacement list is then rescanned for more macro names as +specified below. + +\pnum +\begin{example} +The simplest use of this facility is to define a ``manifest constant'', +as in +\begin{codeblock} +#define TABSIZE 100 +int table[TABSIZE]; +\end{codeblock} +\end{example} + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# define} identifier lparen \opt{identifier-list} \terminal{)} replacement-list new-line\br +\terminal{\# define} identifier lparen \terminal{...} \terminal{)} replacement-list new-line\br +\terminal{\# define} identifier lparen identifier-list \terminal{, ...} \terminal{)} replacement-list new-line +\end{ncsimplebnf} +defines a \defnadj{function-like}{macro} +with parameters, whose use is +similar syntactically to a function call. +The parameters +\indextext{parameter!macro}% +are specified by the optional list of identifiers. +Each subsequent instance of the function-like macro name followed by a +\tcode{(} +as the next preprocessing token +introduces the sequence of preprocessing tokens that is replaced +by the replacement list in the definition +(an invocation of the macro). +\indextext{invocation!macro}% +The replaced sequence of preprocessing tokens is terminated by the matching +\tcode{)} +preprocessing token, skipping intervening matched pairs of left and +right parenthesis preprocessing tokens. +Within the sequence of preprocessing tokens making up an invocation +of a function-like macro, +new-line is considered a normal whitespace character. + +\pnum +\indextext{macro!function-like!arguments}% +The sequence of preprocessing tokens +bounded by the outside-most matching parentheses +forms the list of arguments for the function-like macro. +The individual arguments within the list +are separated by comma preprocessing tokens, +but comma preprocessing tokens between matching +inner parentheses do not separate arguments. +If there are sequences of preprocessing tokens within the list of +arguments that would otherwise act as preprocessing directives, +\begin{footnote} +A \grammarterm{conditionally-supported-directive} is a preprocessing directive regardless of whether the implementation supports it. +\end{footnote} +the behavior is undefined. + +\pnum +\begin{example} +The following defines a function-like +macro whose value is the maximum of its arguments. +It has the disadvantages of evaluating one or the other of its arguments +a second time +(including +\indextext{side effects}% +side effects) +and generating more code than a function if invoked several times. +It also cannot have its address taken, +as it has none. + +\begin{codeblock} +#define max(a, b) ((a) > (b) ? (a) : (b)) +\end{codeblock} + +The parentheses ensure that the arguments and +the resulting expression are bound properly. +\end{example} + +\pnum +\indextext{macro!function-like!arguments}% +If there is a \tcode{...} immediately preceding the \tcode{)} in the +function-like macro +definition, then the trailing arguments (if any), including any separating comma preprocessing +tokens, are merged to form a single item: the \defn{variable arguments}. The number of +arguments so combined is such that, following merger, the number of arguments is +either equal to or +one more than the number of parameters in the macro definition (excluding the +\tcode{...}). + +\rSec2[cpp.subst]{Argument substitution}% +\indextext{macro!argument substitution}% +\indextext{argument substitution|see{macro, argument substitution}}% + +\indextext{__va_opt__@\mname{VA_OPT}}% +\begin{bnf} +\nontermdef{va-opt-replacement}\br + \terminal{\mname{VA_OPT} (} \opt{pp-tokens} \terminal{)} +\end{bnf} + +\pnum +After the arguments for the invocation of a function-like macro have +been identified, argument substitution takes place. +For each parameter in the replacement list that is neither +preceded by a \tcode{\#} or \tcode{\#\#} preprocessing token nor +followed by a \tcode{\#\#} preprocessing token, the preprocessing tokens +naming the parameter are replaced by a token sequence determined as follows: +\begin{itemize} +\item + If the parameter is of the form \grammarterm{va-opt-replacement}, + the replacement preprocessing tokens are the + preprocessing token sequence for the corresponding argument, + as specified below. +\item + Otherwise, the replacement preprocessing tokens are the + preprocessing tokens of corresponding argument after all + macros contained therein have been expanded. The argument's + preprocessing tokens are completely macro replaced before + being substituted as if they formed the rest of the preprocessing + file with no other preprocessing tokens being available. +\end{itemize} +\begin{example} +\begin{codeblock} +#define LPAREN() ( +#define G(Q) 42 +#define F(R, X, ...) __VA_OPT__(G R X) ) +int x = F(LPAREN(), 0, <:-); // replaced by \tcode{int x = 42;} +\end{codeblock} +\end{example} + +\pnum +\indextext{__va_args__@\mname{VA_ARGS}}% +An identifier \mname{VA_ARGS} that occurs in the replacement list +shall be treated as if it were a parameter, and the variable arguments shall form +the preprocessing tokens used to replace it. + +\pnum +\begin{example} +\begin{codeblock} +#define debug(...) fprintf(stderr, @\mname{VA_ARGS}@) +#define showlist(...) puts(#@\mname{VA_ARGS}@) +#define report(test, ...) ((test) ? puts(#test) : printf(@\mname{VA_ARGS}@)) +debug("Flag"); +debug("X = %d\n", x); +showlist(The first, second, and third items.); +report(x>y, "x is %d but y is %d", x, y); +\end{codeblock} +results in +\begin{codeblock} +fprintf(stderr, "Flag"); +fprintf(stderr, "X = %d\n", x); +puts("The first, second, and third items."); +((x>y) ? puts("x>y") : printf("x is %d but y is %d", x, y)); +\end{codeblock} +\end{example} + +\pnum +\indextext{__va_opt__@\mname{VA_OPT}}% +The identifier \mname{VA_OPT} +shall always occur as part of the preprocessing token sequence +\grammarterm{va-opt-replacement}; +its closing \tcode{)} is determined by skipping +intervening pairs of matching left and right parentheses +in its \grammarterm{pp-tokens}. +The \grammarterm{pp-tokens} of a \grammarterm{va-opt-replacement} +shall not contain \mname{VA_OPT}. +If the \grammarterm{pp-tokens} would be ill-formed +as the replacement list of the current function-like macro, +the program is ill-formed. +A \grammarterm{va-opt-replacement} is treated as if it were a parameter, +and the preprocessing token sequence for the corresponding +argument is defined as follows. +If the substitution of \mname{VA_ARGS} as neither an operand +of \tcode{\#} nor \tcode{\#\#} consists of no preprocessing tokens, +the argument consists of +a single placemarker preprocessing token\iref{cpp.concat,cpp.rescan}. +Otherwise, the argument consists of +the results of the expansion of the contained \grammarterm{pp-tokens} +as the replacement list of the current function-like macro +before removal of placemarker tokens, rescanning, and further replacement. +\begin{note} +The placemarker tokens are removed before stringization\iref{cpp.stringize}, +and can be removed by rescanning and further replacement\iref{cpp.rescan}. +\end{note} +\begin{example} +\begin{codeblock} +#define F(...) f(0 __VA_OPT__(,) __VA_ARGS__) +#define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__) +#define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ }) +#define EMP + +F(a, b, c) // replaced by \tcode{f(0, a, b, c)} +F() // replaced by \tcode{f(0)} +F(EMP) // replaced by \tcode{f(0)} + +G(a, b, c) // replaced by \tcode{f(0, a, b, c)} +G(a, ) // replaced by \tcode{f(0, a)} +G(a) // replaced by \tcode{f(0, a)} + +SDEF(foo); // replaced by \tcode{S foo;} +SDEF(bar, 1, 2); // replaced by \tcode{S bar = \{ 1, 2 \};} + +#define H1(X, ...) X __VA_OPT__(##) __VA_ARGS__ // error: \tcode{\#\#} may not appear at + // the beginning of a replacement list\iref{cpp.concat} + +#define H2(X, Y, ...) __VA_OPT__(X ## Y,) __VA_ARGS__ +H2(a, b, c, d) // replaced by \tcode{ab, c, d} + +#define H3(X, ...) #__VA_OPT__(X##X X##X) +H3(, 0) // replaced by \tcode{""} + +#define H4(X, ...) __VA_OPT__(a X ## X) ## b +H4(, 1) // replaced by \tcode{a b} + +#define H5A(...) __VA_OPT__()@\tcode{/**/}@__VA_OPT__() +#define H5B(X) a ## X ## b +#define H5C(X) H5B(X) +H5C(H5A()) // replaced by \tcode{ab} +\end{codeblock} +\end{example} + +\rSec2[cpp.stringize]{The \tcode{\#} operator}% +\indextext{\#\#0 operator@\tcode{\#} operator}% +\indextext{stringize|see{\tcode{\#} operator}} + +\pnum +Each +\tcode{\#} +preprocessing token in the replacement list for a function-like +macro shall be followed by a parameter as the next preprocessing +token in the replacement list. + +\pnum +A \defn{character string literal} is a \grammarterm{string-literal} with no prefix. +If, in the replacement list, a parameter is immediately +preceded by a +\tcode{\#} +preprocessing token, +both are replaced by a single character string literal preprocessing token that +contains the spelling of the preprocessing token sequence for the +corresponding argument (excluding placemarker tokens). +Let the \defn{stringizing argument} be the preprocessing token sequence +for the corresponding argument with placemarker tokens removed. +Each occurrence of whitespace between the stringizing argument's preprocessing +tokens becomes a single space character in the character string literal. +Whitespace before the first preprocessing token and after the last +preprocessing token comprising the stringizing argument is deleted. +Otherwise, the original spelling of each preprocessing token in the +stringizing argument is retained in the character string literal, +except for special handling for producing the spelling of +\grammarterm{string-literal}s and \grammarterm{character-literal}s: +a +\tcode{\textbackslash} +character is inserted before each +\tcode{"} +and +\tcode{\textbackslash} +character of a \grammarterm{character-literal} or \grammarterm{string-literal} +(including the delimiting +\tcode{"} +characters). +If the replacement that results is not a valid character string literal, +the behavior is undefined. The character string literal corresponding to +an empty stringizing argument is \tcode{""}. +The order of evaluation of +\tcode{\#} +and +\tcode{\#\#} +operators is unspecified. + +\rSec2[cpp.concat]{The \tcode{\#\#} operator}% +\indextext{\#\#1 operator@\tcode{\#\#} operator}% +\indextext{concatenation!macro argument|see{\tcode{\#\#} operator}} + +\pnum +A +\tcode{\#\#} +preprocessing token shall not occur at the beginning or +at the end of a replacement list for either form +of macro definition. + +\pnum +If, in the replacement list of a function-like macro, a parameter is +immediately preceded or followed by a +\tcode{\#\#} +preprocessing token, the parameter is replaced by the +corresponding argument's preprocessing token sequence; however, if an argument consists of no preprocessing tokens, the parameter is +replaced by a placemarker preprocessing token instead. +\begin{footnote} +Placemarker preprocessing tokens do not appear in the syntax +because they are temporary entities that exist only within translation phase 4. +\end{footnote} + +\pnum +For both object-like and function-like macro invocations, before the +replacement list is reexamined for more macro names to replace, +each instance of a +\tcode{\#\#} +preprocessing token in the replacement list +(not from an argument) is deleted and the +preceding preprocessing token is concatenated +with the following preprocessing token. +Placemarker preprocessing tokens are handled specially: concatenation +of two placemarkers results in a single placemarker preprocessing token, and +concatenation of a placemarker with a non-placemarker preprocessing token results +in the non-placemarker preprocessing token. +\begin{note} +Concatenation can form +a \grammarterm{universal-character-name}\iref{lex.charset}. +\end{note} +If the result is not a valid preprocessing token, +the behavior is undefined. +The resulting token is available for further macro replacement. +The order of evaluation of +\tcode{\#\#} +operators is unspecified. + +\pnum +\begin{example} +The sequence +\begin{codeblock} +#define str(s) # s +#define xstr(s) str(s) +#define debug(s, t) printf("x" # s "= %d, x" # t "= %s", @\textbackslash@ + x ## s, x ## t) +#define INCFILE(n) vers ## n +#define glue(a, b) a ## b +#define xglue(a, b) glue(a, b) +#define HIGHLOW "hello" +#define LOW LOW ", world" + +debug(1, 2); +fputs(str(strncmp("abc@\textbackslash@0d", "abc", '@\textbackslash@4') // this goes away + == 0) str(: @\atsign\textbackslash@n), s); +#include xstr(INCFILE(2).h) +glue(HIGH, LOW); +xglue(HIGH, LOW) +\end{codeblock} +results in +\begin{codeblock} +printf("x" "1" "= %d, x" "2" "= %s", x1, x2); +fputs("strncmp(@\textbackslash@"abc@\textbackslash\textbackslash@0d@\textbackslash@", @\textbackslash@"abc@\textbackslash@", '@\textbackslash\textbackslash@4') == 0" ": @\atsign\textbackslash@n", s); +#include "vers2.h" @\textrm{(\textit{after macro replacement, before file access})}@ +"hello"; +"hello" ", world" +\end{codeblock} +or, after concatenation of the character string literals, +\begin{codeblock} +printf("x1= %d, x2= %s", x1, x2); +fputs("strncmp(@\textbackslash@"abc@\textbackslash\textbackslash@0d@\textbackslash@", @\textbackslash@"abc@\textbackslash@", '@\textbackslash\textbackslash@4') == 0: @\atsign\textbackslash@n", s); +#include "vers2.h" @\textrm{(\textit{after macro replacement, before file access})}@ +"hello"; +"hello, world" +\end{codeblock} + +Space around the \tcode{\#} and \tcode{\#\#} tokens in the macro definition +is optional. +\end{example} + +\pnum +\begin{example} +In the following fragment: + +\begin{codeblock} +#define hash_hash # ## # +#define mkstr(a) # a +#define in_between(a) mkstr(a) +#define join(c, d) in_between(c hash_hash d) +char p[] = join(x, y); // equivalent to \tcode{char p[] = "x \#\# y";} +\end{codeblock} + +The expansion produces, at various stages: + +\begin{codeblock} +join(x, y) +in_between(x hash_hash y) +in_between(x ## y) +mkstr(x ## y) +"x ## y" +\end{codeblock} + +In other words, expanding \tcode{hash_hash} produces a new token, +consisting of two adjacent sharp signs, but this new token is not the +\tcode{\#\#} operator. +\end{example} + +\pnum +\begin{example} +To illustrate the rules for placemarker preprocessing tokens, the sequence +\begin{codeblock} +#define t(x,y,z) x ## y ## z +int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), + t(10,,), t(,11,), t(,,12), t(,,) }; +\end{codeblock} +results in +\begin{codeblock} +int j[] = { 123, 45, 67, 89, + 10, 11, 12, }; +\end{codeblock} +\end{example} + +\rSec2[cpp.rescan]{Rescanning and further replacement}% +\indextext{macro!rescanning and replacement}% +\indextext{rescanning and replacement|see{macro, rescanning and replacement}} + +\pnum +After all parameters in the replacement list have been substituted and \tcode{\#} and \tcode{\#\#} processing has taken +place, all placemarker preprocessing tokens are removed. Then +the resulting preprocessing token sequence is rescanned, along with all +subsequent preprocessing tokens of the source file, for more macro names +to replace. + +\pnum +\begin{example} +The sequence +\begin{codeblock} +#define x 3 +#define f(a) f(x * (a)) +#undef x +#define x 2 +#define g f +#define z z[0] +#define h g(~ +#define m(a) a(w) +#define w 0,1 +#define t(a) a +#define p() int +#define q(x) x +#define r(x,y) x ## y +#define str(x) # x + +f(y+1) + f(f(z)) % t(t(g)(0) + t)(1); +g(x+(3,4)-w) | h 5) & m + (f)^m(m); +p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) }; +char c[2][6] = { str(hello), str() }; +\end{codeblock} +results in +\begin{codeblock} +f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); +f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); +int i[] = { 1, 23, 4, 5, }; +char c[2][6] = { "hello", "" }; +\end{codeblock} +\end{example} + +\pnum +If the name of the macro being replaced is found during this scan of +the replacement list +(not including the rest of the source file's preprocessing tokens), +it is not replaced. +Furthermore, +if any nested replacements encounter the name of the macro being replaced, +it is not replaced. +These nonreplaced macro name preprocessing tokens are no longer available +for further replacement even if they are later (re)examined in contexts +in which that macro name preprocessing token would otherwise have been +replaced. + +\pnum +The resulting completely macro-replaced preprocessing token sequence +is not processed as a preprocessing directive even if it resembles one, +but all pragma unary operator expressions within it are then processed as +specified in~\ref{cpp.pragma.op} below. + +\rSec2[cpp.scope]{Scope of macro definitions}% +\indextext{macro!scope of definition}% +\indextext{scope!macro definition|see{macro, scope of definition}} + +\pnum +A macro definition lasts +(independent of block structure) +until a corresponding +\tcode{\#undef} +directive is encountered or +(if none is encountered) +until the end of the translation unit. +Macro definitions have no significance after translation phase 4. + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# undef} identifier new-line +\indextext{\idxcode{\#undef}}% +\end{ncsimplebnf} +causes the specified identifier no longer to be defined as a macro name. +It is ignored if the specified identifier is not currently defined as +a macro name. + +\indextext{macro!replacement|)} + +\rSec1[cpp.predefined]{Predefined macro names} +\indextext{macro!predefined}% +\indextext{name!predefined macro|see{macro, predefined}} + +\pnum +The following macro names shall be defined by the implementation: + +\begin{description} + +\item +\indextext{\idxxname{cplusplus}}% +\xname{cplusplus}\\ +The integer literal \tcode{\cppver}. +\begin{note} +Future revisions of this document will +replace the value of this macro with a greater value. +\end{note} + +\item The names listed in \tref{cpp.predefined.ft}.\\ +The macros defined in \tref{cpp.predefined.ft} shall be defined to +the corresponding integer literal. +\begin{note} +Future revisions of this document might replace +the values of these macros with greater values. +\end{note} + +\item +\indextext{__date__@\mname{DATE}}% +\mname{DATE}\\ +The date of translation of the source file: +a character string literal of the form +\tcode{"Mmm~dd~yyyy"}, +where the names of the months are the same as those generated +by the +\tcode{asctime} +function, +and the first character of +\tcode{dd} +is a space character if the value is less than 10. +If the date of translation is not available, +an \impldef{text of \mname{DATE} when date of translation is not available} valid date +shall be supplied. + +\item +\indextext{__file__@\mname{FILE}}% +\mname{FILE}\\ +The presumed name of the current source file (a character string +literal). +\begin{footnote} +The presumed source file name can be changed by the \tcode{\#line} directive. +\end{footnote} + +\item +\indextext{__line__@\mname{LINE}}% +\mname{LINE}\\ +The presumed line number (within the current source file) of the current source line +(an integer literal). +\begin{footnote} +The presumed line number can be changed by the \tcode{\#line} directive. +\end{footnote} + +\item +\indextext{__stdc_hosted__@\mname{STDC_HOSTED}}% +\indextext{implementation!hosted}% +\indextext{implementation!freestanding}% +\mname{STDC_HOSTED}\\ +The integer literal \tcode{1} +if the implementation is a hosted implementation or +the integer literal \tcode{0} +if it is a freestanding implementation\iref{intro.compliance}. + +\item +\indextext{__stdcpp_default_new_alignment__@\mname{STDCPP_DEFAULT_NEW_ALIGNMENT}}% +\mname{STDCPP_DEFAULT_NEW_ALIGNMENT}\\ +An integer literal of type \tcode{std::size_t} +whose value is the alignment guaranteed +by a call to \tcode{operator new(std::size_t)} +or \tcode{operator new[](std::size_t)}. +\begin{note} +Larger alignments will be passed to +\tcode{operator new(std::size_t, std::align_val_t)}, etc.\iref{expr.new}. +\end{note} + +\item +\indextext{__stdcpp_float16_t__@\mname{STDCPP_FLOAT16_T}}% +\mname{STDCPP_FLOAT16_T}\\ +Defined as the integer literal \tcode{1} +if and only if the implementation supports +the \IsoFloatUndated{} floating-point interchange format binary16 +as an extended floating-point type\iref{basic.extended.fp}. + +\item +\indextext{__stdcpp_float32_t__@\mname{STDCPP_FLOAT32_T}}% +\mname{STDCPP_FLOAT32_T}\\ +Defined as the integer literal \tcode{1} +if and only if the implementation supports +the \IsoFloatUndated{} floating-point interchange format binary32 +as an extended floating-point type. + +\item +\indextext{__stdcpp_float64_t__@\mname{STDCPP_FLOAT64_T}}% +\mname{STDCPP_FLOAT64_T}\\ +Defined as the integer literal \tcode{1} +if and only if the implementation supports +the \IsoFloatUndated{} floating-point interchange format binary64 +as an extended floating-point type. + +\item +\indextext{__stdcpp_float128_t__@\mname{STDCPP_FLOAT128_T}}% +\mname{STDCPP_FLOAT128_T}\\ +Defined as the integer literal \tcode{1} +if and only if the implementation supports +the \IsoFloatUndated{} floating-point interchange format binary128 +as an extended floating-point type. + +\item +\indextext{__stdcpp_bfloat16_t__@\mname{STDCPP_BFLOAT16_T}}% +\mname{STDCPP_BFLOAT16_T}\\ +Defined as the integer literal \tcode{1} +if and only if the implementation supports an extended floating-point type +with the properties of the \grammarterm{typedef-name} \tcode{std::bfloat16_t} +as described in \ref{basic.extended.fp}. + +\item +\indextext{__time__@\mname{TIME}}% +\mname{TIME}\\ +The time of translation of the source file: +a character string literal of the form +\tcode{"hh:mm:ss"} +as in the time generated by the +\tcode{asctime} +function. +If the time of translation is not available, +an \impldef{text of \mname{TIME} when time of translation is not available} valid time shall be supplied. +\end{description} + +\indextext{macro!feature-test}% +\indextext{feature-test macro|see{macro, feature-test}}% +\begin{LongTable}{Feature-test macros}{cpp.predefined.ft}{ll} +\\ \topline +\lhdr{Macro name} & \rhdr{Value} \\ \capsep +\endfirsthead +\continuedcaption \\ +\hline +\lhdr{Name} & \rhdr{Value} \\ \capsep +\endhead +\defnxname{cpp_aggregate_bases} & \tcode{201603L} \\ \rowsep +\defnxname{cpp_aggregate_nsdmi} & \tcode{201304L} \\ \rowsep +\defnxname{cpp_aggregate_paren_init} & \tcode{201902L} \\ \rowsep +\defnxname{cpp_alias_templates} & \tcode{200704L} \\ \rowsep +\defnxname{cpp_aligned_new} & \tcode{201606L} \\ \rowsep +\defnxname{cpp_attributes} & \tcode{200809L} \\ \rowsep +\defnxname{cpp_auto_cast} & \tcode{202110L} \\ \rowsep +\defnxname{cpp_binary_literals} & \tcode{201304L} \\ \rowsep +\defnxname{cpp_capture_star_this} & \tcode{201603L} \\ \rowsep +\defnxname{cpp_char8_t} & \tcode{202207L} \\ \rowsep +\defnxname{cpp_concepts} & \tcode{202002L} \\ \rowsep +\defnxname{cpp_conditional_explicit} & \tcode{201806L} \\ \rowsep +\defnxname{cpp_constexpr} & \tcode{202406L} \\ \rowsep +\defnxname{cpp_constexpr_dynamic_alloc} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_constexpr_in_decltype} & \tcode{201711L} \\ \rowsep +\defnxname{cpp_consteval} & \tcode{202211L} \\ \rowsep +\defnxname{cpp_constinit} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_decltype} & \tcode{200707L} \\ \rowsep +\defnxname{cpp_decltype_auto} & \tcode{201304L} \\ \rowsep +\defnxname{cpp_deduction_guides} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_delegating_constructors} & \tcode{200604L} \\ \rowsep +\defnxname{cpp_deleted_function} & \tcode{202403L} \\ \rowsep +\defnxname{cpp_designated_initializers} & \tcode{201707L} \\ \rowsep +\defnxname{cpp_enumerator_attributes} & \tcode{201411L} \\ \rowsep +\defnxname{cpp_explicit_this_parameter} & \tcode{202110L} \\ \rowsep +\defnxname{cpp_fold_expressions} & \tcode{201603L} \\ \rowsep +\defnxname{cpp_generic_lambdas} & \tcode{201707L} \\ \rowsep +\defnxname{cpp_guaranteed_copy_elision} & \tcode{201606L} \\ \rowsep +\defnxname{cpp_hex_float} & \tcode{201603L} \\ \rowsep +\defnxname{cpp_if_consteval} & \tcode{202106L} \\ \rowsep +\defnxname{cpp_if_constexpr} & \tcode{201606L} \\ \rowsep +\defnxname{cpp_impl_coroutine} & \tcode{201902L} \\ \rowsep +\defnxname{cpp_impl_destroying_delete} & \tcode{201806L} \\ \rowsep +\defnxname{cpp_impl_three_way_comparison} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_implicit_move} & \tcode{202207L} \\ \rowsep +\defnxname{cpp_inheriting_constructors} & \tcode{201511L} \\ \rowsep +\defnxname{cpp_init_captures} & \tcode{201803L} \\ \rowsep +\defnxname{cpp_initializer_lists} & \tcode{200806L} \\ \rowsep +\defnxname{cpp_inline_variables} & \tcode{201606L} \\ \rowsep +\defnxname{cpp_lambdas} & \tcode{200907L} \\ \rowsep +\defnxname{cpp_modules} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_multidimensional_subscript} & \tcode{202211L} \\ \rowsep +\defnxname{cpp_named_character_escapes} & \tcode{202207L} \\ \rowsep +\defnxname{cpp_namespace_attributes} & \tcode{201411L} \\ \rowsep +\defnxname{cpp_noexcept_function_type} & \tcode{201510L} \\ \rowsep +\defnxname{cpp_nontype_template_args} & \tcode{201911L} \\ \rowsep +\defnxname{cpp_nontype_template_parameter_auto} & \tcode{201606L} \\ \rowsep +\defnxname{cpp_nsdmi} & \tcode{200809L} \\ \rowsep +\defnxname{cpp_pack_indexing} & \tcode{202311L} \\ \rowsep +\defnxname{cpp_placeholder_variables} & \tcode{202306L} \\ \rowsep +\defnxname{cpp_range_based_for} & \tcode{202211L} \\ \rowsep +\defnxname{cpp_raw_strings} & \tcode{200710L} \\ \rowsep +\defnxname{cpp_ref_qualifiers} & \tcode{200710L} \\ \rowsep +\defnxname{cpp_return_type_deduction} & \tcode{201304L} \\ \rowsep +\defnxname{cpp_rvalue_references} & \tcode{200610L} \\ \rowsep +\defnxname{cpp_size_t_suffix} & \tcode{202011L} \\ \rowsep +\defnxname{cpp_sized_deallocation} & \tcode{201309L} \\ \rowsep +\defnxname{cpp_static_assert} & \tcode{202306L} \\ \rowsep +\defnxname{cpp_static_call_operator} & \tcode{202207L} \\ \rowsep +\defnxname{cpp_structured_bindings} & \tcode{202403L} \\ \rowsep +\defnxname{cpp_template_template_args} & \tcode{201611L} \\ \rowsep +\defnxname{cpp_threadsafe_static_init} & \tcode{200806L} \\ \rowsep +\defnxname{cpp_unicode_characters} & \tcode{200704L} \\ \rowsep +\defnxname{cpp_unicode_literals} & \tcode{200710L} \\ \rowsep +\defnxname{cpp_user_defined_literals} & \tcode{200809L} \\ \rowsep +\defnxname{cpp_using_enum} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_variable_templates} & \tcode{201304L} \\ \rowsep +\defnxname{cpp_variadic_friend} & \tcode{202403L} \\ \rowsep +\defnxname{cpp_variadic_templates} & \tcode{200704L} \\ \rowsep +\defnxname{cpp_variadic_using} & \tcode{201611L} \\ +\end{LongTable} + +\pnum +The following macro names are conditionally defined by the implementation: + +\begin{description} +\item +\indextext{__stdc__@\mname{STDC}}% +\mname{STDC}\\ +Whether \mname{STDC} is predefined and if so, what its value is, +are \impldef{definition and meaning of \mname{STDC}}. + +\item +\indextext{__stdc_mb_might_neq_wc__@\mname{STDC_MB_MIGHT_NEQ_WC}}% +\mname{STDC_MB_MIGHT_NEQ_WC}\\ +The integer literal \tcode{1}, intended to indicate that, in the encoding for +\keyword{wchar_t}, a member of the basic character set need not have a code value equal to +its value when used as the lone character in an ordinary character literal. + +\item +\indextext{__stdc_version__@\mname{STDC_VERSION}}% +\mname{STDC_VERSION}\\ +Whether \mname{STDC_VERSION} is predefined and if so, what its value is, +are \impldef{definition and meaning of \mname{STDC_VERSION}}. + +\item +\indextext{__stdc_iso_10646__@\mname{STDC_ISO_10646}}% +\mname{STDC_ISO_10646}\\ +An integer literal of the form \tcode{yyyymmL} +(for example, \tcode{199712L}). +Whether \mname{STDC_ISO_10646} is predefined and +if so, what its value is, +are \impldef{presence and value of \mname{STDC_ISO_10646}}. + +\item +\indextext{__stdcpp_threads__@\mname{STDCPP_THREADS}}% +\mname{STDCPP_THREADS}\\ +Defined, and has the value integer literal 1, if and only if a program +can have more than one thread of execution\iref{intro.multithread}. + +\end{description} + +\pnum +The values of the predefined macros +(except for +\mname{FILE} +and +\mname{LINE}) +remain constant throughout the translation unit. + +\pnum +If any of the pre-defined macro names in this subclause, +or the identifier +\tcode{defined}, +is the subject of a +\tcode{\#define} +or a +\tcode{\#undef} +preprocessing directive, +the behavior is undefined. +Any other predefined macro names shall begin with a +leading underscore followed by an uppercase letter or a second +underscore. + +\rSec1[cpp.cond]{Conditional inclusion}% +\indextext{preprocessing directive!conditional inclusion}% +\indextext{inclusion!conditional|see{preprocessing directive, conditional inclusion}} + +\indextext{\idxcode{defined}}% +\begin{bnf} +\nontermdef{defined-macro-expression}\br + \terminal{defined} identifier\br + \terminal{defined (} identifier \terminal{)} +\end{bnf} + +\begin{bnf} +\nontermdef{h-preprocessing-token}\br + \textnormal{any \grammarterm{preprocessing-token} other than \terminal{>}} +\end{bnf} + +\begin{bnf} +\nontermdef{h-pp-tokens}\br + h-preprocessing-token\br + h-pp-tokens h-preprocessing-token +\end{bnf} + +\begin{bnf} +\nontermdef{header-name-tokens}\br + string-literal\br + \terminal{<} h-pp-tokens \terminal{>} +\end{bnf} + +\indextext{\idxxname{has_include}}% +\begin{bnf} +\nontermdef{has-include-expression}\br + \terminal{\xname{has_include}} \terminal{(} header-name \terminal{)}\br + \terminal{\xname{has_include}} \terminal{(} header-name-tokens \terminal{)} +\end{bnf} + +\indextext{\idxxname{has_cpp_attribute}}% +\begin{bnf} +\nontermdef{has-attribute-expression}\br + \terminal{\xname{has_cpp_attribute} (} pp-tokens \terminal{)} +\end{bnf} + +\pnum +The expression that controls conditional inclusion +shall be an integral constant expression except that +identifiers +(including those lexically identical to keywords) +are interpreted as described below +\begin{footnote} +Because the controlling constant expression is evaluated +during translation phase 4, +all identifiers either are or are not macro names --- +there simply are no keywords, enumeration constants, etc. +\end{footnote} +and it may contain zero or more \grammarterm{defined-macro-expression}{s} and/or +\grammarterm{has-include-expression}{s} and/or +\grammarterm{has-attribute-expression}{s} as unary operator expressions. + +\pnum +A \grammarterm{defined-macro-expression} evaluates to \tcode{1} +if the identifier is currently defined +as a macro name +(that is, if it is predefined +or if it has one or more active macro definitions\iref{cpp.import}, +for example because +it has been the subject of a +\tcode{\#define} +preprocessing directive +without an intervening +\tcode{\#undef} +directive with the same subject identifier), \tcode{0} if it is not. + +\pnum +The second form of \grammarterm{has-include-expression} +is considered only if the first form does not match, +in which case the preprocessing tokens are processed just as in normal text. + +\pnum +The header or source file identified by +the parenthesized preprocessing token sequence +in each contained \grammarterm{has-include-expression} +is searched for as if that preprocessing token sequence +were the \grammarterm{pp-tokens} in a \tcode{\#include} directive, +except that no further macro expansion is performed. +If such a directive would not satisfy the syntactic requirements +of a \tcode{\#include} directive, the program is ill-formed. +The \grammarterm{has-include-expression} evaluates +to \tcode{1} if the search for the source file succeeds, and +to \tcode{0} if the search fails. + +\pnum +Each \grammarterm{has-attribute-expression} is replaced by +a non-zero \grammarterm{pp-number} +matching the form of an \grammarterm{integer-literal} +if the implementation supports an attribute +with the name specified by interpreting +the \grammarterm{pp-tokens}, after macro expansion, +as an \grammarterm{attribute-token}, +and by \tcode{0} otherwise. +The program is ill-formed if the \grammarterm{pp-tokens} +do not match the form of an \grammarterm{attribute-token}. + +\pnum +For an attribute specified in this document, +it is \impldef{value of \grammarterm{has-attribute-expression} +for standard attributes} +whether the value of the \grammarterm{has-attribute-expression} +is \tcode{0} or is given by \tref{cpp.cond.ha}. +For other attributes recognized by the implementation, +the value is +\impldef{value of \grammarterm{has-attribute-expression} +for non-standard attributes}. +\begin{note} +It is expected +that the availability of an attribute can be detected by any non-zero result. +\end{note} + +\begin{floattable}{\xname{has_cpp_attribute} values}{cpp.cond.ha} +{ll} +\topline +\lhdr{Attribute} & \rhdr{Value} \\ \rowsep +\tcode{assume} & \tcode{202207L} \\ +\tcode{carries_dependency} & \tcode{200809L} \\ +\tcode{deprecated} & \tcode{201309L} \\ +\tcode{fallthrough} & \tcode{201603L} \\ +\tcode{likely} & \tcode{201803L} \\ +\tcode{maybe_unused} & \tcode{201603L} \\ +\tcode{no_unique_address} & \tcode{201803L} \\ +\tcode{nodiscard} & \tcode{201907L} \\ +\tcode{noreturn} & \tcode{200809L} \\ +\tcode{unlikely} & \tcode{201803L} \\ +\end{floattable} + +\pnum +The +\tcode{\#ifdef}, \tcode{\#ifndef}, \tcode{\#elifdef}, and \tcode{\#elifndef} +directives, and +the \tcode{defined} conditional inclusion operator, +shall treat \xname{has_include} and \xname{has_cpp_attribute} +as if they were the names of defined macros. +The identifiers \xname{has_include} and \xname{has_cpp_attribute} +shall not appear in any context not mentioned in this subclause. + +\pnum +Each preprocessing token that remains (in the list of preprocessing tokens that +will become the controlling expression) +after all macro replacements have occurred +shall be in the lexical form of a token\iref{lex.token}. + +\pnum +Preprocessing directives of the forms +\begin{ncsimplebnf}\obeyspaces +\indextext{\idxcode{\#if}}% +\terminal{\# if } constant-expression new-line \opt{group}\br +\indextext{\idxcode{\#elif}}% +\terminal{\# elif } constant-expression new-line \opt{group} +\end{ncsimplebnf} +check whether the controlling constant expression evaluates to nonzero. + +\pnum +Prior to evaluation, +macro invocations in the list of preprocessing tokens +that will become the controlling constant expression +are replaced +(except for those macro names modified by the +\tcode{defined} +unary operator), +just as in normal text. +If the token +\tcode{defined} +is generated as a result of this replacement process +or use of the +\tcode{defined} +unary operator does not match one of the two specified forms +prior to macro replacement, +the behavior is undefined. + +\pnum +After all replacements due to macro expansion and +evaluations of +\grammarterm{defined-macro-expression}s, +\grammarterm{has-include-expression}s, and +\grammarterm{has-attribute-expression}s +have been performed, +all remaining identifiers and keywords, +except for +\tcode{true} +and +\tcode{false}, +are replaced with the \grammarterm{pp-number} +\tcode{0}, +and then each preprocessing token is converted into a token. +\begin{note} +An alternative +token\iref{lex.operators} is not an identifier, +even when its spelling consists entirely of letters and underscores. +Therefore it is not subject to this replacement. +\end{note} + +\pnum +The resulting tokens comprise the controlling constant expression +which is evaluated according to the rules of~\ref{expr.const} +using arithmetic that has at least the ranges specified +in~\ref{support.limits}. For the purposes of this token conversion and evaluation +all signed and unsigned integer types +act as if they have the same representation as, respectively, +\tcode{intmax_t} or \tcode{uintmax_t}\iref{cstdint.syn}. +\begin{note} +Thus on an +implementation where \tcode{std::numeric_limits::max()} is \tcode{0x7FFF} +and \tcode{std::numeric_limits::max()} is \tcode{0xFFFF}, +the integer literal \tcode{0x8000} is signed and positive within a \tcode{\#if} +expression even though it is unsigned in translation phase +7\iref{lex.phases}. +\end{note} +This includes interpreting \grammarterm{character-literal}s +according to the rules in \ref{lex.ccon}. +\begin{note} +The associated character encodings of literals are the same +in \tcode{\#if} and \tcode{\#elif} directives and in any expression. +\end{note} +Each subexpression with type +\tcode{bool} +is subjected to integral promotion before processing continues. + +\pnum +Preprocessing directives of the forms +\begin{ncsimplebnf}\obeyspaces +\terminal{\# ifdef } identifier new-line \opt{group}\br +\indextext{\idxcode{\#ifdef}}% +\terminal{\# ifndef } identifier new-line \opt{group}\br +\indextext{\idxcode{\#ifndef}}% +\terminal{\# elifdef } identifier new-line \opt{group}\br +\indextext{\idxcode{\#elifdef}}% +\terminal{\# elifndef} identifier new-line \opt{group} +\indextext{\idxcode{\#elifndef}}% +\end{ncsimplebnf} +check whether the identifier is or is not currently defined as a macro name. +Their conditions are equivalent to +\tcode{\#if} \tcode{defined} \grammarterm{identifier}, +\tcode{\#if} \tcode{!defined} \grammarterm{identifier}, +\tcode{\#elif} \tcode{defined} \grammarterm{identifier}, and +\tcode{\#elif} \tcode{!defined} \grammarterm{identifier}, +respectively. + +\pnum +Each directive's condition is checked in order. +If it evaluates to false (zero), +the group that it controls is skipped: +directives are processed only through the name that determines +the directive in order to keep track of the level +of nested conditionals; +the rest of the directives' preprocessing tokens are ignored, +as are the other preprocessing tokens in the group. +Only the first group +whose control condition evaluates to true (nonzero) is processed; +any following groups are skipped and their controlling directives +are processed as if they were in a group that is skipped. +If none of the conditions evaluates to true, +and there is a +\tcode{\#else} +\indextext{\idxcode{\#else}}% +directive, +the group controlled by the +\tcode{\#else} +is processed; lacking a +\tcode{\#else} +directive, all the groups until the +\tcode{\#endif} +\indextext{\idxcode{\#endif}}% +are skipped.% +\begin{footnote} +As indicated by the syntax, +a preprocessing token cannot follow a +\tcode{\#else} +or +\tcode{\#endif} +directive before the terminating new-line character. +However, +comments can appear anywhere in a source file, +including within a preprocessing directive. +\end{footnote} + +\pnum +\begin{example} +This demonstrates a way to include a library \tcode{optional} facility +only if it is available: + +\begin{codeblock} +#if __has_include() +# include +# if __cpp_lib_optional >= 201603 +# define have_optional 1 +# endif +#elif __has_include() +# include +# if __cpp_lib_experimental_optional >= 201411 +# define have_optional 1 +# define experimental_optional 1 +# endif +#endif +#ifndef have_optional +# define have_optional 0 +#endif +\end{codeblock} +\end{example} + +\pnum +\begin{example} +This demonstrates a way to use the attribute \tcode{[[acme::deprecated]]} +only if it is available. +\begin{codeblock} +#if __has_cpp_attribute(acme::deprecated) +# define ATTR_DEPRECATED(msg) [[acme::deprecated(msg)]] +#else +# define ATTR_DEPRECATED(msg) [[deprecated(msg)]] +#endif +ATTR_DEPRECATED("This function is deprecated") void anvil(); +\end{codeblock} +\end{example} + +\rSec1[cpp.include]{Source file inclusion} +\indextext{preprocessing directive!header inclusion} +\indextext{preprocessing directive!source-file inclusion} +\indextext{inclusion!source file|see{preprocessing directive, source-file inclusion}}% +\indextext{\idxcode{\#include}}% + +\pnum +A +\tcode{\#include} +directive shall identify a header or source file +that can be processed by the implementation. + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# include <} h-char-sequence \terminal{>} new-line +\end{ncsimplebnf} +searches a sequence of +\impldef{sequence of places searched for a header} +places +for a header identified uniquely by the specified sequence +between the +\tcode{<} +and +\tcode{>} +delimiters, +and causes the replacement of that +directive by the entire contents of the header. +How the places are specified +or the header identified +is \impldef{search locations for \tcode{<>} header}. + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# include "} q-char-sequence \terminal{"} new-line +\end{ncsimplebnf} +causes the replacement of that +directive by the entire contents of the +source file identified by the specified sequence between the +\tcode{"} +delimiters. +The named source file is searched for in an +\impldef{manner of search for included source file} +manner. +If this search is not supported, +or if the search fails, +the directive is reprocessed as if it read +\begin{ncsimplebnf} +\terminal{\# include <} h-char-sequence \terminal{>} new-line +\end{ncsimplebnf} +with the identical contained sequence (including +\tcode{>} +characters, if any) from the original directive. + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# include} pp-tokens new-line +\end{ncsimplebnf} +(that does not match one of the two previous forms) is permitted. +The preprocessing tokens after +\tcode{include} +in the directive are processed just as in normal text +(i.e., each identifier currently defined as a macro name is replaced by its +replacement list of preprocessing tokens). +If the directive resulting after all replacements does not match +one of the two previous forms, the behavior is +undefined. +\begin{footnote} +Note that adjacent \grammarterm{string-literal}s are not concatenated into +a single \grammarterm{string-literal} +(see the translation phases in~\ref{lex.phases}); +thus, an expansion that results in two \grammarterm{string-literal}s is an +invalid directive. +\end{footnote} +The method by which a sequence of preprocessing tokens between a +\tcode{<} +and a +\tcode{>} +preprocessing token pair or a pair of +\tcode{"} +characters is combined into a single header name +preprocessing token is \impldef{search locations for \tcode{""""} header}. + +\pnum +The implementation shall provide unique mappings for +sequences consisting of one or more +\grammarterm{nondigit}{s} or \grammarterm{digit}{s}\iref{lex.name} +followed by a period +(\tcode{.}) +and a single +\grammarterm{nondigit}. +The first character shall not be a \grammarterm{digit}. +The implementation may ignore distinctions of alphabetical case. + +\pnum +A +\tcode{\#include} +preprocessing directive may appear +in a source file that has been read because of a +\tcode{\#include} +directive in another file, +up to an \impldef{nesting limit for \tcode{\#include} directives} nesting limit. + +\pnum +If the header identified by the \grammarterm{header-name} +denotes an importable header\iref{module.import}, +it is +\impldef{whether source file inclusion of importable header +is replaced with \tcode{import} directive} +whether the \tcode{\#include} preprocessing directive +is instead replaced by an \tcode{import} directive\iref{cpp.import} of the form +\begin{ncbnf} +\terminal{import} header-name \terminal{;} new-line +\end{ncbnf} + +\pnum +\begin{note} +An implementation can provide a mechanism for making arbitrary +source files available to the \tcode{< >} search. +However, using the \tcode{< >} form for headers provided +with the implementation and the \tcode{" "} form for sources +outside the control of the implementation +achieves wider portability. For instance: + +\begin{codeblock} +#include +#include +#include "usefullib.h" +#include "myprog.h" +\end{codeblock} + +\end{note} + +\pnum +\begin{example} +This illustrates macro-replaced +\tcode{\#include} +directives: + +\begin{codeblock} +#if VERSION == 1 + #define INCFILE "vers1.h" +#elif VERSION == 2 + #define INCFILE "vers2.h" // and so on +#else + #define INCFILE "versN.h" +#endif +#include INCFILE +\end{codeblock} +\end{example} diff --git a/source/std.tex b/source/std.tex index 0a5f56221d..d4e89096d1 100644 --- a/source/std.tex +++ b/source/std.tex @@ -112,6 +112,7 @@ \include{intro} \include{lex} +\include{preprocessor} \include{basic} \include{expressions} \include{statements}