-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[C] Do not diagnose unions with -Wdefault-const-init #140725
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
[C] Do not diagnose unions with -Wdefault-const-init #140725
Conversation
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++.
|
@llvm/pr-subscribers-clang Author: Aaron Ballman (AaronBallman) ChangesA 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++. Full diff: https://github.com/llvm/llvm-project/pull/140725.diff 2 Files Affected:
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 9ee8603ff7811..810cac889b98f 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -6602,8 +6602,10 @@ void InitializationSequence::InitializeFrom(Sema &S,
}
// If the record has any members which are const (recursively checked),
// then we want to diagnose those as being uninitialized if there is no
- // initializer present.
- if (!Initializer) {
+ // initializer present. However, we only do this for structure types, not
+ // union types, because an unitialized field in a union is generally
+ // reasonable, especially in C where unions can be used for type punning.
+ if (!Initializer && !Rec->isUnion()) {
if (const FieldDecl *FD = getConstField(Rec)) {
unsigned DiagID = diag::warn_default_init_const_field_unsafe;
if (Var->getStorageDuration() == SD_Static ||
diff --git a/clang/test/Sema/warn-default-const-init.c b/clang/test/Sema/warn-default-const-init.c
index e788d72899685..76b85abb6ade2 100644
--- a/clang/test/Sema/warn-default-const-init.c
+++ b/clang/test/Sema/warn-default-const-init.c
@@ -35,6 +35,8 @@ struct V { int i; const struct A a; }; // unsafe-field-note {{member 'a' declare
struct W { struct A a; const int j; }; // unsafe-field-note {{member 'j' declared 'const' here}} \
unsafe-field-compat-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}}
+union Z1 { int i; const int j; };
+union Z2 { int i; const struct A a; };
void f() {
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() {
struct W w2 = { 0 };
struct W w3 = { { 0 }, 0 };
}
+void z() {
+ // Note, we explicitly do not diagnose default initialization of unions with
+ // a const member. Those can be reasonable, the only problematic case is if
+ // the only member of the union is const, but that's a very odd situation to
+ // begin with so we accept it as a false negative.
+ union Z1 z1;
+ union Z2 z2;
+}
// Test a tentative definition which does eventually get an initializer.
extern const int i;
@@ -77,6 +87,8 @@ const int k; // zero-init-var-warning {{default initialization of an obje
cxx-error {{default initialization of an object of const type 'const int'}}
const struct S s; // zero-init-var-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'}}
+const union Z1 z3; // zero-init-var-warning {{default initialization of an object of type 'const union Z1' is incompatible with C++}} \
+ cxx-error {{default initialization of an object of const type 'const union Z1' without a user-provided default constructor}}
void func() {
const int a; // unsafe-var-warning {{default initialization of an object of type 'const int' leaves the object uninitialized}} \
|
shafik
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
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++.