Skip to content

Commit 7305734

Browse files
authored
[clang] Allow class with anonymous union member to be const-default-constructible even if a union member has a default member initializer (#95854) (#96301)
Resolves #95854 -- As per https://eel.is/c++draft/dcl.init#general-8.3
1 parent 4614b80 commit 7305734

File tree

3 files changed

+61
-1
lines changed

3 files changed

+61
-1
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,9 @@ Bug Fixes to C++ Support
539539
- Fix erroneous templated array size calculation leading to crashes in generated code. (#GH41441)
540540
- During the lookup for a base class name, non-type names are ignored. (#GH16855)
541541
- Fix a crash when recovering an invalid expression involving an explicit object member conversion operator. (#GH112559)
542+
- Clang incorrectly considered a class with an anonymous union member to not be
543+
const-default-constructible even if a union member has a default member initializer.
544+
(#GH95854).
542545

543546
Bug Fixes to AST Handling
544547
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/AST/DeclCXX.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,9 @@ void CXXRecordDecl::addedMember(Decl *D) {
10601060
if (isUnion() && !Field->isAnonymousStructOrUnion())
10611061
data().HasVariantMembers = true;
10621062

1063+
if (isUnion() && IsFirstField)
1064+
data().HasUninitializedFields = true;
1065+
10631066
// C++0x [class]p9:
10641067
// A POD struct is a class that is both a trivial class and a
10651068
// standard-layout class, and has no non-static data members of type
@@ -1128,7 +1131,10 @@ void CXXRecordDecl::addedMember(Decl *D) {
11281131
data().DefaultedCopyConstructorIsDeleted = true;
11291132
}
11301133

1131-
if (!Field->hasInClassInitializer() && !Field->isMutable()) {
1134+
if (isUnion() && !Field->isMutable()) {
1135+
if (Field->hasInClassInitializer())
1136+
data().HasUninitializedFields = false;
1137+
} else if (!Field->hasInClassInitializer() && !Field->isMutable()) {
11321138
if (CXXRecordDecl *FieldType = T->getAsCXXRecordDecl()) {
11331139
if (FieldType->hasDefinition() && !FieldType->allowConstDefaultInit())
11341140
data().HasUninitializedFields = true;

clang/test/SemaCXX/GH95854.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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}}
20+
21+
struct S {
22+
int i;
23+
int j;
24+
};
25+
26+
struct T {
27+
T() = default;
28+
};
29+
30+
struct C {
31+
union {
32+
S s;
33+
};
34+
};
35+
36+
struct D {
37+
union {
38+
T s;
39+
};
40+
};
41+
42+
const C c; // expected-error {{default initialization of an object of const type 'const C' without a user-provided default constructor}}
43+
const D d; // expected-error {{default initialization of an object of const type 'const D' without a user-provided default constructor}}
44+
45+
struct E {
46+
union {
47+
int n;
48+
int m=0;
49+
};
50+
};
51+
const E e;

0 commit comments

Comments
 (0)