Skip to content

[C] Modify -Wdefault-const-init #137961

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
12 changes: 10 additions & 2 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -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]>;
Expand Down
18 changes: 12 additions & 6 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/Sema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
32 changes: 13 additions & 19 deletions clang/test/Sema/warn-default-const-init.c
Original file line number Diff line number Diff line change
@@ -1,28 +1,22 @@
// 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 } };
}
Expand All @@ -31,13 +25,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 };
Expand All @@ -47,17 +41,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'}}
}