From d8ab955eb4b06a8d3546a54184ae875dfcd2ec4a Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Sun, 5 Apr 2026 00:40:27 -0700 Subject: [PATCH 01/13] CWG3088 Clarify macro treatment of identifiers with special meaning Fixes NB US 57-105 (C++26 CD). --- source/compatibility.tex | 17 +++++++++++++++++ source/declarations.tex | 7 +++++++ source/lex.tex | 11 +++++++++++ source/preprocessor.tex | 2 +- 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/source/compatibility.tex b/source/compatibility.tex index edbd9196d1..13c6ae3f9e 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} diff --git a/source/declarations.tex b/source/declarations.tex index eac2152fbf..46e3094cab 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -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}. 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 From 160f1b7b5fdd796ea181945d8784e9ebb04fc70f Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Sun, 5 Apr 2026 00:45:21 -0700 Subject: [PATCH 02/13] CWG3119 for-range-declaration of an expansion-statement as a templated entity Fixes NB AT 2-089 (C++26 CD). --- source/templates.tex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/templates.tex b/source/templates.tex index 467b190a19..d3842986a5 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, From 61b0bbc81d0633b37a81d0d0f62c85a61a84e633 Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Sun, 5 Apr 2026 00:50:48 -0700 Subject: [PATCH 03/13] CWG3122 Inadequate value-dependence for reflect-expressions --- source/templates.tex | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/source/templates.tex b/source/templates.tex index d3842986a5..5bb683d607 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -6032,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 From 931ec998d021fe327a015b5440ec2b4a7f49f67b Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Sun, 5 Apr 2026 00:54:05 -0700 Subject: [PATCH 04/13] CWG3123 Global lookup for begin and end for expansion statements --- source/statements.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/statements.tex b/source/statements.tex index 9163c1916a..c006dbac59 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 From 4641f4212fd3fadd0634d42efcce536ae31b54eb Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Sun, 5 Apr 2026 01:20:06 -0700 Subject: [PATCH 05/13] CWG3124 Disallow annotations on block-scope externs and non-unique friend declarations [dcl.attr.annotation]p1 Replaced /function-declarator/ with function declarator as no such grammarterm exists. --- source/declarations.tex | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/source/declarations.tex b/source/declarations.tex index 46e3094cab..9c9bb2944c 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -10228,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 From ce197254f120fe04388785d8e39a05d189dfb97e Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Sun, 5 Apr 2026 01:45:50 -0700 Subject: [PATCH 06/13] CWG3131 Value categories and types for the range in iterable expansion statements --- source/statements.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/statements.tex b/source/statements.tex index c006dbac59..f29e6f2f48 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -869,7 +869,7 @@ \begin{codeblock} { @\grammarterm{init-statement}@ - constexpr auto&& @\exposidnc{range}@ = @\grammarterm{expansion-initializer}@; + constexpr decltype(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} From 8a170e47a0cf81e480164400c2372fdeca84cf1e Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Sun, 5 Apr 2026 03:00:17 -0700 Subject: [PATCH 07/13] CWG3135 constexpr structured bindings with prvalues from tuples --- source/declarations.tex | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/declarations.tex b/source/declarations.tex index 9c9bb2944c..854e354597 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} From 842c3c1f4bd8f20c4843d0ecf8fe181fe2c4a1cc Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Sun, 5 Apr 2026 03:27:17 -0700 Subject: [PATCH 08/13] CWG3140 Allowing expansion over non-constant std::array --- source/basic.tex | 2 +- source/statements.tex | 25 ++++++++++++++----------- 2 files changed, 15 insertions(+), 12 deletions(-) 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/statements.tex b/source/statements.tex index f29e6f2f48..a6852b5602 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -869,9 +869,8 @@ \begin{codeblock} { @\grammarterm{init-statement}@ - constexpr decltype(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, From 2d1f0eb6bdd76ee3c51ea15b7538832d234eacdd Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Sun, 5 Apr 2026 04:08:37 -0700 Subject: [PATCH 09/13] CWG3143 Incorrect statement about enumerators for C23 --- source/compatibility.tex | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/source/compatibility.tex b/source/compatibility.tex index 13c6ae3f9e..51d2c511f8 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -3464,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} @@ -3483,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 From 5fae9f39403e7b2f822b1567e8ee6f5485a6f38e Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Sun, 5 Apr 2026 04:18:26 -0700 Subject: [PATCH 10/13] CWG3145 Uniqueness of annotations --- source/declarations.tex | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/source/declarations.tex b/source/declarations.tex index 854e354597..e75d74d2da 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -10256,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(); @@ -10274,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); From 681355703b8498713d652ed9b1c98f53ca24b782 Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Sun, 5 Apr 2026 04:27:48 -0700 Subject: [PATCH 11/13] CWG3149 Rvalues in destructuring expansion statements --- source/statements.tex | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/statements.tex b/source/statements.tex index a6852b5602..4d9c216bc6 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -931,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 From 21f772481af4c7d0ee39664e8617dd3c766a7554 Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Sun, 5 Apr 2026 16:19:08 -0700 Subject: [PATCH 12/13] CWG3162 Evaluation context of manifestly constant-evaluated expressions Also fixes CWG3127. --- source/expressions.tex | 110 +++++++++++++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 26 deletions(-) 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} From 4547b9f6251a5b0a3972403139d6464bfb22af69 Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Sun, 5 Apr 2026 16:21:39 -0700 Subject: [PATCH 13/13] CWG3172 Reference to wrong placeholder --- source/templates.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/templates.tex b/source/templates.tex index 5bb683d607..b3db96b94c 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -2194,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}