From 9eccd8d1d2e217e770c761c1f3e82267e9f4c5a5 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 12 Nov 2018 14:15:15 +0100 Subject: [PATCH 1/4] P0595R2 std::is_constant_evaluated() --- source/basic.tex | 8 +---- source/expressions.tex | 78 ++++++++++++++++++++++++++++++++++-------- source/support.tex | 2 ++ source/utilities.tex | 28 +++++++++++++++ 4 files changed, 94 insertions(+), 22 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 21b1980d30..1d6f207647 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -5729,15 +5729,9 @@ \pnum \indextext{initialization!static object@\tcode{static} object}% \indextext{initialization!constant}% -A \defn{constant initializer} for a variable or temporary object \tcode{o} -is an initializer whose full-expression is a -constant expression, except that if \tcode{o} is an object, -such an initializer may also invoke constexpr constructors -for \tcode{o} and its subobjects even if those objects are of non-literal class -types. \begin{note} Such a class may have a non-trivial destructor. \end{note} \defnx{Constant initialization}{constant initialization} is performed if a variable or temporary object with static or thread storage duration -is initialized by a constant initializer for the entity. +is initialized by a constant initializer\iref{expr.const} for the entity. \indextext{initialization!runtime}% If constant initialization is not performed, a variable with static storage duration\iref{basic.stc.static} or thread storage diff --git a/source/expressions.tex b/source/expressions.tex index 4a84068a99..157043b272 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -6510,6 +6510,28 @@ conditional-expression \end{bnf} +\pnum +A \defn{constant initializer} for a variable or temporary object \tcode{o} is +an initializer for which interpreting its full-expression +as a \grammarterm{constant-expression} results in a constant expression, +except that if \tcode{o} is an object, +such an initializer may also invoke constexpr constructors +for \tcode{o} and its subobjects +even if those objects are of non-literal class types. +\begin{note} +Such a class may have a non-trivial destructor. +Within this evaluation, +\tcode{std::is_constant_evaluated()}\iref{meta.const.eval} +returns \tcode{true}. +\end{note} + +\pnum +A variable is +\defnx{usable in constant expressions}{usable in constant expression} after +its initializing declaration is encountered if it is a constexpr variable, or +it is of reference type or of const-qualified integral or enumeration type, and +its initializer is a constant initializer. + \pnum An expression \tcode{e} is a \defnadj{core constant}{expression} unless the evaluation of \tcode{e}, following the rules of the abstract @@ -6558,20 +6580,8 @@ \begin{itemize} \item - a non-volatile glvalue of integral or enumeration type that refers - to a complete non-volatile const object with a preceding initialization, - initialized with a constant expression, or - - \item - a non-volatile glvalue that refers to a subobject of a string - literal\iref{lex.string}, or - - \item - a non-volatile glvalue that refers to a non-volatile object - defined with \tcode{constexpr} or - a template parameter object\iref{temp.param}, - or that refers to a non-mutable subobject - of such an object, or + a non-volatile glvalue that refers to an object that is + usable in constant expressions, or \item a non-volatile glvalue of literal type that refers to a non-volatile object @@ -6601,7 +6611,7 @@ \begin{itemize} \item - it is initialized with a constant expression or + it is usable in constant expressions or \item its lifetime began within the evaluation of \tcode{e}; @@ -6879,6 +6889,44 @@ An immediate invocation is evaluated even in an unevaluated operand. \end{note} +\pnum +An expression or conversion \tcode{e} is \defn{manifestly constant-evaluated} +if it is: +\begin{itemize} +\item a \grammarterm{constant-expression}, or +\item the condition of a constexpr if statement\iref{stmt.if}, or +\item the initializer of a constexpr variable\iref{dcl.constexpr}, or +\item an immediate invocation, or +\item a \grammarterm{constraint-expression}\iref{temp.constr.decl} +(possibly one formed from the \grammarterm{constraint-logical-or-expression} +of a \grammarterm{requires-clause}), or +\item the initializer of a variable +that is usable in constant expressions or +has constant initialization.\footnote{Testing this condition +may involve a trial evaluation of its initializer as described above.} +\begin{example} +\begin{codeblock} +template struct X {}; +X x; // type \tcode{X} +int y; +const int a = std::is_constant_evaluated() ? y : 1; // dynamic initialization to 1 +double z[a]; // ill-formed: \tcode{a} is not usable + // in constant expressions +const int b = std::is_constant_evaluated() ? 2 : y; // static initialization to 2 +int c = y + (std::is_constant_evaluated() ? 2 : y); // dynamic initialization to \tcode{y+y} + +constexpr int f() { + const int n = std::is_constant_evaluated() ? 13 : 17; // \tcode{n} is 13 + int m = std::is_constant_evaluated() ? 13 : 17; // \tcode{m} might be 13 or 17 (see below) + char arr[n] = {}; // char[13] + return m + sizeof(arr); +} +int p = f(); // \tcode{m} is 13; initialized to 26 +int q = p + f(); // \tcode{m} is 17 for this call; initialized to 56 +\end{codeblock} +\end{example} +\end{itemize} + \pnum \indextext{expression!potentially constant evaluated}% An expression or conversion is \defn{potentially constant evaluated} diff --git a/source/support.tex b/source/support.tex index 7133579946..3e2881ea14 100644 --- a/source/support.tex +++ b/source/support.tex @@ -605,6 +605,8 @@ \tcode{} \\ \rowsep \defnlibxname{cpp_lib_is_aggregate} & \tcode{201703L} & \tcode{} \\ \rowsep +\defnlibxname{cpp_lib_is_constant_evaluated} & \tcode{201811L} & + \tcode{} \\ \rowsep \defnlibxname{cpp_lib_is_final} & \tcode{201402L} & \tcode{} \\ \rowsep \defnlibxname{cpp_lib_is_invocable} & \tcode{201703L} & diff --git a/source/utilities.tex b/source/utilities.tex index b6ac5c9c9a..cc4c773e5d 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -15744,6 +15744,9 @@ inline constexpr bool disjunction_v = disjunction::value; template inline constexpr bool negation_v = negation::value; + + // \ref{meta.const.eval}, constant evaluation context + constexpr bool is_constant_evaluated() noexcept; } \end{codeblock} @@ -17394,6 +17397,31 @@ to either \tcode{endian::big} or \tcode{endian::little}. \end{itemdescr} +\rSec2[meta.const.eval]{Constant evaluation context} +\begin{itemdecl} +constexpr bool is_constant_evaluation() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns \tcode{true} if and only if evaluation of the call occurs +within the evaluation of an expression or conversion +that is manifestly constant-evaluated\iref{expr.const}. + +\pnum +\begin{example} +\begin{codeblock} +constexpr void f(unsigned char *p, int n) { + if (std::is_constant_evaluated()) { // should not be a constexpr if statement + for (int k = 0; k Date: Sat, 24 Nov 2018 23:13:58 -0800 Subject: [PATCH 2/4] [expr.const] Add missing definition of 'usable in constant expressions' for (sub)objects and reference members. --- source/expressions.tex | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/expressions.tex b/source/expressions.tex index 157043b272..65aa2e7eab 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -6527,10 +6527,16 @@ \pnum A variable is -\defnx{usable in constant expressions}{usable in constant expression} after +\defn{usable in constant expressions} after its initializing declaration is encountered if it is a constexpr variable, or it is of reference type or of const-qualified integral or enumeration type, and its initializer is a constant initializer. +An object or reference is \defn{usable in constant expressions} +if it is a variable that is usable in constant expressions, +a template parameter object\iref{temp.param}, +a string literal object\iref{lex.string}, +or a non-mutable subobject or reference member +of an object that is usable in constant expressions. \pnum An expression \tcode{e} is a \defnadj{core constant}{expression} From e201f3325d8a91319c37a702e50d8032759fd822 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sat, 24 Nov 2018 23:37:02 -0800 Subject: [PATCH 3/4] [expr.const] Factor out some commonality from 'manifestly constant-evaluated' and 'potentially constant evaluated'. --- source/expressions.tex | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/source/expressions.tex b/source/expressions.tex index 65aa2e7eab..ea29205844 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -6904,8 +6904,8 @@ \item the initializer of a constexpr variable\iref{dcl.constexpr}, or \item an immediate invocation, or \item a \grammarterm{constraint-expression}\iref{temp.constr.decl} -(possibly one formed from the \grammarterm{constraint-logical-or-expression} -of a \grammarterm{requires-clause}), or +including one formed from the \grammarterm{constraint-logical-or-expression} +of a \grammarterm{requires-clause}, or \item the initializer of a variable that is usable in constant expressions or has constant initialization.\footnote{Testing this condition @@ -6940,15 +6940,10 @@ \begin{itemize} \item -a potentially-evaluated expression\iref{basic.def.odr}, - -\item -an immediate invocation, +a manifestly constant-evaluated expression, \item -a \grammarterm{constraint-expression}, -including one formed from the \grammarterm{constraint-logical-or-expression} -of a \grammarterm{requires-clause}, +a potentially-evaluated expression\iref{basic.def.odr}, \item an immediate subexpression of a \grammarterm{braced-init-list},% From d4d65994bcf692c472cee2ed83db34e4c94266e6 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sat, 24 Nov 2018 23:40:25 -0800 Subject: [PATCH 4/4] [expr.const] Remove redundant bullet from definition of manifestly constant-evaluated. Constexpr variables are always usable in constant expressions. --- source/expressions.tex | 1 - 1 file changed, 1 deletion(-) diff --git a/source/expressions.tex b/source/expressions.tex index ea29205844..0bc282a59f 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -6901,7 +6901,6 @@ \begin{itemize} \item a \grammarterm{constant-expression}, or \item the condition of a constexpr if statement\iref{stmt.if}, or -\item the initializer of a constexpr variable\iref{dcl.constexpr}, or \item an immediate invocation, or \item a \grammarterm{constraint-expression}\iref{temp.constr.decl} including one formed from the \grammarterm{constraint-logical-or-expression}