Skip to content

Commit 3ccb1c9

Browse files
committed
[clang] Allow class with anonymous union member to be const-default-constructible even if a union member has a default member initializer (#95854)
Resolves #95854 Clang incorrectly considers a class with an anonymous union member to not be const-default-constructible even if a union member has a default member initializer. ``` struct A { union { int n = 0; int m; }; }; const A a; ``` -- As per https://eel.is/c++draft/dcl.init#general-8.3
1 parent 64d9713 commit 3ccb1c9

File tree

3 files changed

+30
-1
lines changed

3 files changed

+30
-1
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,9 @@ Bug Fixes to C++ Support
219219
- Fixed a bug when diagnosing ambiguous explicit specializations of constrained member functions.
220220
- Fixed an assertion failure when selecting a function from an overload set that includes a
221221
specialization of a conversion function template.
222+
- Clang incorrectly considers a class with an anonymous union member to not be
223+
const-default-constructible even if a union member has a default member initializer.
224+
(#GH95854).
222225

223226
Bug Fixes to AST Handling
224227
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/AST/DeclCXX.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1057,6 +1057,9 @@ void CXXRecordDecl::addedMember(Decl *D) {
10571057
if (isUnion() && !Field->isAnonymousStructOrUnion())
10581058
data().HasVariantMembers = true;
10591059

1060+
if (isUnion() && IsFirstField)
1061+
data().HasUninitializedFields = true;
1062+
10601063
// C++0x [class]p9:
10611064
// A POD struct is a class that is both a trivial class and a
10621065
// standard-layout class, and has no non-static data members of type
@@ -1125,7 +1128,11 @@ void CXXRecordDecl::addedMember(Decl *D) {
11251128
data().DefaultedCopyConstructorIsDeleted = true;
11261129
}
11271130

1128-
if (!Field->hasInClassInitializer() && !Field->isMutable()) {
1131+
if (isUnion() && !Field->isMutable()) {
1132+
if (Field->hasInClassInitializer()) {
1133+
data().HasUninitializedFields = false;
1134+
}
1135+
} else if (!Field->hasInClassInitializer() && !Field->isMutable()) {
11291136
if (CXXRecordDecl *FieldType = T->getAsCXXRecordDecl()) {
11301137
if (FieldType->hasDefinition() && !FieldType->allowConstDefaultInit())
11311138
data().HasUninitializedFields = true;

clang/test/SemaCXX/GH95854.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s
2+
3+
struct A {
4+
union {
5+
int n = 0;
6+
int m;
7+
};
8+
};
9+
const A a;
10+
11+
struct B {
12+
union {
13+
struct {
14+
int n = 5;
15+
int m;
16+
};
17+
};
18+
};
19+
const B b; // expected-error {{default initialization of an object of const type 'const B' without a user-provided default constructor}}

0 commit comments

Comments
 (0)