Which compiler is right here?
Invoking a consteval
constructor with new
is ill-formed.
MSVC and GCC are right to reject it; clang is wrong as a diagnostic is required.
struct A { consteval A() {} };
consteval
makes A::A()
an immediate function1.
An immediate function can only be called from2,3:
- another immediate function, or
- a consteval if statement, or
- a constant expression4.
new A{}
is none of the above.
1) [dcl.constexpr]/2
A constexpr
or consteval
specifier used in the declaration of a function declares that function to be a constexpr function.
A function or constructor declared with the consteval
specifier is called an immediate function.
2) [expr.prim.id.general]/4
A potentially-evaluated id-expression that denotes an immediate function shall appear only
(4.1) as a subexpression of an immediate invocation, or
(4.2) in an immediate function context.
3) [expr.const]/13
An expression or conversion is in an immediate function context if it is potentially evaluated and either:
(13.1) its innermost enclosing non-block scope is a function parameter scope of an immediate function, or
(13.2) its enclosing statement is enclosed ([stmt.pre]) by the compound-statement of a consteval if statement ([stmt.if]).
An expression or conversion is an immediate invocation if it is a potentially-evaluated explicit or implicit invocation of an immediate function and is not in an immediate function context.
An immediate invocation shall be a constant expression.
4) [expr.const]/11.2
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:
(11.2) if the value is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object ([expr.add]), the address of a non-immediate function, or a null pointer value,
A
could be heap-allocated in a constant expression context. – Azar