This code compiles in GCC 8, but not in GCC 7 nor clang.
constexpr int a = 1;
constexpr int b = --const_cast<int&>(a);
This is clearly UB.
My question: what does standardese say about evaluating a constexpr that contains UB - should this code compile at all?
All undefined behavior in a constexpr
compile-time expression makes the expression not evaluated at compile time (not consteval
basically, to use a new keyword that basically has that meaning).
Initializing a constexpr
requires, effectively, a consteval
expression.
I won't address if what you did is UB (I believe it is), but if it is UB then it should not compile.
I'll see if I can find standard quotes to back these assertions; but there is no tricky language-lawyering required here. Just a simple principle: At compile time during evaluation of compile time expressions, compilers must audit the code it runs for UB, and if they run into UB (again, at compile time) the expression isn't a compile-time expression anymore.
This code is ill-formed, and GCC 8 and 9 are incorrect to not give a diagnostic.
[expr.const] (C++17 paragraph 2, current C++20 draft paragraph 4):
An expression
e
is a core constant expression unless the evaluation ofe
, following the rules of the abstract machine, would evaluate one of the following expressions:
...
an operation that would have undefined behavior as specified in Clauses [intro] through [cpp] of this International Standard;
...
modification of an object unless it is applied to a non-volatile lvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of
e
;...
"Clauses [intro] through [cpp]" is also known as the core language specification.
[expr.const] (C++17 paragraph 5, current C++20 draft paragraph 10):
A constant expression is either a glvalue core constant expression that refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints:
The "following constraints" apply only to values of class type, array type, or pointer type.
[dcl.constexpr] (C++17 paragraph 9, current C++20 draft paragraph 10):
In any
constexpr
variable declaration, the full-expression of the initialization shall be a constant expression.
The expression --const_cast<int&>(a);
is not a core constant expression and therefore not a constant expression, both because its evaluation would have undefined behavior, and because it modifies an object whose lifetime did not begin within the evaluation. A "shall" statement (unless combined with "no diagnostic required") means that an implementation must print a diagnostic message (e.g. an error or warning) when a program violates it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With