Author: Roy Jacobson Date: 2023-03-15T23:55:52+02:00 New Revision: 765d8a192180f8f33618087b15c022fe758044af
URL: https://github.com/llvm/llvm-project/commit/765d8a192180f8f33618087b15c022fe758044af DIFF: https://github.com/llvm/llvm-project/commit/765d8a192180f8f33618087b15c022fe758044af.diff LOG: [Clang][Sema] Fix incorrect deletion of default constructors for some unions If a union has explicit initializers for some members, we shouldn't delete its default constructor. Fixes https://github.com/llvm/llvm-project/issues/48416. Reviewed By: erichkeane Differential Revision: https://reviews.llvm.org/D145851 Added: clang/test/CodeGen/union-non-trivial-member.cpp Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaDeclCXX.cpp clang/test/SemaCXX/cxx0x-nontrivial-union.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 10be3be259bc..09a3daee6887 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -225,6 +225,8 @@ Bug Fixes to C++ Support - Fix an issue about ``decltype`` in the members of class templates derived from templates with related parameters. (`#58674 <https://github.com/llvm/llvm-project/issues/58674>`_) +- 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 ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 41c76e5c1371..16e1071366b3 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -9158,7 +9158,18 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall( // 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) diff --git a/clang/test/CodeGen/union-non-trivial-member.cpp b/clang/test/CodeGen/union-non-trivial-member.cpp new file mode 100644 index 000000000000..fdc9fd16911e --- /dev/null +++ b/clang/test/CodeGen/union-non-trivial-member.cpp @@ -0,0 +1,37 @@ +// 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: call void @_ZN8UnionIntC1Ev +// CHECK-NEXT: call void @_ZN15UnionNonTrivialC1Ev + +// CHECK: define {{.*}}void @_ZN8UnionIntC1Ev +// CHECK: call void @_ZN8UnionIntC2Ev + +// CHECK: define {{.*}}void @_ZN15UnionNonTrivialC1Ev +// CHECK: call void @_ZN15UnionNonTrivialC2Ev + +// CHECK: define {{.*}}void @_ZN8UnionIntC2Ev +// CHECK: store i32 1000 + +// CHECK: define {{.*}}void @_ZN15UnionNonTrivialC2Ev +// CHECK: call void @_ZN23non_trivial_constructorC1Ev diff --git a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp index ad1f09fee33f..4a4bf7180a47 100644 --- a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp +++ b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp @@ -144,3 +144,47 @@ namespace pr16061 { 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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits