[clang] [C] Modify -Wdefault-const-init (PR #137961)
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 30 07:02:52 PDT 2025
https://github.com/AaronBallman updated https://github.com/llvm/llvm-project/pull/137961
>From d331697715977eca37197f25bac31b4724ffefee Mon Sep 17 00:00:00 2001
From: Aaron Ballman <aaron at aaronballman.com>
Date: Wed, 30 Apr 2025 08:57:48 -0400
Subject: [PATCH 1/2] [C] Modify -Wdefault-const-init
Post-commit review feedback on
https://github.com/llvm/llvm-project/pull/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
---
clang/docs/ReleaseNotes.rst | 16 +++++----
clang/include/clang/Basic/DiagnosticGroups.td | 12 +++++--
.../clang/Basic/DiagnosticSemaKinds.td | 18 ++++++----
clang/lib/Sema/Sema.cpp | 2 +-
clang/lib/Sema/SemaDecl.cpp | 2 +-
clang/lib/Sema/SemaInit.cpp | 6 ++--
clang/test/Sema/warn-default-const-init.c | 33 ++++++++-----------
7 files changed, 51 insertions(+), 38 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index bc68bb8b70b3d..4fb606afc0f14 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -141,12 +141,16 @@ C Language Changes
function type in Microsoft compatibility mode. #GH124869
- Clang now allows ``restrict`` qualifier for array types with pointer elements (#GH92847).
- Clang now diagnoses ``const``-qualified object definitions without an
- initializer. If the object is zero-initialized, it will be diagnosed under
- the new warning ``-Wdefault-const-init`` (which is grouped under
- ``-Wc++-compat`` because this construct is not compatible with C++). If the
- object is left uninitialized, it will be diagnosed unsed the new warning
- ``-Wdefault-const-init-unsafe`` (which is grouped under
- ``-Wdefault-const-init``). #GH19297
+ initializer. If the object is a variable or field which is zero-initialized,
+ it will be diagnosed under the new warning ``-Wdefault-const-init-var`` or
+ ``-Wdefault-const-init-field``, respectively. Similarly, if the variable or
+ field is not zero-initialized, it will be diagnosed under the new diagnostic
+ ``-Wdefault-const-init-var-unsafe`` or ``-Wdefault-const-init-field-unsafe``,
+ respectively. The unsafe diagnostic variants are grouped under a new
+ diagnostic ``-Wdefault-const-init-unsafe``, which itself is grouped under the
+ new diagnostic ``-Wdefault-const-init``. Finally, ``-Wdefault-const-init`` is
+ grouped under ``-Wc++-compat`` because these constructs are not compatible
+ with C++. #GH19297
- Added ``-Wimplicit-void-ptr-cast``, grouped under ``-Wc++-compat``, which
diagnoses implicit conversion from ``void *`` to another pointer type as
being incompatible with C++. (#GH17792)
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index fc1ce197ef134..3835cd7251488 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -157,8 +157,16 @@ def C99Compat : DiagGroup<"c99-compat">;
def C23Compat : DiagGroup<"c23-compat">;
def : DiagGroup<"c2x-compat", [C23Compat]>;
def HiddenCppDecl : DiagGroup<"c++-hidden-decl">;
-def DefaultConstInitUnsafe : DiagGroup<"default-const-init-unsafe">;
-def DefaultConstInit : DiagGroup<"default-const-init", [DefaultConstInitUnsafe]>;
+def DefaultConstInitFieldUnsafe : DiagGroup<"default-const-init-field-unsafe">;
+def DefaultConstInitVarUnsafe : DiagGroup<"default-const-init-var-unsafe">;
+def DefaultConstInitUnsafe : DiagGroup<"default-const-init-unsafe",
+ [DefaultConstInitFieldUnsafe,
+ DefaultConstInitVarUnsafe]>;
+def DefaultConstInitField : DiagGroup<"default-const-init-field">;
+def DefaultConstInitVar : DiagGroup<"default-const-init-var">;
+def DefaultConstInit : DiagGroup<"default-const-init",
+ [DefaultConstInitField, DefaultConstInitVar,
+ DefaultConstInitUnsafe]>;
def ImplicitVoidPtrCast : DiagGroup<"implicit-void-ptr-cast">;
def ImplicitIntToEnumCast : DiagGroup<"implicit-int-enum-cast",
[ImplicitEnumEnumCast]>;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index ad5bf26be2590..90a7cac9df29e 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8206,14 +8206,20 @@ def err_address_space_qualified_delete : Error<
def note_default_init_const_member : Note<
"member %0 declared 'const' here">;
+def warn_default_init_const_field : Warning<
+ "default initialization of an object of type %0 with const member is "
+ "incompatible with C++">, InGroup<DefaultConstInitField>, DefaultIgnore;
def warn_default_init_const : Warning<
- "default initialization of an object of type %0%select{| with const member}1 "
- "is incompatible with C++">,
- InGroup<DefaultConstInit>, DefaultIgnore;
+ "default initialization of an object of type %0 is incompatible with C++">,
+ InGroup<DefaultConstInitVar>, DefaultIgnore;
+def warn_default_init_const_field_unsafe : Warning<
+ "default initialization of an object of type %0 with const member leaves the "
+ "object uninitialized and is incompatible with C++">,
+ InGroup<DefaultConstInitFieldUnsafe>;
def warn_default_init_const_unsafe : Warning<
- "default initialization of an object of type %0%select{| with const member}1 "
- "leaves the object uninitialized and is incompatible with C++">,
- InGroup<DefaultConstInitUnsafe>;
+ "default initialization of an object of type %0 leaves the object "
+ "uninitialized and is incompatible with C++">,
+ InGroup<DefaultConstInitVarUnsafe>;
def err_default_init_const : Error<
"default initialization of an object of const type %0"
"%select{| without a user-provided default constructor}1">;
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 4edcd3f945f6c..39e370a03afd0 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1457,7 +1457,7 @@ void Sema::ActOnEndOfTranslationUnit() {
if (VD->getStorageDuration() == SD_Static ||
VD->getStorageDuration() == SD_Thread)
DiagID = diag::warn_default_init_const;
- Diag(VD->getLocation(), DiagID) << Type << /*not a field*/ 0;
+ Diag(VD->getLocation(), DiagID) << Type;
}
// Notify the consumer that we've completed a tentative definition.
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index dfc718eedc1d9..ecc9909682522 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -14348,7 +14348,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
if (Var->getStorageDuration() == SD_Static ||
Var->getStorageDuration() == SD_Thread)
DiagID = diag::warn_default_init_const;
- Diag(Var->getLocation(), DiagID) << Type << /*not a field*/ 0;
+ Diag(Var->getLocation(), DiagID) << Type;
}
// Check for jumps past the implicit initializer. C++0x
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index a85eca4d4ac3c..9bf67ce31446e 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -6590,12 +6590,12 @@ void InitializationSequence::InitializeFrom(Sema &S,
// initializer present.
if (!Initializer) {
if (const FieldDecl *FD = getConstField(Rec)) {
- unsigned DiagID = diag::warn_default_init_const_unsafe;
+ unsigned DiagID = diag::warn_default_init_const_field_unsafe;
if (Var->getStorageDuration() == SD_Static ||
Var->getStorageDuration() == SD_Thread)
- DiagID = diag::warn_default_init_const;
+ DiagID = diag::warn_default_init_const_field;
- S.Diag(Var->getLocation(), DiagID) << Var->getType() << /*member*/ 1;
+ S.Diag(Var->getLocation(), DiagID) << Var->getType();
S.Diag(FD->getLocation(), diag::note_default_init_const_member) << FD;
}
}
diff --git a/clang/test/Sema/warn-default-const-init.c b/clang/test/Sema/warn-default-const-init.c
index b8da41b333f3d..d1e60e5db28c7 100644
--- a/clang/test/Sema/warn-default-const-init.c
+++ b/clang/test/Sema/warn-default-const-init.c
@@ -1,28 +1,23 @@
-// RUN: %clang_cc1 -fsyntax-only -verify=c,unsafe -Wdefault-const-init %s
-// RUN: %clang_cc1 -fsyntax-only -verify=c,unsafe -Wc++-compat %s
-// RUN: %clang_cc1 -fsyntax-only -verify=unsafe %s
-// RUN: %clang_cc1 -fsyntax-only -verify=c -Wdefault-const-init -Wno-default-const-init-unsafe %s
-// RUN: %clang_cc1 -fsyntax-only -verify=good -Wno-default-const-init-unsafe %s
-// RUN: %clang_cc1 -fsyntax-only -verify=cxx -x c++ %s
-// good-no-diagnostics
+
+// RUN: %clang_cc1 -fsyntax-only -verify=unsafe-var,unsafe-field -Wdefault-const-init-unsafe %s
struct A { int i; };
-struct S{ const int i; }; // unsafe-note 2 {{member 'i' declared 'const' here}} \
+struct S{ const int i; }; // unsafe-field-note 2 {{member 'i' declared 'const' here}} \
cxx-note 3 {{default constructor of 'S' is implicitly deleted because field 'i' of const-qualified type 'const int' would not be initialized}}
struct T { struct S s; }; // cxx-note {{default constructor of 'T' is implicitly deleted because field 's' has a deleted default constructor}}
struct U { struct S s; const int j; };
-struct V { int i; const struct A a; }; // unsafe-note {{member 'a' declared 'const' here}} \
+struct V { int i; const struct A a; }; // unsafe-field-note {{member 'a' declared 'const' here}} \
cxx-note {{default constructor of 'V' is implicitly deleted because field 'a' of const-qualified type 'const struct A' would not be initialized}}
-struct W { struct A a; const int j; }; // unsafe-note {{member 'j' declared 'const' here}} \
+struct W { struct A a; const int j; }; // unsafe-field-note {{member 'j' declared 'const' here}} \
cxx-note {{default constructor of 'W' is implicitly deleted because field 'j' of const-qualified type 'const int' would not be initialized}}
void f() {
- 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++}} \
+ 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++}} \
cxx-error {{call to implicitly-deleted default constructor of 'struct S'}}
struct S s2 = { 0 };
}
void g() {
- 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++}} \
+ 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++}} \
cxx-error {{call to implicitly-deleted default constructor of 'struct T'}}
struct T t2 = { { 0 } };
}
@@ -31,13 +26,13 @@ void h() {
struct U u2 = { { 0 }, 0 };
}
void x() {
- 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++}} \
+ 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++}} \
cxx-error {{call to implicitly-deleted default constructor of 'struct V'}}
struct V v2 = { 0 };
struct V v3 = { 0, { 0 } };
}
void y() {
- 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++}} \
+ 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++}} \
cxx-error {{call to implicitly-deleted default constructor of 'struct W'}}
struct W w2 = { 0 };
struct W w3 = { { 0 }, 0 };
@@ -47,17 +42,17 @@ void y() {
extern const int i;
const int i = 12;
-static const int j; // c-warning {{default initialization of an object of type 'const int' is incompatible with C++}} \
+static const int j; // zero-init-var-warning {{default initialization of an object of type 'const int' is incompatible with C++}} \
cxx-error {{default initialization of an object of const type 'const int'}}
-const int k; // c-warning {{default initialization of an object of type 'const int' is incompatible with C++}} \
+const int k; // zero-init-var-warning {{default initialization of an object of type 'const int' is incompatible with C++}} \
cxx-error {{default initialization of an object of const type 'const int'}}
-const struct S s; // c-warning {{default initialization of an object of type 'const struct S' is incompatible with C++}} \
+const struct S s; // zero-init-field-warning {{default initialization of an object of type 'const struct S' is incompatible with C++}} \
cxx-error {{call to implicitly-deleted default constructor of 'const struct S'}}
void func() {
- const int a; // unsafe-warning {{default initialization of an object of type 'const int' leaves the object uninitialized and is incompatible with C++}} \
+ const int a; // unsafe-var-warning {{default initialization of an object of type 'const int' leaves the object uninitialized and is incompatible with C++}} \
cxx-error {{default initialization of an object of const type 'const int'}}
- static const int b; // c-warning {{default initialization of an object of type 'const int' is incompatible with C++}} \
+ static const int b; // zero-init-var-warning {{default initialization of an object of type 'const int' is incompatible with C++}} \
cxx-error {{default initialization of an object of const type 'const int'}}
}
>From a8ffca1414e86934724cd0be9ed5a8ed140a7a84 Mon Sep 17 00:00:00 2001
From: Aaron Ballman <aaron at aaronballman.com>
Date: Wed, 30 Apr 2025 10:02:44 -0400
Subject: [PATCH 2/2] Update clang/test/Sema/warn-default-const-init.c
Co-authored-by: Mariya Podchishchaeva <mariya.podchishchaeva at intel.com>
---
clang/test/Sema/warn-default-const-init.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang/test/Sema/warn-default-const-init.c b/clang/test/Sema/warn-default-const-init.c
index d1e60e5db28c7..b6c593e578bd5 100644
--- a/clang/test/Sema/warn-default-const-init.c
+++ b/clang/test/Sema/warn-default-const-init.c
@@ -1,4 +1,3 @@
-
// RUN: %clang_cc1 -fsyntax-only -verify=unsafe-var,unsafe-field -Wdefault-const-init-unsafe %s
struct A { int i; };
More information about the cfe-commits
mailing list