Skip to content

Commit f8e1760

Browse files
committed
Split the diagnostic into two groups
The unsafe variant is on by default, the other one is not.
1 parent c3aef49 commit f8e1760

File tree

7 files changed

+47
-30
lines changed

7 files changed

+47
-30
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,12 @@ 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, under the new warning ``-Wdefault-const-init`` (which is grouped
145-
under ``-Wc++-compat``, as this construct is not compatible with C++). #GH19297
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
146150

147151
C2y Feature Support
148152
^^^^^^^^^^^^^^^^^^^

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,8 @@ def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">;
154154
def C99Compat : DiagGroup<"c99-compat">;
155155
def C23Compat : DiagGroup<"c23-compat">;
156156
def : DiagGroup<"c2x-compat", [C23Compat]>;
157-
def DefaultConstInit : DiagGroup<"default-const-init">;
157+
def DefaultConstInitUnsafe : DiagGroup<"default-const-init-unsafe">;
158+
def DefaultConstInit : DiagGroup<"default-const-init", [DefaultConstInitUnsafe]>;
158159

159160
def CXXCompat: DiagGroup<"c++-compat", [DefaultConstInit]>;
160161
def ExternCCompat : DiagGroup<"extern-c-compat">;

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8200,9 +8200,13 @@ def err_address_space_qualified_delete : Error<
82008200
def note_default_init_const_member : Note<
82018201
"member %0 declared 'const' here">;
82028202
def warn_default_init_const : Warning<
8203-
"default initialization of an object of type %0%select{| with const member}1"
8204-
"%select{| leaves the object uninitialized and}2 is incompatible with C++">,
8205-
InGroup<DefaultConstInit>;
8203+
"default initialization of an object of type %0%select{| with const member}1 "
8204+
"is incompatible with C++">,
8205+
InGroup<DefaultConstInit>, DefaultIgnore;
8206+
def warn_default_init_const_unsafe : Warning<
8207+
"default initialization of an object of type %0%select{| with const member}1 "
8208+
"leaves the object uninitialized and is incompatible with C++">,
8209+
InGroup<DefaultConstInitUnsafe>;
82068210
def err_default_init_const : Error<
82078211
"default initialization of an object of const type %0"
82088212
"%select{| without a user-provided default constructor}1">;

clang/lib/Sema/Sema.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,11 +1452,14 @@ void Sema::ActOnEndOfTranslationUnit() {
14521452
// is left uninitialized unless it has static or thread storage duration.
14531453
QualType Type = VD->getType();
14541454
if (!VD->isInvalidDecl() && !getLangOpts().CPlusPlus &&
1455-
Type.isConstQualified() && !VD->getAnyInitializer())
1456-
Diag(VD->getLocation(), diag::warn_default_init_const)
1457-
<< Type << /*not a field*/0
1458-
<< (VD->getStorageDuration() != SD_Static &&
1459-
VD->getStorageDuration() != SD_Thread);
1455+
Type.isConstQualified() && !VD->getAnyInitializer()) {
1456+
unsigned DiagID = diag::warn_default_init_const_unsafe;
1457+
if (VD->getStorageDuration() == SD_Static ||
1458+
VD->getStorageDuration() == SD_Thread)
1459+
DiagID = diag::warn_default_init_const;
1460+
Diag(VD->getLocation(), DiagID) << Type << /*not a field*/ 0;
1461+
}
1462+
14601463

14611464
// Notify the consumer that we've completed a tentative definition.
14621465
if (!VD->isInvalidDecl())

clang/lib/Sema/SemaDecl.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14335,11 +14335,13 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
1433514335

1433614336
// In C, if the definition is const-qualified and has no initializer, it
1433714337
// is left uninitialized unless it has static or thread storage duration.
14338-
if (!getLangOpts().CPlusPlus && Type.isConstQualified())
14339-
Diag(Var->getLocation(), diag::warn_default_init_const)
14340-
<< Type << /*not a field*/0
14341-
<< (Var->getStorageDuration() != SD_Static &&
14342-
Var->getStorageDuration() != SD_Thread);
14338+
if (!getLangOpts().CPlusPlus && Type.isConstQualified()) {
14339+
unsigned DiagID = diag::warn_default_init_const_unsafe;
14340+
if (Var->getStorageDuration() == SD_Static ||
14341+
Var->getStorageDuration() == SD_Thread)
14342+
DiagID = diag::warn_default_init_const;
14343+
Diag(Var->getLocation(), DiagID) << Type << /*not a field*/ 0;
14344+
}
1434314345

1434414346
// Check for jumps past the implicit initializer. C++0x
1434514347
// clarifies that this applies to a "variable with automatic

clang/lib/Sema/SemaInit.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6588,10 +6588,12 @@ void InitializationSequence::InitializeFrom(Sema &S,
65886588
// initializer present.
65896589
if (!Initializer) {
65906590
if (const FieldDecl *FD = GetConstField(Rec)) {
6591-
S.Diag(Var->getLocation(), diag::warn_default_init_const)
6592-
<< Var->getType() << /*member*/ 1
6593-
<< (Var->getStorageDuration() != SD_Static &&
6594-
Var->getStorageDuration() != SD_Thread);
6591+
unsigned DiagID = diag::warn_default_init_const_unsafe;
6592+
if (Var->getStorageDuration() == SD_Static ||
6593+
Var->getStorageDuration() == SD_Thread)
6594+
DiagID = diag::warn_default_init_const;
6595+
6596+
S.Diag(Var->getLocation(), DiagID) << Var->getType() << /*member*/ 1;
65956597
S.Diag(FD->getLocation(), diag::note_default_init_const_member) << FD;
65966598
}
65976599
}

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

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
1-
// RUN: %clang_cc1 -fsyntax-only -verify=c -Wdefault-const-init %s
2-
// RUN: %clang_cc1 -fsyntax-only -verify=c -Wc++-compat %s
3-
// RUN: %clang_cc1 -fsyntax-only -verify=c %s
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
46
// RUN: %clang_cc1 -fsyntax-only -verify=cxx -x c++ %s
5-
// RUN: %clang_cc1 -fsyntax-only -verify=good -Wc++-compat -Wno-default-const-init %s
67
// good-no-diagnostics
78

89
struct A { int i; };
9-
struct S{ const int i; }; // c-note 2 {{member 'i' declared 'const' here}} \
10+
struct S{ const int i; }; // unsafe-note 2 {{member 'i' declared 'const' here}} \
1011
cxx-note 3 {{default constructor of 'S' is implicitly deleted because field 'i' of const-qualified type 'const int' would not be initialized}}
1112
struct T { struct S s; }; // cxx-note {{default constructor of 'T' is implicitly deleted because field 's' has a deleted default constructor}}
1213
struct U { struct S s; const int j; };
13-
struct V { int i; const struct A a; }; // c-note {{member 'a' declared 'const' here}} \
14+
struct V { int i; const struct A a; }; // unsafe-note {{member 'a' declared 'const' here}} \
1415
cxx-note {{default constructor of 'V' is implicitly deleted because field 'a' of const-qualified type 'const struct A' would not be initialized}}
1516

1617
void f() {
17-
struct S s1; // c-warning {{default initialization of an object of type 'struct S' with const member leaves the object uninitialized and is incompatible with C++}} \
18+
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++}} \
1819
cxx-error {{call to implicitly-deleted default constructor of 'struct S'}}
1920
struct S s2 = { 0 };
2021
}
2122
void g() {
22-
struct T t1; // c-warning {{default initialization of an object of type 'struct T' with const member leaves the object uninitialized and is incompatible with C++}} \
23+
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++}} \
2324
cxx-error {{call to implicitly-deleted default constructor of 'struct T'}}
2425
struct T t2 = { { 0 } };
2526
}
@@ -28,7 +29,7 @@ void h() {
2829
struct U u2 = { { 0 }, 0 };
2930
}
3031
void x() {
31-
struct V v1; // c-warning {{default initialization of an object of type 'struct V' with const member leaves the object uninitialized and is incompatible with C++}} \
32+
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++}} \
3233
cxx-error {{call to implicitly-deleted default constructor of 'struct V'}}
3334
struct V v2 = { 0 };
3435
struct V v3 = { 0, { 0 } };
@@ -46,7 +47,7 @@ const struct S s; // c-warning {{default initialization of an object of type '
4647
cxx-error {{call to implicitly-deleted default constructor of 'const struct S'}}
4748

4849
void func() {
49-
const int a; // c-warning {{default initialization of an object of type 'const int' leaves the object uninitialized and is incompatible with C++}} \
50+
const int a; // unsafe-warning {{default initialization of an object of type 'const int' leaves the object uninitialized and is incompatible with C++}} \
5051
cxx-error {{default initialization of an object of const type 'const int'}}
5152
static const int b; // c-warning {{default initialization of an object of type 'const int' is incompatible with C++}} \
5253
cxx-error {{default initialization of an object of const type 'const int'}}

0 commit comments

Comments
 (0)