royjacobson updated this revision to Diff 505216. royjacobson added a comment.
Fix the codegen test, add a standard ref to the comment. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D145851/new/ https://reviews.llvm.org/D145851 Files: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaDeclCXX.cpp clang/test/CodeGen/union-non-trivial-member.cpp clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
Index: clang/test/SemaCXX/cxx0x-nontrivial-union.cpp =================================================================== --- clang/test/SemaCXX/cxx0x-nontrivial-union.cpp +++ clang/test/SemaCXX/cxx0x-nontrivial-union.cpp @@ -144,3 +144,47 @@ Test2<X> t2x; // expected-error {{call to implicitly-deleted default constructor of 'Test2<X>'}} } + +namespace GH48416 { + +struct non_trivial_constructor { + constexpr non_trivial_constructor() : x(100) {} + int x; +}; + + +union U1 { + int a; + non_trivial_constructor b; // expected-note {{has a non-trivial default constructor}} +}; + +union U2 { + int a{1000}; + 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; + +static_assert(U2().a == 1000, ""); +static_assert(U3().a == 1000, ""); +// expected-error@-1 {{static assertion expression is not an integral constant expression}} +// expected-note@-2 {{read of member 'a' of union with active member 'b'}} +static_assert(U2().b.x == 100, ""); +// expected-error@-1 {{static assertion expression is not an integral constant expression}} +// expected-note@-2 {{read of member 'b' of union with active member 'a'}} +static_assert(U3().b.x == 100, ""); + +} // namespace GH48416 Index: clang/test/CodeGen/union-non-trivial-member.cpp =================================================================== --- /dev/null +++ clang/test/CodeGen/union-non-trivial-member.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 --std=c++17 -emit-llvm %s -o - -triple x86_64-unknown-linux-gnu | FileCheck %s + +struct non_trivial_constructor { + constexpr non_trivial_constructor() : x(100) { } + int x; +}; + +union UnionInt { + int a{1000}; + non_trivial_constructor b; +}; + +union UnionNonTrivial { + int a; + non_trivial_constructor b{}; +}; + +void f() { + UnionInt u1; + UnionNonTrivial u2; +} + +// CHECK: define dso_local void @_Z1fv() {{.*}} { +// CHECK-NEXT: entry: +// CHECK: call void @_ZN8UnionIntC1Ev{{.*}} +// CHECK-NEXT: call void @_ZN15UnionNonTrivialC1Ev{{.*}} +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK: define {{.*}} void @_ZN8UnionIntC1Ev{{.*}} +// CHECK-NEXT: entry: +// CHECK: call void @_ZN8UnionIntC2Ev{{.*}} +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK: define {{.*}} void @_ZN15UnionNonTrivialC1Ev{{.*}} +// CHECK-NEXT: entry: +// CHECK: call void @_ZN15UnionNonTrivialC2Ev{{.*}} +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK: define {{.*}} void @_ZN8UnionIntC2Ev{{.*}} +// CHECK-NEXT: entry: +// CHECK: store i32 1000{{.*}} +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK: define {{.*}} void @_ZN15UnionNonTrivialC2Ev{{.*}} +// CHECK-NEXT: entry: +// CHECK: call void @_ZN23non_trivial_constructorC1Ev{{.*}} +// CHECK-NEXT: ret void +// CHECK-NEXT: } Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -9157,7 +9157,18 @@ // 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) { + // [class.default.ctor]p2: + // A defaulted default constructor for class X is defined as deleted if + // - X is a union that has a variant member with a non-trivial default + // constructor and no variant member of X has a default member + // initializer + const auto *RD = cast<CXXRecordDecl>(Field->getParent()); + if (!RD->hasInClassInitializer()) + DiagKind = 4; + } else { + DiagKind = 4; + } } if (DiagKind == -1) Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ 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 <https://github.com/llvm/llvm-project/issues/60166>`_) +- Fix incorrect deletion of the default constructor of unions in some + cases. (`#48416 <https://github.com/llvm/llvm-project/issues/48416>`_) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits