================ @@ -0,0 +1,80 @@ +// RUN: %clang_cc1 -verify -std=c++26 %s -Wno-defaulted-function-deleted -triple x86_64-linux-gnu + +struct NonTrivial { + int i; + constexpr NonTrivial(int i) :i(i) { } + constexpr ~NonTrivial() { } +}; + +union U0 { + NonTrivial nt; + int i; +}; +U0 u0; + +// check for constant evaluation failure +constexpr NonTrivial make() { + U0 u0; + return u0.nt; +} +constexpr NonTrivial nt = make(); // expected-error {{must be initialized by a constant expression}}} + // expected-note@-3 {{union with no active member}} + // expected-note@-4 {{in call to 'NonTrivial(u0.nt)'}} + // expected-note@-3 {{in call to 'make()'}} + +// overload resolution to select a constructor to default-initialize an object of type X either fails +union U1 { + U1(int); + NonTrivial nt; // #1 +}; +U1 u1(1); // expected-error {{deleted function}} expected-note@#1 {{non-trivial destructor}} + +// or selects a constructor that is either deleted or not trivial, or +union U2 { + U2() : nt(2) { } + NonTrivial nt; // #2 +}; +U2 u2; // expected-error {{deleted function}} expected-note@#2 {{non-trivial destructor}} + +union U3 { + U3() = delete; + U3(int); + NonTrivial nt; // #3 +}; +U3 u3(1); // expected-error {{deleted function}} expected-note@#3 {{non-trivial destructor}} + +// or X has a variant member V of class type M (or possibly multi-dimensional array thereof) where V has a default member initializer and M has a destructor that is non-trivial, +union U4 { + NonTrivial nt = 1; // #4 +}; +U4 u4; // expected-error {{deleted function}} expected-note@#4 {{non-trivial destructor}} + +union U5 { + NonTrivial nt; + U5* next = nullptr; +}; +U5 u5; + +union U6 { + U6() = default; + NonTrivial nt; + U6* next = nullptr; +}; +U6 u6; + + +struct DeletedDtor { + ~DeletedDtor() = delete; // expected-note 2 {{deleted here}} +}; +union B1 { + B1(); + DeletedDtor a; // expected-note {{because field 'a' has a deleted destructor}} +}; +B1 b1; // expected-error {{deleted function}} +union B2 { ---------------- Sirraide wrote:
Hmm, at a glance nothing jumps out to me; we *do* create a `FieldDecl` for the anonymous struct inside the union so I’d expect this to just handle that case—maybe we’re doing something weird with `IndirectFieldDecl`s somewhere but that’s just a guess. I did spot a fixme about anonymous unions inside anonymous unions, so er, here’s another gross test case I suppose: ```c++ union { union { NonTrivial x; }; } a; ``` https://github.com/llvm/llvm-project/pull/146815 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits