Skip to content

Commit d331697

Browse files
committed
[C] Modify -Wdefault-const-init
Post-commit review feedback on llvm#137166 raised a concern from the Linux kernel about wanting to silence the new diagnostic when the uninitialized object is a const member of a structure. These members can be initialized later if the containing object is non-const, such as through a call to memset, for example. This splits the diagnostic groups into: -Wc++-compat -Wdefault-const-init -Wdefault-const-init-field -Wdefault-const-init-var -Wdefault-const-init-unsafe -Wdefault-const-init-field-unsafe -Wdefault-const-init-var-unsafe
1 parent 6e43cdb commit d331697

File tree

7 files changed

+51
-38
lines changed

7 files changed

+51
-38
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,16 @@ C Language Changes
141141
function type in Microsoft compatibility mode. #GH124869
142142
- Clang now allows ``restrict`` qualifier for array types with pointer elements (#GH92847).
143143
- Clang now diagnoses ``const``-qualified object definitions without an
144-
initializer. If the object is zero-initialized, it will be diagnosed under
145-
the new warning ``-Wdefault-const-init`` (which is grouped under
146-
``-Wc++-compat`` because this construct is not compatible with C++). If the
147-
object is left uninitialized, it will be diagnosed unsed the new warning
148-
``-Wdefault-const-init-unsafe`` (which is grouped under
149-
``-Wdefault-const-init``). #GH19297
144+
initializer. If the object is a variable or field which is zero-initialized,
145+
it will be diagnosed under the new warning ``-Wdefault-const-init-var`` or
146+
``-Wdefault-const-init-field``, respectively. Similarly, if the variable or
147+
field is not zero-initialized, it will be diagnosed under the new diagnostic
148+
``-Wdefault-const-init-var-unsafe`` or ``-Wdefault-const-init-field-unsafe``,
149+
respectively. The unsafe diagnostic variants are grouped under a new
150+
diagnostic ``-Wdefault-const-init-unsafe``, which itself is grouped under the
151+
new diagnostic ``-Wdefault-const-init``. Finally, ``-Wdefault-const-init`` is
152+
grouped under ``-Wc++-compat`` because these constructs are not compatible
153+
with C++. #GH19297
150154
- Added ``-Wimplicit-void-ptr-cast``, grouped under ``-Wc++-compat``, which
151155
diagnoses implicit conversion from ``void *`` to another pointer type as
152156
being incompatible with C++. (#GH17792)

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,16 @@ def C99Compat : DiagGroup<"c99-compat">;
157157
def C23Compat : DiagGroup<"c23-compat">;
158158
def : DiagGroup<"c2x-compat", [C23Compat]>;
159159
def HiddenCppDecl : DiagGroup<"c++-hidden-decl">;
160-
def DefaultConstInitUnsafe : DiagGroup<"default-const-init-unsafe">;
161-
def DefaultConstInit : DiagGroup<"default-const-init", [DefaultConstInitUnsafe]>;
160+
def DefaultConstInitFieldUnsafe : DiagGroup<"default-const-init-field-unsafe">;
161+
def DefaultConstInitVarUnsafe : DiagGroup<"default-const-init-var-unsafe">;
162+
def DefaultConstInitUnsafe : DiagGroup<"default-const-init-unsafe",
163+
[DefaultConstInitFieldUnsafe,
164+
DefaultConstInitVarUnsafe]>;
165+
def DefaultConstInitField : DiagGroup<"default-const-init-field">;
166+
def DefaultConstInitVar : DiagGroup<"default-const-init-var">;
167+
def DefaultConstInit : DiagGroup<"default-const-init",
168+
[DefaultConstInitField, DefaultConstInitVar,
169+
DefaultConstInitUnsafe]>;
162170
def ImplicitVoidPtrCast : DiagGroup<"implicit-void-ptr-cast">;
163171
def ImplicitIntToEnumCast : DiagGroup<"implicit-int-enum-cast",
164172
[ImplicitEnumEnumCast]>;

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8206,14 +8206,20 @@ def err_address_space_qualified_delete : Error<
82068206

82078207
def note_default_init_const_member : Note<
82088208
"member %0 declared 'const' here">;
8209+
def warn_default_init_const_field : Warning<
8210+
"default initialization of an object of type %0 with const member is "
8211+
"incompatible with C++">, InGroup<DefaultConstInitField>, DefaultIgnore;
82098212
def warn_default_init_const : Warning<
8210-
"default initialization of an object of type %0%select{| with const member}1 "
8211-
"is incompatible with C++">,
8212-
InGroup<DefaultConstInit>, DefaultIgnore;
8213+
"default initialization of an object of type %0 is incompatible with C++">,
8214+
InGroup<DefaultConstInitVar>, DefaultIgnore;
8215+
def warn_default_init_const_field_unsafe : Warning<
8216+
"default initialization of an object of type %0 with const member leaves the "
8217+
"object uninitialized and is incompatible with C++">,
8218+
InGroup<DefaultConstInitFieldUnsafe>;
82138219
def warn_default_init_const_unsafe : Warning<
8214-
"default initialization of an object of type %0%select{| with const member}1 "
8215-
"leaves the object uninitialized and is incompatible with C++">,
8216-
InGroup<DefaultConstInitUnsafe>;
8220+
"default initialization of an object of type %0 leaves the object "
8221+
"uninitialized and is incompatible with C++">,
8222+
InGroup<DefaultConstInitVarUnsafe>;
82178223
def err_default_init_const : Error<
82188224
"default initialization of an object of const type %0"
82198225
"%select{| without a user-provided default constructor}1">;

clang/lib/Sema/Sema.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1457,7 +1457,7 @@ void Sema::ActOnEndOfTranslationUnit() {
14571457
if (VD->getStorageDuration() == SD_Static ||
14581458
VD->getStorageDuration() == SD_Thread)
14591459
DiagID = diag::warn_default_init_const;
1460-
Diag(VD->getLocation(), DiagID) << Type << /*not a field*/ 0;
1460+
Diag(VD->getLocation(), DiagID) << Type;
14611461
}
14621462

14631463
// Notify the consumer that we've completed a tentative definition.

clang/lib/Sema/SemaDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14348,7 +14348,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
1434814348
if (Var->getStorageDuration() == SD_Static ||
1434914349
Var->getStorageDuration() == SD_Thread)
1435014350
DiagID = diag::warn_default_init_const;
14351-
Diag(Var->getLocation(), DiagID) << Type << /*not a field*/ 0;
14351+
Diag(Var->getLocation(), DiagID) << Type;
1435214352
}
1435314353

1435414354
// Check for jumps past the implicit initializer. C++0x

clang/lib/Sema/SemaInit.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6590,12 +6590,12 @@ void InitializationSequence::InitializeFrom(Sema &S,
65906590
// initializer present.
65916591
if (!Initializer) {
65926592
if (const FieldDecl *FD = getConstField(Rec)) {
6593-
unsigned DiagID = diag::warn_default_init_const_unsafe;
6593+
unsigned DiagID = diag::warn_default_init_const_field_unsafe;
65946594
if (Var->getStorageDuration() == SD_Static ||
65956595
Var->getStorageDuration() == SD_Thread)
6596-
DiagID = diag::warn_default_init_const;
6596+
DiagID = diag::warn_default_init_const_field;
65976597

6598-
S.Diag(Var->getLocation(), DiagID) << Var->getType() << /*member*/ 1;
6598+
S.Diag(Var->getLocation(), DiagID) << Var->getType();
65996599
S.Diag(FD->getLocation(), diag::note_default_init_const_member) << FD;
66006600
}
66016601
}
Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,23 @@
1-
// RUN: %clang_cc1 -fsyntax-only -verify=c,unsafe -Wdefault-const-init %s
2-
// RUN: %clang_cc1 -fsyntax-only -verify=c,unsafe -Wc++-compat %s
3-
// RUN: %clang_cc1 -fsyntax-only -verify=unsafe %s
4-
// RUN: %clang_cc1 -fsyntax-only -verify=c -Wdefault-const-init -Wno-default-const-init-unsafe %s
5-
// RUN: %clang_cc1 -fsyntax-only -verify=good -Wno-default-const-init-unsafe %s
6-
// RUN: %clang_cc1 -fsyntax-only -verify=cxx -x c++ %s
7-
// good-no-diagnostics
1+
2+
// RUN: %clang_cc1 -fsyntax-only -verify=unsafe-var,unsafe-field -Wdefault-const-init-unsafe %s
83

94
struct A { int i; };
10-
struct S{ const int i; }; // unsafe-note 2 {{member 'i' declared 'const' here}} \
5+
struct S{ const int i; }; // unsafe-field-note 2 {{member 'i' declared 'const' here}} \
116
cxx-note 3 {{default constructor of 'S' is implicitly deleted because field 'i' of const-qualified type 'const int' would not be initialized}}
127
struct T { struct S s; }; // cxx-note {{default constructor of 'T' is implicitly deleted because field 's' has a deleted default constructor}}
138
struct U { struct S s; const int j; };
14-
struct V { int i; const struct A a; }; // unsafe-note {{member 'a' declared 'const' here}} \
9+
struct V { int i; const struct A a; }; // unsafe-field-note {{member 'a' declared 'const' here}} \
1510
cxx-note {{default constructor of 'V' is implicitly deleted because field 'a' of const-qualified type 'const struct A' would not be initialized}}
16-
struct W { struct A a; const int j; }; // unsafe-note {{member 'j' declared 'const' here}} \
11+
struct W { struct A a; const int j; }; // unsafe-field-note {{member 'j' declared 'const' here}} \
1712
cxx-note {{default constructor of 'W' is implicitly deleted because field 'j' of const-qualified type 'const int' would not be initialized}}
1813

1914
void f() {
20-
struct S s1; // unsafe-warning {{default initialization of an object of type 'struct S' with const member leaves the object uninitialized and is incompatible with C++}} \
15+
struct S s1; // unsafe-field-warning {{default initialization of an object of type 'struct S' with const member leaves the object uninitialized and is incompatible with C++}} \
2116
cxx-error {{call to implicitly-deleted default constructor of 'struct S'}}
2217
struct S s2 = { 0 };
2318
}
2419
void g() {
25-
struct T t1; // unsafe-warning {{default initialization of an object of type 'struct T' with const member leaves the object uninitialized and is incompatible with C++}} \
20+
struct T t1; // unsafe-field-warning {{default initialization of an object of type 'struct T' with const member leaves the object uninitialized and is incompatible with C++}} \
2621
cxx-error {{call to implicitly-deleted default constructor of 'struct T'}}
2722
struct T t2 = { { 0 } };
2823
}
@@ -31,13 +26,13 @@ void h() {
3126
struct U u2 = { { 0 }, 0 };
3227
}
3328
void x() {
34-
struct V v1; // unsafe-warning {{default initialization of an object of type 'struct V' with const member leaves the object uninitialized and is incompatible with C++}} \
29+
struct V v1; // unsafe-field-warning {{default initialization of an object of type 'struct V' with const member leaves the object uninitialized and is incompatible with C++}} \
3530
cxx-error {{call to implicitly-deleted default constructor of 'struct V'}}
3631
struct V v2 = { 0 };
3732
struct V v3 = { 0, { 0 } };
3833
}
3934
void y() {
40-
struct W w1; // unsafe-warning {{default initialization of an object of type 'struct W' with const member leaves the object uninitialized and is incompatible with C++}} \
35+
struct W w1; // unsafe-field-warning {{default initialization of an object of type 'struct W' with const member leaves the object uninitialized and is incompatible with C++}} \
4136
cxx-error {{call to implicitly-deleted default constructor of 'struct W'}}
4237
struct W w2 = { 0 };
4338
struct W w3 = { { 0 }, 0 };
@@ -47,17 +42,17 @@ void y() {
4742
extern const int i;
4843
const int i = 12;
4944

50-
static const int j; // c-warning {{default initialization of an object of type 'const int' is incompatible with C++}} \
45+
static const int j; // zero-init-var-warning {{default initialization of an object of type 'const int' is incompatible with C++}} \
5146
cxx-error {{default initialization of an object of const type 'const int'}}
52-
const int k; // c-warning {{default initialization of an object of type 'const int' is incompatible with C++}} \
47+
const int k; // zero-init-var-warning {{default initialization of an object of type 'const int' is incompatible with C++}} \
5348
cxx-error {{default initialization of an object of const type 'const int'}}
54-
const struct S s; // c-warning {{default initialization of an object of type 'const struct S' is incompatible with C++}} \
49+
const struct S s; // zero-init-field-warning {{default initialization of an object of type 'const struct S' is incompatible with C++}} \
5550
cxx-error {{call to implicitly-deleted default constructor of 'const struct S'}}
5651

5752
void func() {
58-
const int a; // unsafe-warning {{default initialization of an object of type 'const int' leaves the object uninitialized and is incompatible with C++}} \
53+
const int a; // unsafe-var-warning {{default initialization of an object of type 'const int' leaves the object uninitialized and is incompatible with C++}} \
5954
cxx-error {{default initialization of an object of const type 'const int'}}
60-
static const int b; // c-warning {{default initialization of an object of type 'const int' is incompatible with C++}} \
55+
static const int b; // zero-init-var-warning {{default initialization of an object of type 'const int' is incompatible with C++}} \
6156
cxx-error {{default initialization of an object of const type 'const int'}}
6257
}
6358

0 commit comments

Comments
 (0)