diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -202,6 +202,8 @@ - Fix crash when evaluating consteval constructor of derived class whose base has more than one field. (`#60166 `_) +- Fix incorrect deletion of the default constructor of unions in some + cases. (`#48416 `_) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -9157,7 +9157,15 @@ // must be accessible and non-deleted, but need not be trivial. Such a // destructor is never actually called, but is semantically checked as // if it were. - DiagKind = 4; + if (CSM == Sema::CXXDefaultConstructor) { + // Default constructor of a union can also be valid if one of the + // members has an explicit initializer. + auto* RD = dyn_cast(Field->getParent()); + assert(RD); + if (!RD->hasInClassInitializer()) + DiagKind = 4; + } else + DiagKind = 4; } if (DiagKind == -1) diff --git a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp --- a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp +++ b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp @@ -144,3 +144,37 @@ Test2 t2x; // expected-error {{call to implicitly-deleted default constructor of 'Test2'}} } + +namespace GH48416 { + +struct non_trivial_constructor { + non_trivial_constructor() {} +}; + + +union U1 { + int a; + non_trivial_constructor b; // expected-note {{has a non-trivial default constructor}} +}; + +union U2 { + int a{}; + non_trivial_constructor b; +}; + +union U3 { + int a; + non_trivial_constructor b{}; +}; + +union U4 { + int a{}; // expected-note {{previous initialization is here}} + non_trivial_constructor b{}; // expected-error {{initializing multiple members of union}} +}; + +U1 u1; // expected-error {{call to implicitly-deleted default constructor}} +U2 u2; +U3 u3; +U4 u4; + +} // namespace GH48416