forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 3
Closed
Description
https://godbolt.org/z/73oM1j1v8
struct T {};
struct Op {
constexpr Op() : t() {}
union {
char c;
T t;
};
};
constexpr bool f() {
Op op;
op.t.~T();
// op.c = 0;
auto op2 = op; // wrongly fails to be constexpr-friendly
(void)op2;
return true;
}
static_assert(f()); // wrongly fails
Clang trunk (ever since constexpr destructors were added in Clang 10) complains:
<source>:21:15: error: static assertion expression is not an integral constant expression
21 | static_assert(f());
| ^~~
<source>:16:14: note: subobject 't' is not initialized
16 | auto op2 = op; // trivial?
| ^
<source>:16:14: note: in call to 'Op(op)'
16 | auto op2 = op; // trivial?
| ^~
<source>:21:15: note: in call to 'f()'
21 | static_assert(f());
| ^~~
<source>:8:7: note: subobject declared here
8 | T t;
| ^
Uncommenting the line op.c = 0;
makes Clang happy. But that line shouldn't be necessary — not physically, because op
's copy constructor is trivial i.e. bytewise; nor on paper, because op.c
is a char — an implicit-lifetime type — which can "pop into existence" without our needing to explicitly "activate" it here.
GCC, MSVC, and EDG happily accept this code; only Clang rejects.