Skip to content

Commit 03c02ea

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 5c717d6 commit 03c02ea

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-1
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ Bug Fixes to C++ Support
217217
- Clang now preserves the unexpanded flag in a lambda transform used for pack expansion. (#GH56852), (#GH85667),
218218
(#GH99877).
219219
- Fixed a bug when diagnosing ambiguous explicit specializations of constrained member functions.
220+
- Clang incorrectly considers a class with an anonymous union member to not be
221+
const-default-constructible even if a union member has a default member initializer.
222+
This is valid as per ``8.3`` in `Draft C++ Standard <https://eel.is/c++draft/dcl.init#general-8.3>`_.
223+
(#GH95854).
220224

221225
Bug Fixes to AST Handling
222226
^^^^^^^^^^^^^^^^^^^^^^^^^

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)