Skip to content

Commit 5fcaead

Browse files
committed
[Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member
In 765d8a1 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: #81774
1 parent 807ed69 commit 5fcaead

File tree

4 files changed

+46
-3
lines changed

4 files changed

+46
-3
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,9 @@ Bug Fixes to C++ Support
292292
was only accepted at namespace scope but not at local function scope.
293293
- Clang no longer tries to call consteval constructors at runtime when they appear in a member initializer.
294294
(`#782154 <https://github.com/llvm/llvm-project/issues/82154>`_`)
295+
- Fix for clang incorrectly rejecting the default construction of a union with
296+
nontrivial member when another member has an initializer.
297+
(`#81774 <https://github.com/llvm/llvm-project/issues/81774>`_)
295298

296299
Bug Fixes to AST Handling
297300
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9442,9 +9442,21 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
94429442

94439443
int DiagKind = -1;
94449444

9445-
if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
9446-
DiagKind = !Decl ? 0 : 1;
9447-
else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
9445+
if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) {
9446+
if (CSM == Sema::CXXDefaultConstructor && Field &&
9447+
Field->getParent()->isUnion()) {
9448+
// [class.default.ctor]p2:
9449+
// A defaulted default constructor for class X is defined as deleted if
9450+
// - X is a union that has a variant member with a non-trivial default
9451+
// constructor and no variant member of X has a default member
9452+
// initializer
9453+
const auto *RD = cast<CXXRecordDecl>(Field->getParent());
9454+
if (!RD->hasInClassInitializer())
9455+
DiagKind = !Decl ? 0 : 1;
9456+
} else {
9457+
DiagKind = !Decl ? 0 : 1;
9458+
}
9459+
} else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
94489460
DiagKind = 2;
94499461
else if (!isAccessible(Subobj, Decl))
94509462
DiagKind = 3;

clang/test/CodeGen/union-non-trivial-member.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,40 @@ union UnionNonTrivial {
1515
non_trivial_constructor b{};
1616
};
1717

18+
struct Handle {
19+
Handle(int) {}
20+
};
21+
22+
union UnionNonTrivialEqualInit {
23+
int NoState = 0;
24+
Handle CustomState;
25+
};
26+
1827
void f() {
1928
UnionInt u1;
2029
UnionNonTrivial u2;
30+
UnionNonTrivialEqualInit u3;
2131
}
2232

2333
// CHECK: define dso_local void @_Z1fv()
2434
// CHECK: call void @_ZN8UnionIntC1Ev
2535
// CHECK-NEXT: call void @_ZN15UnionNonTrivialC1Ev
36+
// CHECK-NEXT: call void @_ZN24UnionNonTrivialEqualInitC1Ev
2637

2738
// CHECK: define {{.*}}void @_ZN8UnionIntC1Ev
2839
// CHECK: call void @_ZN8UnionIntC2Ev
2940

3041
// CHECK: define {{.*}}void @_ZN15UnionNonTrivialC1Ev
3142
// CHECK: call void @_ZN15UnionNonTrivialC2Ev
3243

44+
// CHECK: define {{.*}}void @_ZN24UnionNonTrivialEqualInitC1Ev
45+
// CHECK: call void @_ZN24UnionNonTrivialEqualInitC2Ev
46+
3347
// CHECK: define {{.*}}void @_ZN8UnionIntC2Ev
3448
// CHECK: store i32 1000
3549

3650
// CHECK: define {{.*}}void @_ZN15UnionNonTrivialC2Ev
3751
// CHECK: call void @_ZN23non_trivial_constructorC1Ev
52+
53+
// CHECK: define {{.*}}void @_ZN24UnionNonTrivialEqualInitC2Ev
54+
// CHECK: store i32 0

clang/test/SemaCXX/cxx0x-nontrivial-union.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,3 +188,14 @@ static_assert(U2().b.x == 100, "");
188188
static_assert(U3().b.x == 100, "");
189189

190190
} // namespace GH48416
191+
192+
namespace GH81774 {
193+
struct Handle {
194+
Handle(int) {}
195+
};
196+
// Should be well-formed because NoState has a brace-or-equal-initializer.
197+
union a {
198+
int NoState = 0;
199+
Handle CustomState;
200+
} b;
201+
} // namespace GH81774

0 commit comments

Comments
 (0)