EDIT: this has been reported as a llvm bug here.
The following code compiles on GCC and MSVC but is rejected by Clang:
struct X
{
const void *p_;
consteval X()
: p_{this}
{
}
};
static constexpr X x{};
(https://godbolt.org/z/ExYMeTcTq)
Is Clang correct here?
My understanding is that x{}
is an immediate invocation of the constructor, and within its body the address of a static constexpr
variable should be a known constant value.
The answer to this similar question shows how invoking a member function on an object created in the same expression is valid, hence one more reason for me to think that this
is a vlid constant in this case too.
To add to my confusion, if the constructor of the class is marked constexpr
rather than consteval
, Clang happily accepts the code.
The program is well-formed. This can be seen from expr.const:
An expression E is a core constant expression unless the evaluation of E, following the rules of the abstract machine ([intro.execution]), would evaluate one of the following:
- this ([expr.prim.this]), except
- in a constexpr function ([dcl.constexpr]) that is being evaluated as part of E or
Below is a more contrived example that has exactly the same reason for being well-formed as your code:
struct X {
int i;
consteval X(int x) {
this->i = x; //valid and compiles in all 3 compilers
}
};
constexpr X x{5};