[clang] [Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member (PR #82407)

2024-05-01 Thread Mital Ashok via cfe-commits


@@ -9442,9 +9442,21 @@ bool 
SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
 
   int DiagKind = -1;
 
-  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
-DiagKind = !Decl ? 0 : 1;
-  else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) {
+if (CSM == Sema::CXXDefaultConstructor && Field &&
+Field->getParent()->isUnion()) {
+  // [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(Field->getParent());
+  if (!RD->hasInClassInitializer())
+DiagKind = !Decl ? 0 : 1;

MitalAshok wrote:

You can refactor it like this: 
https://github.com/MitalAshok/llvm-project/commit/a119d89788c2c642b5a13ea00b2ea649b04a418e
 and I would suggest changing to an enum for readability: 
https://github.com/MitalAshok/llvm-project/commit/38ca82e1a55012e7d37fd8c6d049d1f00bb50835
 (This can then be extracted out into a static function that returns the enum 
and each `DiagKind = ...` can turn into `return ...`, and the `if`/`else if` 
ladder can be dismantled)

https://github.com/llvm/llvm-project/pull/82407
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member (PR #82407)

2024-05-01 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

This is [CWG2084](https://wg21.link/CWG2084). Could you also add some tests to 
CXX/drs/ so that www/cxx_dr_status.html can be updated?

https://github.com/llvm/llvm-project/pull/82407
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member (PR #82407)

2024-03-01 Thread Aaron Ballman via cfe-commits


@@ -9442,9 +9442,21 @@ bool 
SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
 
   int DiagKind = -1;
 
-  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
-DiagKind = !Decl ? 0 : 1;
-  else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) {
+if (CSM == Sema::CXXDefaultConstructor && Field &&
+Field->getParent()->isUnion()) {
+  // [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(Field->getParent());
+  if (!RD->hasInClassInitializer())
+DiagKind = !Decl ? 0 : 1;

AaronBallman wrote:

FWIW, I ran into exactly the same issue that Erich did in noticing that both 
branches do `DiagKind = !Decl ? 0 : 1;`.  That two of us ran into the same 
readability issue suggests that this should be modified to be more clear.

https://github.com/llvm/llvm-project/pull/82407
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member (PR #82407)

2024-02-29 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik updated 
https://github.com/llvm/llvm-project/pull/82407

>From 5fcaeaddccc0f7e370bf7bebce113d8d52e1b1bd Mon Sep 17 00:00:00 2001
From: Shafik Yaghmour 
Date: Tue, 20 Feb 2024 11:22:39 -0800
Subject: [PATCH] [Clang][Sema] Fix incorrect rejection default construction of
 union with nontrivial member

In 765d8a192180f8f33618087b15c022fe758044af we impelemented a fix for incorrect 
deletion of
default constructors in unions. This fix missed a case and so this PR will
extend the fix to cover the additional case.

Fixes: https://github.com/llvm/llvm-project/issues/81774
---
 clang/docs/ReleaseNotes.rst|  3 +++
 clang/lib/Sema/SemaDeclCXX.cpp | 18 +++---
 .../test/CodeGen/union-non-trivial-member.cpp  | 17 +
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp  | 11 +++
 4 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5bca2c965c866b..452382eb6c4a1e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -292,6 +292,9 @@ Bug Fixes to C++ Support
   was only accepted at namespace scope but not at local function scope.
 - Clang no longer tries to call consteval constructors at runtime when they 
appear in a member initializer.
   (`#782154 `_`)
+- Fix for clang incorrectly rejecting the default construction of a union with
+  nontrivial member when another member has an initializer.
+  (`#81774 `_)
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 79263bc3ff671d..25a4b4381ca25e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9442,9 +9442,21 @@ bool 
SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
 
   int DiagKind = -1;
 
-  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
-DiagKind = !Decl ? 0 : 1;
-  else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) {
+if (CSM == Sema::CXXDefaultConstructor && Field &&
+Field->getParent()->isUnion()) {
+  // [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(Field->getParent());
+  if (!RD->hasInClassInitializer())
+DiagKind = !Decl ? 0 : 1;
+} else {
+  DiagKind = !Decl ? 0 : 1;
+}
+  } else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
 DiagKind = 2;
   else if (!isAccessible(Subobj, Decl))
 DiagKind = 3;
diff --git a/clang/test/CodeGen/union-non-trivial-member.cpp 
b/clang/test/CodeGen/union-non-trivial-member.cpp
index fdc9fd16911e14..8b055a9970fc75 100644
--- a/clang/test/CodeGen/union-non-trivial-member.cpp
+++ b/clang/test/CodeGen/union-non-trivial-member.cpp
@@ -15,14 +15,25 @@ union UnionNonTrivial {
 non_trivial_constructor b{};
 };
 
+struct Handle {
+Handle(int) {}
+};
+
+union UnionNonTrivialEqualInit {
+int NoState = 0;
+Handle CustomState;
+};
+
 void f() {
 UnionInt u1;
 UnionNonTrivial u2;
+UnionNonTrivialEqualInit u3;
 }
 
 // CHECK:  define dso_local void @_Z1fv()
 // CHECK:call void @_ZN8UnionIntC1Ev
 // CHECK-NEXT:   call void @_ZN15UnionNonTrivialC1Ev
+// CHECK-NEXT:   call void @_ZN24UnionNonTrivialEqualInitC1Ev
 
 // CHECK:  define {{.*}}void @_ZN8UnionIntC1Ev
 // CHECK:call void @_ZN8UnionIntC2Ev
@@ -30,8 +41,14 @@ void f() {
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC1Ev
 // CHECK:call void @_ZN15UnionNonTrivialC2Ev
 
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC1Ev
+// CHECK:call void @_ZN24UnionNonTrivialEqualInitC2Ev
+
 // CHECK:  define {{.*}}void @_ZN8UnionIntC2Ev
 // CHECK:store i32 1000
 
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC2Ev
 // CHECK:call void @_ZN23non_trivial_constructorC1Ev
+
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC2Ev
+// CHECK:store i32 0
diff --git a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp 
b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
index c7cdf76d850dbe..833642b3d739ab 100644
--- a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
+++ b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
@@ -188,3 +188,14 @@ static_assert(U2().b.x == 100, "");
 static_assert(U3().b.x == 100, "");
 
 } // namespace GH48416
+
+namespace GH81774 {
+struct Handle {
+Handle(int) {}
+};
+// Should be well-formed because NoState has a brace-or-equal-initializer.
+union a {
+int NoState = 0;
+ 

[clang] [Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member (PR #82407)

2024-02-23 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik updated 
https://github.com/llvm/llvm-project/pull/82407

>From 5fcaeaddccc0f7e370bf7bebce113d8d52e1b1bd Mon Sep 17 00:00:00 2001
From: Shafik Yaghmour 
Date: Tue, 20 Feb 2024 11:22:39 -0800
Subject: [PATCH] [Clang][Sema] Fix incorrect rejection default construction of
 union with nontrivial member

In 765d8a192180f8f33618087b15c022fe758044af we impelemented a fix for incorrect 
deletion of
default constructors in unions. This fix missed a case and so this PR will
extend the fix to cover the additional case.

Fixes: https://github.com/llvm/llvm-project/issues/81774
---
 clang/docs/ReleaseNotes.rst|  3 +++
 clang/lib/Sema/SemaDeclCXX.cpp | 18 +++---
 .../test/CodeGen/union-non-trivial-member.cpp  | 17 +
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp  | 11 +++
 4 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5bca2c965c866b..452382eb6c4a1e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -292,6 +292,9 @@ Bug Fixes to C++ Support
   was only accepted at namespace scope but not at local function scope.
 - Clang no longer tries to call consteval constructors at runtime when they 
appear in a member initializer.
   (`#782154 `_`)
+- Fix for clang incorrectly rejecting the default construction of a union with
+  nontrivial member when another member has an initializer.
+  (`#81774 `_)
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 79263bc3ff671d..25a4b4381ca25e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9442,9 +9442,21 @@ bool 
SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
 
   int DiagKind = -1;
 
-  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
-DiagKind = !Decl ? 0 : 1;
-  else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) {
+if (CSM == Sema::CXXDefaultConstructor && Field &&
+Field->getParent()->isUnion()) {
+  // [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(Field->getParent());
+  if (!RD->hasInClassInitializer())
+DiagKind = !Decl ? 0 : 1;
+} else {
+  DiagKind = !Decl ? 0 : 1;
+}
+  } else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
 DiagKind = 2;
   else if (!isAccessible(Subobj, Decl))
 DiagKind = 3;
diff --git a/clang/test/CodeGen/union-non-trivial-member.cpp 
b/clang/test/CodeGen/union-non-trivial-member.cpp
index fdc9fd16911e14..8b055a9970fc75 100644
--- a/clang/test/CodeGen/union-non-trivial-member.cpp
+++ b/clang/test/CodeGen/union-non-trivial-member.cpp
@@ -15,14 +15,25 @@ union UnionNonTrivial {
 non_trivial_constructor b{};
 };
 
+struct Handle {
+Handle(int) {}
+};
+
+union UnionNonTrivialEqualInit {
+int NoState = 0;
+Handle CustomState;
+};
+
 void f() {
 UnionInt u1;
 UnionNonTrivial u2;
+UnionNonTrivialEqualInit u3;
 }
 
 // CHECK:  define dso_local void @_Z1fv()
 // CHECK:call void @_ZN8UnionIntC1Ev
 // CHECK-NEXT:   call void @_ZN15UnionNonTrivialC1Ev
+// CHECK-NEXT:   call void @_ZN24UnionNonTrivialEqualInitC1Ev
 
 // CHECK:  define {{.*}}void @_ZN8UnionIntC1Ev
 // CHECK:call void @_ZN8UnionIntC2Ev
@@ -30,8 +41,14 @@ void f() {
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC1Ev
 // CHECK:call void @_ZN15UnionNonTrivialC2Ev
 
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC1Ev
+// CHECK:call void @_ZN24UnionNonTrivialEqualInitC2Ev
+
 // CHECK:  define {{.*}}void @_ZN8UnionIntC2Ev
 // CHECK:store i32 1000
 
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC2Ev
 // CHECK:call void @_ZN23non_trivial_constructorC1Ev
+
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC2Ev
+// CHECK:store i32 0
diff --git a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp 
b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
index c7cdf76d850dbe..833642b3d739ab 100644
--- a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
+++ b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
@@ -188,3 +188,14 @@ static_assert(U2().b.x == 100, "");
 static_assert(U3().b.x == 100, "");
 
 } // namespace GH48416
+
+namespace GH81774 {
+struct Handle {
+Handle(int) {}
+};
+// Should be well-formed because NoState has a brace-or-equal-initializer.
+union a {
+int NoState = 0;
+ 

[clang] [Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member (PR #82407)

2024-02-23 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik updated 
https://github.com/llvm/llvm-project/pull/82407

>From 5fcaeaddccc0f7e370bf7bebce113d8d52e1b1bd Mon Sep 17 00:00:00 2001
From: Shafik Yaghmour 
Date: Tue, 20 Feb 2024 11:22:39 -0800
Subject: [PATCH] [Clang][Sema] Fix incorrect rejection default construction of
 union with nontrivial member

In 765d8a192180f8f33618087b15c022fe758044af we impelemented a fix for incorrect 
deletion of
default constructors in unions. This fix missed a case and so this PR will
extend the fix to cover the additional case.

Fixes: https://github.com/llvm/llvm-project/issues/81774
---
 clang/docs/ReleaseNotes.rst|  3 +++
 clang/lib/Sema/SemaDeclCXX.cpp | 18 +++---
 .../test/CodeGen/union-non-trivial-member.cpp  | 17 +
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp  | 11 +++
 4 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5bca2c965c866b..452382eb6c4a1e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -292,6 +292,9 @@ Bug Fixes to C++ Support
   was only accepted at namespace scope but not at local function scope.
 - Clang no longer tries to call consteval constructors at runtime when they 
appear in a member initializer.
   (`#782154 `_`)
+- Fix for clang incorrectly rejecting the default construction of a union with
+  nontrivial member when another member has an initializer.
+  (`#81774 `_)
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 79263bc3ff671d..25a4b4381ca25e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9442,9 +9442,21 @@ bool 
SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
 
   int DiagKind = -1;
 
-  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
-DiagKind = !Decl ? 0 : 1;
-  else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) {
+if (CSM == Sema::CXXDefaultConstructor && Field &&
+Field->getParent()->isUnion()) {
+  // [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(Field->getParent());
+  if (!RD->hasInClassInitializer())
+DiagKind = !Decl ? 0 : 1;
+} else {
+  DiagKind = !Decl ? 0 : 1;
+}
+  } else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
 DiagKind = 2;
   else if (!isAccessible(Subobj, Decl))
 DiagKind = 3;
diff --git a/clang/test/CodeGen/union-non-trivial-member.cpp 
b/clang/test/CodeGen/union-non-trivial-member.cpp
index fdc9fd16911e14..8b055a9970fc75 100644
--- a/clang/test/CodeGen/union-non-trivial-member.cpp
+++ b/clang/test/CodeGen/union-non-trivial-member.cpp
@@ -15,14 +15,25 @@ union UnionNonTrivial {
 non_trivial_constructor b{};
 };
 
+struct Handle {
+Handle(int) {}
+};
+
+union UnionNonTrivialEqualInit {
+int NoState = 0;
+Handle CustomState;
+};
+
 void f() {
 UnionInt u1;
 UnionNonTrivial u2;
+UnionNonTrivialEqualInit u3;
 }
 
 // CHECK:  define dso_local void @_Z1fv()
 // CHECK:call void @_ZN8UnionIntC1Ev
 // CHECK-NEXT:   call void @_ZN15UnionNonTrivialC1Ev
+// CHECK-NEXT:   call void @_ZN24UnionNonTrivialEqualInitC1Ev
 
 // CHECK:  define {{.*}}void @_ZN8UnionIntC1Ev
 // CHECK:call void @_ZN8UnionIntC2Ev
@@ -30,8 +41,14 @@ void f() {
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC1Ev
 // CHECK:call void @_ZN15UnionNonTrivialC2Ev
 
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC1Ev
+// CHECK:call void @_ZN24UnionNonTrivialEqualInitC2Ev
+
 // CHECK:  define {{.*}}void @_ZN8UnionIntC2Ev
 // CHECK:store i32 1000
 
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC2Ev
 // CHECK:call void @_ZN23non_trivial_constructorC1Ev
+
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC2Ev
+// CHECK:store i32 0
diff --git a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp 
b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
index c7cdf76d850dbe..833642b3d739ab 100644
--- a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
+++ b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
@@ -188,3 +188,14 @@ static_assert(U2().b.x == 100, "");
 static_assert(U3().b.x == 100, "");
 
 } // namespace GH48416
+
+namespace GH81774 {
+struct Handle {
+Handle(int) {}
+};
+// Should be well-formed because NoState has a brace-or-equal-initializer.
+union a {
+int NoState = 0;
+ 

[clang] [Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member (PR #82407)

2024-02-23 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik updated 
https://github.com/llvm/llvm-project/pull/82407

>From 5fcaeaddccc0f7e370bf7bebce113d8d52e1b1bd Mon Sep 17 00:00:00 2001
From: Shafik Yaghmour 
Date: Tue, 20 Feb 2024 11:22:39 -0800
Subject: [PATCH] [Clang][Sema] Fix incorrect rejection default construction of
 union with nontrivial member

In 765d8a192180f8f33618087b15c022fe758044af we impelemented a fix for incorrect 
deletion of
default constructors in unions. This fix missed a case and so this PR will
extend the fix to cover the additional case.

Fixes: https://github.com/llvm/llvm-project/issues/81774
---
 clang/docs/ReleaseNotes.rst|  3 +++
 clang/lib/Sema/SemaDeclCXX.cpp | 18 +++---
 .../test/CodeGen/union-non-trivial-member.cpp  | 17 +
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp  | 11 +++
 4 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5bca2c965c866b..452382eb6c4a1e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -292,6 +292,9 @@ Bug Fixes to C++ Support
   was only accepted at namespace scope but not at local function scope.
 - Clang no longer tries to call consteval constructors at runtime when they 
appear in a member initializer.
   (`#782154 `_`)
+- Fix for clang incorrectly rejecting the default construction of a union with
+  nontrivial member when another member has an initializer.
+  (`#81774 `_)
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 79263bc3ff671d..25a4b4381ca25e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9442,9 +9442,21 @@ bool 
SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
 
   int DiagKind = -1;
 
-  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
-DiagKind = !Decl ? 0 : 1;
-  else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) {
+if (CSM == Sema::CXXDefaultConstructor && Field &&
+Field->getParent()->isUnion()) {
+  // [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(Field->getParent());
+  if (!RD->hasInClassInitializer())
+DiagKind = !Decl ? 0 : 1;
+} else {
+  DiagKind = !Decl ? 0 : 1;
+}
+  } else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
 DiagKind = 2;
   else if (!isAccessible(Subobj, Decl))
 DiagKind = 3;
diff --git a/clang/test/CodeGen/union-non-trivial-member.cpp 
b/clang/test/CodeGen/union-non-trivial-member.cpp
index fdc9fd16911e14..8b055a9970fc75 100644
--- a/clang/test/CodeGen/union-non-trivial-member.cpp
+++ b/clang/test/CodeGen/union-non-trivial-member.cpp
@@ -15,14 +15,25 @@ union UnionNonTrivial {
 non_trivial_constructor b{};
 };
 
+struct Handle {
+Handle(int) {}
+};
+
+union UnionNonTrivialEqualInit {
+int NoState = 0;
+Handle CustomState;
+};
+
 void f() {
 UnionInt u1;
 UnionNonTrivial u2;
+UnionNonTrivialEqualInit u3;
 }
 
 // CHECK:  define dso_local void @_Z1fv()
 // CHECK:call void @_ZN8UnionIntC1Ev
 // CHECK-NEXT:   call void @_ZN15UnionNonTrivialC1Ev
+// CHECK-NEXT:   call void @_ZN24UnionNonTrivialEqualInitC1Ev
 
 // CHECK:  define {{.*}}void @_ZN8UnionIntC1Ev
 // CHECK:call void @_ZN8UnionIntC2Ev
@@ -30,8 +41,14 @@ void f() {
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC1Ev
 // CHECK:call void @_ZN15UnionNonTrivialC2Ev
 
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC1Ev
+// CHECK:call void @_ZN24UnionNonTrivialEqualInitC2Ev
+
 // CHECK:  define {{.*}}void @_ZN8UnionIntC2Ev
 // CHECK:store i32 1000
 
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC2Ev
 // CHECK:call void @_ZN23non_trivial_constructorC1Ev
+
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC2Ev
+// CHECK:store i32 0
diff --git a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp 
b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
index c7cdf76d850dbe..833642b3d739ab 100644
--- a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
+++ b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
@@ -188,3 +188,14 @@ static_assert(U2().b.x == 100, "");
 static_assert(U3().b.x == 100, "");
 
 } // namespace GH48416
+
+namespace GH81774 {
+struct Handle {
+Handle(int) {}
+};
+// Should be well-formed because NoState has a brace-or-equal-initializer.
+union a {
+int NoState = 0;
+ 

[clang] [Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member (PR #82407)

2024-02-21 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik updated 
https://github.com/llvm/llvm-project/pull/82407

>From 5fcaeaddccc0f7e370bf7bebce113d8d52e1b1bd Mon Sep 17 00:00:00 2001
From: Shafik Yaghmour 
Date: Tue, 20 Feb 2024 11:22:39 -0800
Subject: [PATCH] [Clang][Sema] Fix incorrect rejection default construction of
 union with nontrivial member

In 765d8a192180f8f33618087b15c022fe758044af we impelemented a fix for incorrect 
deletion of
default constructors in unions. This fix missed a case and so this PR will
extend the fix to cover the additional case.

Fixes: https://github.com/llvm/llvm-project/issues/81774
---
 clang/docs/ReleaseNotes.rst|  3 +++
 clang/lib/Sema/SemaDeclCXX.cpp | 18 +++---
 .../test/CodeGen/union-non-trivial-member.cpp  | 17 +
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp  | 11 +++
 4 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5bca2c965c866b..452382eb6c4a1e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -292,6 +292,9 @@ Bug Fixes to C++ Support
   was only accepted at namespace scope but not at local function scope.
 - Clang no longer tries to call consteval constructors at runtime when they 
appear in a member initializer.
   (`#782154 `_`)
+- Fix for clang incorrectly rejecting the default construction of a union with
+  nontrivial member when another member has an initializer.
+  (`#81774 `_)
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 79263bc3ff671d..25a4b4381ca25e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9442,9 +9442,21 @@ bool 
SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
 
   int DiagKind = -1;
 
-  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
-DiagKind = !Decl ? 0 : 1;
-  else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) {
+if (CSM == Sema::CXXDefaultConstructor && Field &&
+Field->getParent()->isUnion()) {
+  // [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(Field->getParent());
+  if (!RD->hasInClassInitializer())
+DiagKind = !Decl ? 0 : 1;
+} else {
+  DiagKind = !Decl ? 0 : 1;
+}
+  } else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
 DiagKind = 2;
   else if (!isAccessible(Subobj, Decl))
 DiagKind = 3;
diff --git a/clang/test/CodeGen/union-non-trivial-member.cpp 
b/clang/test/CodeGen/union-non-trivial-member.cpp
index fdc9fd16911e14..8b055a9970fc75 100644
--- a/clang/test/CodeGen/union-non-trivial-member.cpp
+++ b/clang/test/CodeGen/union-non-trivial-member.cpp
@@ -15,14 +15,25 @@ union UnionNonTrivial {
 non_trivial_constructor b{};
 };
 
+struct Handle {
+Handle(int) {}
+};
+
+union UnionNonTrivialEqualInit {
+int NoState = 0;
+Handle CustomState;
+};
+
 void f() {
 UnionInt u1;
 UnionNonTrivial u2;
+UnionNonTrivialEqualInit u3;
 }
 
 // CHECK:  define dso_local void @_Z1fv()
 // CHECK:call void @_ZN8UnionIntC1Ev
 // CHECK-NEXT:   call void @_ZN15UnionNonTrivialC1Ev
+// CHECK-NEXT:   call void @_ZN24UnionNonTrivialEqualInitC1Ev
 
 // CHECK:  define {{.*}}void @_ZN8UnionIntC1Ev
 // CHECK:call void @_ZN8UnionIntC2Ev
@@ -30,8 +41,14 @@ void f() {
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC1Ev
 // CHECK:call void @_ZN15UnionNonTrivialC2Ev
 
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC1Ev
+// CHECK:call void @_ZN24UnionNonTrivialEqualInitC2Ev
+
 // CHECK:  define {{.*}}void @_ZN8UnionIntC2Ev
 // CHECK:store i32 1000
 
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC2Ev
 // CHECK:call void @_ZN23non_trivial_constructorC1Ev
+
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC2Ev
+// CHECK:store i32 0
diff --git a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp 
b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
index c7cdf76d850dbe..833642b3d739ab 100644
--- a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
+++ b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
@@ -188,3 +188,14 @@ static_assert(U2().b.x == 100, "");
 static_assert(U3().b.x == 100, "");
 
 } // namespace GH48416
+
+namespace GH81774 {
+struct Handle {
+Handle(int) {}
+};
+// Should be well-formed because NoState has a brace-or-equal-initializer.
+union a {
+int NoState = 0;
+ 

[clang] [Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member (PR #82407)

2024-02-21 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik updated 
https://github.com/llvm/llvm-project/pull/82407

>From 5fcaeaddccc0f7e370bf7bebce113d8d52e1b1bd Mon Sep 17 00:00:00 2001
From: Shafik Yaghmour 
Date: Tue, 20 Feb 2024 11:22:39 -0800
Subject: [PATCH] [Clang][Sema] Fix incorrect rejection default construction of
 union with nontrivial member

In 765d8a192180f8f33618087b15c022fe758044af we impelemented a fix for incorrect 
deletion of
default constructors in unions. This fix missed a case and so this PR will
extend the fix to cover the additional case.

Fixes: https://github.com/llvm/llvm-project/issues/81774
---
 clang/docs/ReleaseNotes.rst|  3 +++
 clang/lib/Sema/SemaDeclCXX.cpp | 18 +++---
 .../test/CodeGen/union-non-trivial-member.cpp  | 17 +
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp  | 11 +++
 4 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5bca2c965c866b..452382eb6c4a1e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -292,6 +292,9 @@ Bug Fixes to C++ Support
   was only accepted at namespace scope but not at local function scope.
 - Clang no longer tries to call consteval constructors at runtime when they 
appear in a member initializer.
   (`#782154 `_`)
+- Fix for clang incorrectly rejecting the default construction of a union with
+  nontrivial member when another member has an initializer.
+  (`#81774 `_)
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 79263bc3ff671d..25a4b4381ca25e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9442,9 +9442,21 @@ bool 
SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
 
   int DiagKind = -1;
 
-  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
-DiagKind = !Decl ? 0 : 1;
-  else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) {
+if (CSM == Sema::CXXDefaultConstructor && Field &&
+Field->getParent()->isUnion()) {
+  // [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(Field->getParent());
+  if (!RD->hasInClassInitializer())
+DiagKind = !Decl ? 0 : 1;
+} else {
+  DiagKind = !Decl ? 0 : 1;
+}
+  } else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
 DiagKind = 2;
   else if (!isAccessible(Subobj, Decl))
 DiagKind = 3;
diff --git a/clang/test/CodeGen/union-non-trivial-member.cpp 
b/clang/test/CodeGen/union-non-trivial-member.cpp
index fdc9fd16911e14..8b055a9970fc75 100644
--- a/clang/test/CodeGen/union-non-trivial-member.cpp
+++ b/clang/test/CodeGen/union-non-trivial-member.cpp
@@ -15,14 +15,25 @@ union UnionNonTrivial {
 non_trivial_constructor b{};
 };
 
+struct Handle {
+Handle(int) {}
+};
+
+union UnionNonTrivialEqualInit {
+int NoState = 0;
+Handle CustomState;
+};
+
 void f() {
 UnionInt u1;
 UnionNonTrivial u2;
+UnionNonTrivialEqualInit u3;
 }
 
 // CHECK:  define dso_local void @_Z1fv()
 // CHECK:call void @_ZN8UnionIntC1Ev
 // CHECK-NEXT:   call void @_ZN15UnionNonTrivialC1Ev
+// CHECK-NEXT:   call void @_ZN24UnionNonTrivialEqualInitC1Ev
 
 // CHECK:  define {{.*}}void @_ZN8UnionIntC1Ev
 // CHECK:call void @_ZN8UnionIntC2Ev
@@ -30,8 +41,14 @@ void f() {
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC1Ev
 // CHECK:call void @_ZN15UnionNonTrivialC2Ev
 
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC1Ev
+// CHECK:call void @_ZN24UnionNonTrivialEqualInitC2Ev
+
 // CHECK:  define {{.*}}void @_ZN8UnionIntC2Ev
 // CHECK:store i32 1000
 
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC2Ev
 // CHECK:call void @_ZN23non_trivial_constructorC1Ev
+
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC2Ev
+// CHECK:store i32 0
diff --git a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp 
b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
index c7cdf76d850dbe..833642b3d739ab 100644
--- a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
+++ b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
@@ -188,3 +188,14 @@ static_assert(U2().b.x == 100, "");
 static_assert(U3().b.x == 100, "");
 
 } // namespace GH48416
+
+namespace GH81774 {
+struct Handle {
+Handle(int) {}
+};
+// Should be well-formed because NoState has a brace-or-equal-initializer.
+union a {
+int NoState = 0;
+ 

[clang] [Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member (PR #82407)

2024-02-21 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik updated 
https://github.com/llvm/llvm-project/pull/82407

>From 5fcaeaddccc0f7e370bf7bebce113d8d52e1b1bd Mon Sep 17 00:00:00 2001
From: Shafik Yaghmour 
Date: Tue, 20 Feb 2024 11:22:39 -0800
Subject: [PATCH] [Clang][Sema] Fix incorrect rejection default construction of
 union with nontrivial member

In 765d8a192180f8f33618087b15c022fe758044af we impelemented a fix for incorrect 
deletion of
default constructors in unions. This fix missed a case and so this PR will
extend the fix to cover the additional case.

Fixes: https://github.com/llvm/llvm-project/issues/81774
---
 clang/docs/ReleaseNotes.rst|  3 +++
 clang/lib/Sema/SemaDeclCXX.cpp | 18 +++---
 .../test/CodeGen/union-non-trivial-member.cpp  | 17 +
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp  | 11 +++
 4 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5bca2c965c866b..452382eb6c4a1e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -292,6 +292,9 @@ Bug Fixes to C++ Support
   was only accepted at namespace scope but not at local function scope.
 - Clang no longer tries to call consteval constructors at runtime when they 
appear in a member initializer.
   (`#782154 `_`)
+- Fix for clang incorrectly rejecting the default construction of a union with
+  nontrivial member when another member has an initializer.
+  (`#81774 `_)
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 79263bc3ff671d..25a4b4381ca25e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9442,9 +9442,21 @@ bool 
SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
 
   int DiagKind = -1;
 
-  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
-DiagKind = !Decl ? 0 : 1;
-  else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) {
+if (CSM == Sema::CXXDefaultConstructor && Field &&
+Field->getParent()->isUnion()) {
+  // [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(Field->getParent());
+  if (!RD->hasInClassInitializer())
+DiagKind = !Decl ? 0 : 1;
+} else {
+  DiagKind = !Decl ? 0 : 1;
+}
+  } else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
 DiagKind = 2;
   else if (!isAccessible(Subobj, Decl))
 DiagKind = 3;
diff --git a/clang/test/CodeGen/union-non-trivial-member.cpp 
b/clang/test/CodeGen/union-non-trivial-member.cpp
index fdc9fd16911e14..8b055a9970fc75 100644
--- a/clang/test/CodeGen/union-non-trivial-member.cpp
+++ b/clang/test/CodeGen/union-non-trivial-member.cpp
@@ -15,14 +15,25 @@ union UnionNonTrivial {
 non_trivial_constructor b{};
 };
 
+struct Handle {
+Handle(int) {}
+};
+
+union UnionNonTrivialEqualInit {
+int NoState = 0;
+Handle CustomState;
+};
+
 void f() {
 UnionInt u1;
 UnionNonTrivial u2;
+UnionNonTrivialEqualInit u3;
 }
 
 // CHECK:  define dso_local void @_Z1fv()
 // CHECK:call void @_ZN8UnionIntC1Ev
 // CHECK-NEXT:   call void @_ZN15UnionNonTrivialC1Ev
+// CHECK-NEXT:   call void @_ZN24UnionNonTrivialEqualInitC1Ev
 
 // CHECK:  define {{.*}}void @_ZN8UnionIntC1Ev
 // CHECK:call void @_ZN8UnionIntC2Ev
@@ -30,8 +41,14 @@ void f() {
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC1Ev
 // CHECK:call void @_ZN15UnionNonTrivialC2Ev
 
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC1Ev
+// CHECK:call void @_ZN24UnionNonTrivialEqualInitC2Ev
+
 // CHECK:  define {{.*}}void @_ZN8UnionIntC2Ev
 // CHECK:store i32 1000
 
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC2Ev
 // CHECK:call void @_ZN23non_trivial_constructorC1Ev
+
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC2Ev
+// CHECK:store i32 0
diff --git a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp 
b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
index c7cdf76d850dbe..833642b3d739ab 100644
--- a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
+++ b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
@@ -188,3 +188,14 @@ static_assert(U2().b.x == 100, "");
 static_assert(U3().b.x == 100, "");
 
 } // namespace GH48416
+
+namespace GH81774 {
+struct Handle {
+Handle(int) {}
+};
+// Should be well-formed because NoState has a brace-or-equal-initializer.
+union a {
+int NoState = 0;
+ 

[clang] [Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member (PR #82407)

2024-02-20 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik updated 
https://github.com/llvm/llvm-project/pull/82407

>From 5fcaeaddccc0f7e370bf7bebce113d8d52e1b1bd Mon Sep 17 00:00:00 2001
From: Shafik Yaghmour 
Date: Tue, 20 Feb 2024 11:22:39 -0800
Subject: [PATCH] [Clang][Sema] Fix incorrect rejection default construction of
 union with nontrivial member

In 765d8a192180f8f33618087b15c022fe758044af we impelemented a fix for incorrect 
deletion of
default constructors in unions. This fix missed a case and so this PR will
extend the fix to cover the additional case.

Fixes: https://github.com/llvm/llvm-project/issues/81774
---
 clang/docs/ReleaseNotes.rst|  3 +++
 clang/lib/Sema/SemaDeclCXX.cpp | 18 +++---
 .../test/CodeGen/union-non-trivial-member.cpp  | 17 +
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp  | 11 +++
 4 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5bca2c965c866b..452382eb6c4a1e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -292,6 +292,9 @@ Bug Fixes to C++ Support
   was only accepted at namespace scope but not at local function scope.
 - Clang no longer tries to call consteval constructors at runtime when they 
appear in a member initializer.
   (`#782154 `_`)
+- Fix for clang incorrectly rejecting the default construction of a union with
+  nontrivial member when another member has an initializer.
+  (`#81774 `_)
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 79263bc3ff671d..25a4b4381ca25e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9442,9 +9442,21 @@ bool 
SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
 
   int DiagKind = -1;
 
-  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
-DiagKind = !Decl ? 0 : 1;
-  else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) {
+if (CSM == Sema::CXXDefaultConstructor && Field &&
+Field->getParent()->isUnion()) {
+  // [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(Field->getParent());
+  if (!RD->hasInClassInitializer())
+DiagKind = !Decl ? 0 : 1;
+} else {
+  DiagKind = !Decl ? 0 : 1;
+}
+  } else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
 DiagKind = 2;
   else if (!isAccessible(Subobj, Decl))
 DiagKind = 3;
diff --git a/clang/test/CodeGen/union-non-trivial-member.cpp 
b/clang/test/CodeGen/union-non-trivial-member.cpp
index fdc9fd16911e14..8b055a9970fc75 100644
--- a/clang/test/CodeGen/union-non-trivial-member.cpp
+++ b/clang/test/CodeGen/union-non-trivial-member.cpp
@@ -15,14 +15,25 @@ union UnionNonTrivial {
 non_trivial_constructor b{};
 };
 
+struct Handle {
+Handle(int) {}
+};
+
+union UnionNonTrivialEqualInit {
+int NoState = 0;
+Handle CustomState;
+};
+
 void f() {
 UnionInt u1;
 UnionNonTrivial u2;
+UnionNonTrivialEqualInit u3;
 }
 
 // CHECK:  define dso_local void @_Z1fv()
 // CHECK:call void @_ZN8UnionIntC1Ev
 // CHECK-NEXT:   call void @_ZN15UnionNonTrivialC1Ev
+// CHECK-NEXT:   call void @_ZN24UnionNonTrivialEqualInitC1Ev
 
 // CHECK:  define {{.*}}void @_ZN8UnionIntC1Ev
 // CHECK:call void @_ZN8UnionIntC2Ev
@@ -30,8 +41,14 @@ void f() {
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC1Ev
 // CHECK:call void @_ZN15UnionNonTrivialC2Ev
 
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC1Ev
+// CHECK:call void @_ZN24UnionNonTrivialEqualInitC2Ev
+
 // CHECK:  define {{.*}}void @_ZN8UnionIntC2Ev
 // CHECK:store i32 1000
 
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC2Ev
 // CHECK:call void @_ZN23non_trivial_constructorC1Ev
+
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC2Ev
+// CHECK:store i32 0
diff --git a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp 
b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
index c7cdf76d850dbe..833642b3d739ab 100644
--- a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
+++ b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
@@ -188,3 +188,14 @@ static_assert(U2().b.x == 100, "");
 static_assert(U3().b.x == 100, "");
 
 } // namespace GH48416
+
+namespace GH81774 {
+struct Handle {
+Handle(int) {}
+};
+// Should be well-formed because NoState has a brace-or-equal-initializer.
+union a {
+int NoState = 0;
+ 

[clang] [Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member (PR #82407)

2024-02-20 Thread Shafik Yaghmour via cfe-commits


@@ -9442,9 +9442,21 @@ bool 
SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
 
   int DiagKind = -1;
 
-  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
-DiagKind = !Decl ? 0 : 1;
-  else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) {
+if (CSM == Sema::CXXDefaultConstructor && Field &&
+Field->getParent()->isUnion()) {
+  // [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(Field->getParent());
+  if (!RD->hasInClassInitializer())
+DiagKind = !Decl ? 0 : 1;

shafik wrote:

I have three different states I need to check, I can remove a check by setting 
`DiagKind` unconditionally and then check `if(RD->hasInClassInitializer())` 
instead and in that case set it back to `-1` but that does not express the 
intent as clearly. So I think what I have now is more maintainable although 
slightly more verbose. 

https://github.com/llvm/llvm-project/pull/82407
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member (PR #82407)

2024-02-20 Thread Erich Keane via cfe-commits


@@ -188,3 +188,14 @@ static_assert(U2().b.x == 100, "");
 static_assert(U3().b.x == 100, "");
 
 } // namespace GH48416
+
+namespace GH81774 {
+struct Handle {
+Handle(int) {}
+};
+// Should be well-formed b/c NoState has a brace-or-equal-initializer

erichkeane wrote:

```suggestion
// Should be well-formed because NoState has a brace-or-equal-initializer.
```


https://github.com/llvm/llvm-project/pull/82407
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member (PR #82407)

2024-02-20 Thread Erich Keane via cfe-commits


@@ -9442,9 +9442,21 @@ bool 
SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
 
   int DiagKind = -1;
 
-  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
-DiagKind = !Decl ? 0 : 1;
-  else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) {
+if (CSM == Sema::CXXDefaultConstructor && Field &&
+Field->getParent()->isUnion()) {
+  // [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(Field->getParent());
+  if (!RD->hasInClassInitializer())
+DiagKind = !Decl ? 0 : 1;

erichkeane wrote:

So what is going on here?  this is the same value as its 'else' clause, and 
leaves DiagKind as -1 otherwise?  I might suggest making this a single 'if' and 
getting rid of the 'else' here.

https://github.com/llvm/llvm-project/pull/82407
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member (PR #82407)

2024-02-20 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Shafik Yaghmour (shafik)


Changes

In 765d8a192180f8f33618087b15c022fe758044af we impelemented a fix for incorrect 
deletion of default constructors in unions. This fix missed a case and so this 
PR will extend the fix to cover the additional case.

Fixes: https://github.com/llvm/llvm-project/issues/81774

---
Full diff: https://github.com/llvm/llvm-project/pull/82407.diff


4 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+3) 
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+15-3) 
- (modified) clang/test/CodeGen/union-non-trivial-member.cpp (+17) 
- (modified) clang/test/SemaCXX/cxx0x-nontrivial-union.cpp (+11) 


``diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5bca2c965c866b..452382eb6c4a1e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -292,6 +292,9 @@ Bug Fixes to C++ Support
   was only accepted at namespace scope but not at local function scope.
 - Clang no longer tries to call consteval constructors at runtime when they 
appear in a member initializer.
   (`#782154 `_`)
+- Fix for clang incorrectly rejecting the default construction of a union with
+  nontrivial member when another member has an initializer.
+  (`#81774 `_)
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 79263bc3ff671d..25a4b4381ca25e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9442,9 +9442,21 @@ bool 
SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
 
   int DiagKind = -1;
 
-  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
-DiagKind = !Decl ? 0 : 1;
-  else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) {
+if (CSM == Sema::CXXDefaultConstructor && Field &&
+Field->getParent()->isUnion()) {
+  // [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(Field->getParent());
+  if (!RD->hasInClassInitializer())
+DiagKind = !Decl ? 0 : 1;
+} else {
+  DiagKind = !Decl ? 0 : 1;
+}
+  } else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
 DiagKind = 2;
   else if (!isAccessible(Subobj, Decl))
 DiagKind = 3;
diff --git a/clang/test/CodeGen/union-non-trivial-member.cpp 
b/clang/test/CodeGen/union-non-trivial-member.cpp
index fdc9fd16911e14..8b055a9970fc75 100644
--- a/clang/test/CodeGen/union-non-trivial-member.cpp
+++ b/clang/test/CodeGen/union-non-trivial-member.cpp
@@ -15,14 +15,25 @@ union UnionNonTrivial {
 non_trivial_constructor b{};
 };
 
+struct Handle {
+Handle(int) {}
+};
+
+union UnionNonTrivialEqualInit {
+int NoState = 0;
+Handle CustomState;
+};
+
 void f() {
 UnionInt u1;
 UnionNonTrivial u2;
+UnionNonTrivialEqualInit u3;
 }
 
 // CHECK:  define dso_local void @_Z1fv()
 // CHECK:call void @_ZN8UnionIntC1Ev
 // CHECK-NEXT:   call void @_ZN15UnionNonTrivialC1Ev
+// CHECK-NEXT:   call void @_ZN24UnionNonTrivialEqualInitC1Ev
 
 // CHECK:  define {{.*}}void @_ZN8UnionIntC1Ev
 // CHECK:call void @_ZN8UnionIntC2Ev
@@ -30,8 +41,14 @@ void f() {
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC1Ev
 // CHECK:call void @_ZN15UnionNonTrivialC2Ev
 
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC1Ev
+// CHECK:call void @_ZN24UnionNonTrivialEqualInitC2Ev
+
 // CHECK:  define {{.*}}void @_ZN8UnionIntC2Ev
 // CHECK:store i32 1000
 
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC2Ev
 // CHECK:call void @_ZN23non_trivial_constructorC1Ev
+
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC2Ev
+// CHECK:store i32 0
diff --git a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp 
b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
index c7cdf76d850dbe..141fe96f512471 100644
--- a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
+++ b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
@@ -188,3 +188,14 @@ static_assert(U2().b.x == 100, "");
 static_assert(U3().b.x == 100, "");
 
 } // namespace GH48416
+
+namespace GH81774 {
+struct Handle {
+Handle(int) {}
+};
+// Should be well-formed b/c NoState has a brace-or-equal-initializer
+union a {
+int NoState = 0;
+Handle CustomState;
+} b;
+} // namespace GH81774

``




https://github.com/llvm/llvm-project/pull/82407
___
cfe-commits mailing list
cfe-commits@lists.llvm.org

[clang] [Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member (PR #82407)

2024-02-20 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik created 
https://github.com/llvm/llvm-project/pull/82407

In 765d8a192180f8f33618087b15c022fe758044af we impelemented a fix for incorrect 
deletion of default constructors in unions. This fix missed a case and so this 
PR will extend the fix to cover the additional case.

Fixes: https://github.com/llvm/llvm-project/issues/81774

>From 285a76507f4497e3114b7b53196576889e5c0b1a Mon Sep 17 00:00:00 2001
From: Shafik Yaghmour 
Date: Tue, 20 Feb 2024 11:22:39 -0800
Subject: [PATCH] [Clang][Sema] Fix incorrect rejection default construction of
 union with nontrivial member

In 765d8a192180f8f33618087b15c022fe758044af we impelemented a fix for incorrect 
deletion of
default constructors in unions. This fix missed a case and so this PR will
extend the fix to cover the additional case.

Fixes: https://github.com/llvm/llvm-project/issues/81774
---
 clang/docs/ReleaseNotes.rst|  3 +++
 clang/lib/Sema/SemaDeclCXX.cpp | 18 +++---
 .../test/CodeGen/union-non-trivial-member.cpp  | 17 +
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp  | 11 +++
 4 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5bca2c965c866b..452382eb6c4a1e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -292,6 +292,9 @@ Bug Fixes to C++ Support
   was only accepted at namespace scope but not at local function scope.
 - Clang no longer tries to call consteval constructors at runtime when they 
appear in a member initializer.
   (`#782154 `_`)
+- Fix for clang incorrectly rejecting the default construction of a union with
+  nontrivial member when another member has an initializer.
+  (`#81774 `_)
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 79263bc3ff671d..25a4b4381ca25e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9442,9 +9442,21 @@ bool 
SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
 
   int DiagKind = -1;
 
-  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
-DiagKind = !Decl ? 0 : 1;
-  else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) {
+if (CSM == Sema::CXXDefaultConstructor && Field &&
+Field->getParent()->isUnion()) {
+  // [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(Field->getParent());
+  if (!RD->hasInClassInitializer())
+DiagKind = !Decl ? 0 : 1;
+} else {
+  DiagKind = !Decl ? 0 : 1;
+}
+  } else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
 DiagKind = 2;
   else if (!isAccessible(Subobj, Decl))
 DiagKind = 3;
diff --git a/clang/test/CodeGen/union-non-trivial-member.cpp 
b/clang/test/CodeGen/union-non-trivial-member.cpp
index fdc9fd16911e14..8b055a9970fc75 100644
--- a/clang/test/CodeGen/union-non-trivial-member.cpp
+++ b/clang/test/CodeGen/union-non-trivial-member.cpp
@@ -15,14 +15,25 @@ union UnionNonTrivial {
 non_trivial_constructor b{};
 };
 
+struct Handle {
+Handle(int) {}
+};
+
+union UnionNonTrivialEqualInit {
+int NoState = 0;
+Handle CustomState;
+};
+
 void f() {
 UnionInt u1;
 UnionNonTrivial u2;
+UnionNonTrivialEqualInit u3;
 }
 
 // CHECK:  define dso_local void @_Z1fv()
 // CHECK:call void @_ZN8UnionIntC1Ev
 // CHECK-NEXT:   call void @_ZN15UnionNonTrivialC1Ev
+// CHECK-NEXT:   call void @_ZN24UnionNonTrivialEqualInitC1Ev
 
 // CHECK:  define {{.*}}void @_ZN8UnionIntC1Ev
 // CHECK:call void @_ZN8UnionIntC2Ev
@@ -30,8 +41,14 @@ void f() {
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC1Ev
 // CHECK:call void @_ZN15UnionNonTrivialC2Ev
 
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC1Ev
+// CHECK:call void @_ZN24UnionNonTrivialEqualInitC2Ev
+
 // CHECK:  define {{.*}}void @_ZN8UnionIntC2Ev
 // CHECK:store i32 1000
 
 // CHECK:  define {{.*}}void @_ZN15UnionNonTrivialC2Ev
 // CHECK:call void @_ZN23non_trivial_constructorC1Ev
+
+// CHECK:  define {{.*}}void @_ZN24UnionNonTrivialEqualInitC2Ev
+// CHECK:store i32 0
diff --git a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp 
b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
index c7cdf76d850dbe..141fe96f512471 100644
--- a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
+++ b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
@@ -188,3 +188,14 @@