diff --git a/source/basic.tex b/source/basic.tex index e9ce2c1e8e..83f53f1cd5 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -4954,7 +4954,7 @@ \pnum The sixth context is when a temporary object is created in the \grammarterm{expansion-initializer} -of a destructuring expansion statement. +of an iterating or destructuring expansion statement. If such a temporary object would otherwise be destroyed at the end of that \grammarterm{expansion-initializer}, the object persists for the lifetime of the reference diff --git a/source/compatibility.tex b/source/compatibility.tex index edbd9196d1..51d2c511f8 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -222,6 +222,23 @@ type deductions from \#2 and \#3 both succeed. \end{example} +\rSec2[diff.cpp23.cpp]{\ref{cpp}: preprocessing directives} + +\diffref{cpp.replace.general} +\change +Additional restrictions on macro names. +\rationale +Avoid hard to diagnose or non-portable constructs. +\effect +Keywords, +names of identifiers with special meaning\iref{lex.name}, +and (unless otherwise specified) \grammarterm{attribute-token}{s} +specified in \ref{dcl.attr} +may not be used as macro names. +For example, valid \CppXXIII{} code that +defines \tcode{post} or \tcode{pre} as macros +is invalid in this revision of \Cpp{}. + \rSec2[diff.cpp23.library]{\ref{library}: library introduction} \diffref{headers} @@ -3447,14 +3464,15 @@ \diffref{dcl.enum} \change -In \Cpp{}, the type of an enumerator is its enumeration. In C, the type of an enumerator is \keyword{int}. +In \Cpp{}, the type of an enumerator is its enumeration. In C, the type of an enumerator is an integer type. \begin{example} \begin{codeblock} enum e { A }; -sizeof(A) == sizeof(int) // in C -sizeof(A) == sizeof(e) // in \Cpp{} -/* and @sizeof(int)@ is not necessarily equal to @sizeof(e)@ */ +void f() { + auto x = A; + int *p = &x; // valid C, invalid \Cpp{} +} \end{codeblock} \end{example} @@ -3466,10 +3484,6 @@ Semantic transformation. \howwide Seldom. -The only time this affects existing C code is when the size of an -enumerator is taken. -Taking the size of an enumerator is not a -common C coding practice. \diffref{dcl.align} \change diff --git a/source/declarations.tex b/source/declarations.tex index eac2152fbf..e75d74d2da 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -7741,10 +7741,10 @@ is an lvalue reference and an xvalue otherwise. Given the type $\tcode{T}_i$ designated by \tcode{std::tuple_element::type} and -the type $\tcode{U}_i$ designated by -either \tcode{$\tcode{T}_i$\&} or \tcode{$\tcode{T}_i$\&\&}, -where $\tcode{U}_i$ is an lvalue reference if -the initializer is an lvalue and an rvalue reference otherwise, +the type $\tcode{U}_i$ defined +as $\tcode{T}_i$ if the initializer is a prvalue, +as ``lvalue reference to $\tcode{T}_i$'' if the initializer is an lvalue, or +as ``rvalue reference to $\tcode{T}_i$'' otherwise, variables are introduced with unique names $\tcode{r}_i$ as follows: \begin{ncbnf} @@ -9512,6 +9512,13 @@ \grammarterm{attribute-token}. The \grammarterm{attribute-token} determines additional requirements on the \grammarterm{attribute-argument-clause} (if any). +\pnum +\begin{note} +Unless otherwise specified, +an \grammarterm{attribute-token} specified in this document cannot be used +as a macro name\iref{cpp.replace.general}. +\end{note} + \pnum An \grammarterm{annotation} followed by an ellipsis is a pack expansion\iref{temp.variadic}. @@ -10221,14 +10228,26 @@ \pnum An annotation may be applied to a \grammarterm{base-specifier} or -to any declaration of a +to a declaration $D$ of a type, type alias, variable, function, namespace, enumerator, or -non-static data member. +non-static data member, +unless +\begin{itemize} +\item the host scope of $X$ differs from its target scope or +\item $X$ is a non-defining friend declaration, +\end{itemize} +where $X$ is +\begin{itemize} +\item +$D'$ if $D$ is a function parameter declaration in +a function declarator\iref{dcl.fct} of a function declaration $D'$ and +\item $D$ otherwise. +\end{itemize} \pnum Let $E$ be the expression @@ -10237,11 +10256,8 @@ the result of $E$ is the \defnadj{underlying}{constant} of the annotation. \pnum -Each \grammarterm{annotation} produces a unique annotation. - -\pnum -Substituting into an \grammarterm{annotation} -is not in the immediate context. +Each \grammarterm{annotation} or instantiation thereof +produces a unique annotation. \begin{example} \begin{codeblock} [[=1]] void f(); @@ -10255,6 +10271,16 @@ \end{example} \begin{example} \begin{codeblock} +template int x [[=1]]; +static_assert(annotations_of(^^x<0>) != annotations_of(^^x<1>)); // OK +\end{codeblock} +\end{example} + +\pnum +Substituting into an \grammarterm{annotation} +is not in the immediate context. +\begin{example} +\begin{codeblock} template [[=T::type()]] void f(T t); diff --git a/source/expressions.tex b/source/expressions.tex index 10fffe4f88..dc320e8a0d 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -9373,39 +9373,97 @@ \end{example} \pnum -The \defn{evaluation context} is a set of program points -that determines the behavior of certain functions -used for reflection\iref{meta.reflection}. -During the evaluation $V$ of an expression $E$ as a core constant expression, -the evaluation context of an evaluation $X$\iref{intro.execution} -consists of the following points: -\begin{itemize} -\item -The program point $\textit{EVAL-PT}(L)$, -where $L$ is the point at which $E$ appears, and -where $\textit{EVAL-PT}(P)$, for a point $P$, -is a point $R$ determined as follows: +During an evaluation $V$\iref{intro.execution} of +an expression, conversion, or initialization $E$ +as a core constant expression, the +\indextext{point of!evaluation}% +\indextext{point!of evaluation}% +\indextext{evaluation!point of evaluation, during}% +\defnx{point of evaluation of $E$ during $V$}{point of evaluation during evaluation} +is the program point $P$ determined as follows: \begin{itemize} \item -If a potentially-evaluated subexpression\iref{intro.execution} of -a default member initializer $I$ appears at $P$, and -a (possibly aggregate) initialization during $V$ is using $I$, -then $R$ is $\textit{EVAL-PT}(Q)$ -where $Q$ is the point at which that initialization appears. +If $E$ is a potentially-evaluated subexpression of +a default member initializer $I$, and +%FIXME: An evaluation "in" an evaluation "as"? (Same issue below). +%FIXME: Do we define these concepts anywhere? +%FIXME: Which evaluation gets the "as"? Which initialzation exactly? +$V$ is the evaluation of $E$ in the evaluation of $I$ +as an immediate subexpression of a (possibly aggregate) initialization, then +$P$ is the point of evaluation of that initialization. +\begin{tailnote} +For example, +$E$ can be an immediate invocation in a default member initializer +used by an aggregate initialization appearing at $P$. +\end{tailnote} + \item -Otherwise, if a potentially-evaluated subexpression of -a default argument\iref{dcl.fct.default} appears at $P$, and -an invocation of a function\iref{expr.call} during $V$ -is using that default argument, -then $R$ is $\textit{EVAL-PT}(Q)$ -where $Q$ is the point at which that invocation appears. +Otherwise, +if $E$ is a potentially-evaluated subexpression of +a default argument $A$\iref{dcl.fct.default}, and +$V$ is the evaluation of $E$ in the evaluation of $A$ as +an immediate subexpression of a function call\iref{expr.call}, then +$P$ is the point of evaluation of that function call. + \item -Otherwise, $R$ is $P$. +Otherwise, +%FIXME: At what point does $E$ "appear"? What is "appear" in this context? +%FIXME: Also, we don't seem to define "program point" anywhere (just "synthesized point"). +$P$ is the point at which $E$ appears. \end{itemize} +During the evaluation $V$ of an expression $E$ as a core constant expression, +the \defnadj{evaluation}{context} of an evaluation $X$ +during $V$ is the set $C$ of program points determined as follows: +\begin{itemize} \item -Each synthesized point corresponding to an injected declaration produced by -any evaluation sequenced before $X$\iref{intro.execution}. +If $X$ occurs during the evaluation $Y$ of +a manifestly constant-evaluated expression, +where $Y$ occurs during $V$, then +$C$ is the evaluation context of $X$ during $Y$. +\item +Otherwise, $C$ contains + \begin{itemize} + \item + the point of evaluation of $E$ during $V$ and + each synthesized point in the instantiation context thereof and + \item + each synthesized point corresponding to an injected declaration + produced by any evaluation executed during $V$ that + is sequenced before $X$\iref{intro.execution}. + \end{itemize} \end{itemize} +\begin{note} +The evaluation context determines the behavior of certain functions +used for reflection\iref{meta.reflection}. +\end{note} +\begin{example} +\begin{codeblock} +struct S; +consteval std::size_t f(int p) { + constexpr std::size_t r = /* Q */ std::meta::is_complete_type(^^S) ? 1 : 2; // \#1 + if (!std::meta::is_complete_type(^^S)) { // \#2 + std::meta::define_aggregate(^^S, {}); + } + return (p > 0) ? f(p - 1) : r; +} + +consteval { + if (f(1) != 2) { + throw; // OK, not evaluated + } +} +\end{codeblock} +During each evaluation of +\tcode{std::meta::is_complete_type(\caret\caret{}S)} +at \#1\iref{meta.reflection.queries} that is +executed during the evaluation of \tcode{f(1) != 2}, +the evaluation context contains Q, +but does not contain the synthesized point +associated with the injected declaration of S. +However, the synthesized point is in the evaluation context of +\tcode{std::meta::is_complete_type(\caret\caret{}S)} at \#2 +during the evaluation of \tcode{f(0)}. +\end{example} \rSec2[expr.const.defns]{Further definitions} diff --git a/source/lex.tex b/source/lex.tex index 7547b4aa69..4876fb1a41 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -979,6 +979,12 @@ \keyword{pre} \\ \end{multicolfloattable} +\pnum +\begin{note} +Identifiers with special meaning +cannot be used as macro names\iref{cpp.replace.general}. +\end{note} + \pnum \indextext{\idxcode{_}|see{character, underscore}}% \indextext{character!underscore!in identifier}% @@ -1117,6 +1123,11 @@ \keyword{while} \\ \end{multicolfloattable} +\pnum +\begin{note} +Keywords cannot be used as macro names\iref{cpp.replace.general}. +\end{note} + \pnum Furthermore, the alternative representations shown in \tref{lex.key.digraph} for certain operators and diff --git a/source/preprocessor.tex b/source/preprocessor.tex index f8bd97288f..3a4634a7d1 100644 --- a/source/preprocessor.tex +++ b/source/preprocessor.tex @@ -1530,7 +1530,7 @@ \indextext{unit!translation}% A translation unit shall not \tcode{\#define} or \tcode{\#undef} macro names lexically identical -to keywords, +to keywords\iref{lex.key}, to the identifiers listed in \tref{lex.name.special}, or to the \grammarterm{attribute-token}{s} described in~\ref{dcl.attr}, except that the macro names \tcode{likely} and \tcode{unlikely} may be diff --git a/source/statements.tex b/source/statements.tex index 9163c1916a..4d9c216bc6 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -822,7 +822,7 @@ \tcode{E.begin()} and \tcode{E.end()}, or \item argument-dependent lookups for \tcode{begin(E)} and for \tcode{end(E)} -each find at least one function or function template. +each find at least one viable candidate\iref{over.match.viable}. \end{itemize} \pnum @@ -869,9 +869,8 @@ \begin{codeblock} { @\grammarterm{init-statement}@ - constexpr auto&& @\exposidnc{range}@ = @\grammarterm{expansion-initializer}@; - constexpr auto @\exposidnc{begin}@ = @\exposidnc{begin-expr}@; // see \ref{stmt.ranged} - constexpr auto @\exposidnc{end}@ = @\exposidnc{end-expr}@; // see \ref{stmt.ranged} + @\opt{constexpr}@ decltype(auto) @\exposidnc{range}@ = (@\grammarterm{expansion-initializer}@); + @\opt{constexpr}@ auto @\exposidnc{begin}@ = @\exposidnc{begin-expr}@; // see \ref{stmt.ranged} @$S_{0}$@ @\vdots@ @@ -880,30 +879,34 @@ \end{codeblock} where $N$ is the result of evaluating the expression \begin{codeblock} -[] consteval { +[&] consteval { std::ptrdiff_t result = 0; - for (auto i = @\exposid{begin}@; i != @\exposid{end}@; ++i) ++result; + auto b = @\exposid{begin-expr}@; + auto e = @\exposid{end-expr}@; + for (; b != e; ++b) ++result; return result; // distance from \exposid{begin} to \exposid{end} }() \end{codeblock} and $S_{i}$ is \begin{codeblock} { - constexpr auto @\exposid{iter}@ = @\exposid{begin}@ + decltype(begin - begin){@\placeholder{i}@}; + @\opt{constexpr}@ auto @\exposid{iter}@ = @\exposid{begin}@ + decltype(begin - begin){@\placeholder{i}@}; @\grammarterm{for-range-declaration}@ = *@\exposid{iter}@; @\grammarterm{compound-statement}@ } \end{codeblock} -The variables \exposid{range}, \exposid{begin}, \exposid{end}, and \exposid{iter} +The variables \exposid{range}, \exposid{begin}, and \exposid{iter} are defined for exposition only. +The keyword \keyword{constexpr} is present in the declarations +of \exposid{range}, \exposid{begin}, and \exposid{iter} +if and only if +\keyword{constexpr} is one of the \grammarterm{decl-specifier}{s} of +the \grammarterm{decl-specifier-seq} of +the \grammarterm{for-range-declaration}. The identifier \tcode{\placeholder{i}} is considered to be a prvalue of type \tcode{std::ptrdiff_t}; the program is ill-formed if \tcode{\placeholder{i}} is not representable as such a value. -\begin{note} -The instantiation is ill-formed if \exposid{range} -is not a constant expression\iref{expr.const.const}. -\end{note} \item Otherwise, $S$ is a destructuring expansion statement and, @@ -928,10 +931,13 @@ of the \grammarterm{expansion-initializer} and $S_{i}$ is \begin{codeblock} { - @\grammarterm{for-range-declaration}@ = @$u_{i}$@; + @\grammarterm{for-range-declaration}@ = @$v_{i}$@; @\grammarterm{compound-statement}@ } \end{codeblock} +If the \grammarterm{expansion-initializer} is an lvalue, then +$v_{i}$ is $u_{i}$; +otherwise, $v_{i}$ is \tcode{static_cast($u_{i}$)}. The keyword \keyword{constexpr} is present in the declaration of $u_{0}, u_{1}, \dotsc, u_{N-1}$ if and only if \keyword{constexpr} is one of the \grammarterm{decl-specifier}s diff --git a/source/templates.tex b/source/templates.tex index 467b190a19..b3db96b94c 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -193,7 +193,8 @@ \begin{itemize} \item a template, \item an entity defined\iref{basic.def} or created\iref{class.temporary} - within the \grammarterm{compound-statement} + within the + \grammarterm{for-range-declaration} or \grammarterm{compound-statement} of an \grammarterm{expansion-statement}\iref{stmt.expand}, \item an entity defined or created in a templated entity, \item a member of a templated entity, @@ -2193,7 +2194,7 @@ in the normal form \tcode{N} of \tcode{CE}, appearances of \tcode{C}{'s} template parameters in the parameter mappings of the atomic constraints in \tcode{N} -with their respective arguments from \tcode{C}. +with their respective arguments from \tcode{CI}. If any such substitution results in an invalid type or expression, the program is ill-formed; no diagnostic is required. \end{itemize} @@ -6031,12 +6032,13 @@ \begin{itemize} \item it is of the form \tcode{\caret\caret \grammarterm{reflection-name}} and -the \grammarterm{reflection-name} +either lookup for the \grammarterm{reflection-name} finds a declaration that +inhabits a scope corresponding to a templated entity or +the \grammarterm{reflection-name} is \begin{itemize} -\item is a dependent qualified name, -\item is a dependent \grammarterm{namespace-name}, -\item is the name of a template parameter, or -\item names a dependent member of the current instantiation\iref{temp.dep.type}, +\item a dependent qualified name, +\item a dependent \grammarterm{namespace-name}, or +\item the name of a template parameter, \end{itemize} \item it is of the form \tcode{\caret\caret \grammarterm{type-id}} and