Can a field of anonymous union reference itself during the constexpr evaluation?

Hello all,

I was investigating the bug Heap-use-after-free in clang::APValue::swap which corresponds to the more human-friendly form

struct S {
union {
int i = i = 3;
};
constexpr S() {}
};
static_assert(S().i == 3, "”);

When you compile this example with
clang -std=c++14 -fsyntax-only

it crashes Clang 5.0.0, 4.0.0, 3.9.0 and running with ASAN shows there is use after free in APValue hierarchy caused by the i on the right hand side. If anybody is interested I can provide more details about the mechanism of the crash but it’s not important for the question I have.

Should Clang accept such code at all according to C++14 constexpr evaluation rules? GCC 7.2 rejects it, Clang ToT with -std=c++11 rejects it too. Also it would be helpful to shed some light on the differences between C++11 and C++14 for this example as for int i = i; and -std=c++11 Clang hits the assertion

Assertion failed: (isInt() && “Invalid accessor”), function getInt, file clang/include/clang/AST/APValue.h, line 202.

Thanks,
Volodymyr

The constexpr evaluation rules got substantially rewritten for C++14 (assignment wasn’t allowed at all in C++11). Let’s work through some cases. Consider the following: struct S { int i = 2; int j = i = 3; constexpr S() {} }; static_assert(S().i == 3, “”); Both clang and gcc accept this because assignment is generally allowed in constant expressions. How about the following? struct S { int i = i = 3; constexpr S() {} }; static_assert(S().i == 3, “”); The relevant standard text is that constant evaluation doesn’t allow “modification of an object (8.5.18, 8.5.1.6, 8.5.2.2) unless it is applied to a non-volatile lvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of e”. gcc accepts this, clang rejects it because it thinks the lifetime of i doesn’t start until after it’s initialized. clang’s interpretation seems reasonable. Then we come to your testcase, with the anonymous union. I don’t think the addition of the anonymous union changes the analysis in any significant way. -Eli

Thank you, Eli. Lifetime explanation is useful and helps to grasp the difference between GCC and Clang.