Skip to content

Commit 6fb23af

Browse files
authored
[C] Do not diagnose unions with -Wdefault-const-init (#140725)
A default-initialized union with a const member is generally reasonable in C and isn't necessarily incompatible with C++, so we now silence the diagnostic in that case. However, we do still diagnose a const- qualified, default-initialized union as that is incompatible with C++.
1 parent a1e314d commit 6fb23af

File tree

2 files changed

+16
-2
lines changed

2 files changed

+16
-2
lines changed

clang/lib/Sema/SemaInit.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6602,8 +6602,10 @@ void InitializationSequence::InitializeFrom(Sema &S,
66026602
}
66036603
// If the record has any members which are const (recursively checked),
66046604
// then we want to diagnose those as being uninitialized if there is no
6605-
// initializer present.
6606-
if (!Initializer) {
6605+
// initializer present. However, we only do this for structure types, not
6606+
// union types, because an unitialized field in a union is generally
6607+
// reasonable, especially in C where unions can be used for type punning.
6608+
if (!Initializer && !Rec->isUnion()) {
66076609
if (const FieldDecl *FD = getConstField(Rec)) {
66086610
unsigned DiagID = diag::warn_default_init_const_field_unsafe;
66096611
if (Var->getStorageDuration() == SD_Static ||

clang/test/Sema/warn-default-const-init.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ struct V { int i; const struct A a; }; // unsafe-field-note {{member 'a' declare
3535
struct W { struct A a; const int j; }; // unsafe-field-note {{member 'j' declared 'const' here}} \
3636
unsafe-field-compat-note {{member 'j' declared 'const' here}} \
3737
cxx-note {{default constructor of 'W' is implicitly deleted because field 'j' of const-qualified type 'const int' would not be initialized}}
38+
union Z1 { int i; const int j; };
39+
union Z2 { int i; const struct A a; };
3840

3941
void f() {
4042
struct S s1; // unsafe-field-warning {{default initialization of an object of type 'struct S' with const member leaves the object uninitialized}} \
@@ -66,6 +68,14 @@ void y() {
6668
struct W w2 = { 0 };
6769
struct W w3 = { { 0 }, 0 };
6870
}
71+
void z() {
72+
// Note, we explicitly do not diagnose default initialization of unions with
73+
// a const member. Those can be reasonable, the only problematic case is if
74+
// the only member of the union is const, but that's a very odd situation to
75+
// begin with so we accept it as a false negative.
76+
union Z1 z1;
77+
union Z2 z2;
78+
}
6979

7080
// Test a tentative definition which does eventually get an initializer.
7181
extern const int i;
@@ -77,6 +87,8 @@ const int k; // zero-init-var-warning {{default initialization of an obje
7787
cxx-error {{default initialization of an object of const type 'const int'}}
7888
const struct S s; // zero-init-var-warning {{default initialization of an object of type 'const struct S' is incompatible with C++}} \
7989
cxx-error {{call to implicitly-deleted default constructor of 'const struct S'}}
90+
const union Z1 z3; // zero-init-var-warning {{default initialization of an object of type 'const union Z1' is incompatible with C++}} \
91+
cxx-error {{default initialization of an object of const type 'const union Z1' without a user-provided default constructor}}
8092

8193
void func() {
8294
const int a; // unsafe-var-warning {{default initialization of an object of type 'const int' leaves the object uninitialized}} \

0 commit comments

Comments
 (0)