Search code examples
c++language-lawyerconstexprconsteval

Is the address of a consteval-constructed object a constant expression?


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.


Solution

  • 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};
    

    Demo