[clang] 765d8a1 - [Clang][Sema] Fix incorrect deletion of default constructors for some unions

Roy Jacobson via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 15 14:55:59 PDT 2023


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 at -1 {{static assertion expression is not an integral constant expression}}
+// expected-note at -2 {{read of member 'a' of union with active member 'b'}}
+static_assert(U2().b.x == 100, "");
+// expected-error at -1 {{static assertion expression is not an integral constant expression}}
+// expected-note at -2 {{read of member 'b' of union with active member 'a'}}
+static_assert(U3().b.x == 100, "");
+
+} // namespace GH48416


        


More information about the cfe-commits mailing list