Constexpr function returning member of union: g++ vs. clang++: no diagnostics vs. error

Viewed 83

Consider this code:

typedef union { float v; unsigned u; } T;
constexpr T x = { .u = 0 };
constexpr float f(void)
{
        return x.v;
}

Is this code valid?

Invocations:

$ g++ t506a.cpp -c -std=c++20 -pedantic -Wall -Wextra
<nothing>

$ clang++ t506a.cpp -c -std=c++20 -pedantic -Wall -Wextra
t506a.cpp:3:17: error: constexpr function never produces a constant expression
      [-Winvalid-constexpr]
constexpr float f(void)
                ^
t506a.cpp:5:9: note: read of member 'v' of union with active member 'u' is not allowed in a
      constant expression
        return x.v;
               ^
1 error generated.

Which compiler is correct?

1 Answers

Both compilers are correct, even though the code is ill-formed, because no diagnostic is required in the program you've shown. It's true that f can never be evaluated as a core constant expression, but in that case dcl.constexpr#6 applies:

For a constexpr function or constexpr constructor that is neither defaulted nor a template, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression, or, for a constructor, an evaluated subexpression of the initialization full-expression of some constant-initialized object ([basic.start.static]), the program is ill-formed, no diagnostic required.

(emphasis mine)

Since no diagnostic is required, GCC is allowed to not diagnose this.

On the other hand, if you do attempt to evaluate f as a constant, e.g.

constexpr float a = f();

then it violates expr.const#5.10:

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:

  • an lvalue-to-rvalue conversion that is applied to a glvalue that refers to a non-active member of a union or a subobject thereof;

and indeed, both GCC and Clang diagnose this error, as required during constant evaluation.

Related