Search code examples
c++clangconstexpr

Why does clang allow this C-style cast in a constexpr?


The following code compiles with clang++ 14 but not with g++ 12 (which fails because reinterpret_cast is not allowed in constexprs).

constexpr int* convert(char* a) {
    return (int*)(a);
}

int main() {
    return (int) *convert(new char('a'));
}

Why does clang allow this C-style cast while gcc doesn't?


Solution

  • Before P2448R2, if a constexpr function could never produce a constant expression no matter what the arguments, your program would be ill-formed, no diagnostic required. This is standardese for "A compiler is allowed to check but doesn't have to", especially for something hard to prove.

    Your function fits that definition: no argument for a would mean that convert(a) would be a constant expression. GCC chose to check this specific case and Clang did not.

    After P2448R2, this rule was struck and it is no longer ill-formed. The function is now a constexpr function that just can't be called at compile time, exactly as if it was not marked constexpr.

    Your current code does have undefined behaviour, but it wouldn't have undefined behaviour if you had instead had new char[sizeof(int)]{} or (char*) new int{}.

    And according to https://gcc.gnu.org/projects/cxx-status.html, P2448R2 is implemented in GCC 14 (the development branch). And sure enough your code compiles now with GCC 14.