aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-03-11 19:32:38 +0000
committerJohn McCall <rjmccall@apple.com>2010-03-11 19:32:38 +0000
commit80639debfb2d90b2f1ffdbcd9a391f744cb0a393 (patch)
tree9de4aa664572ef5d6c92670ba0e55329a7f84249
parentd295d78645503711d67ce54be2faddf7abdbc4e9 (diff)
Implement -Wmissing-field-initializers. Patch by mikem!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98275 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticGroups.td3
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--lib/Sema/SemaInit.cpp20
-rw-r--r--test/Sema/missing-field-initializers.c48
4 files changed, 73 insertions, 1 deletions
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 17bad64e9c..e5793fa58b 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -59,7 +59,7 @@ def : DiagGroup<"nested-externs">;
def : DiagGroup<"newline-eof">;
def LongLong : DiagGroup<"long-long">;
def MismatchedTags : DiagGroup<"mismatched-tags">;
-def : DiagGroup<"missing-field-initializers">;
+def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
def NonNull : DiagGroup<"nonnull">;
def : DiagGroup<"nonportable-cfstrings">;
def : DiagGroup<"non-virtual-dtor">;
@@ -147,6 +147,7 @@ def Format2 : DiagGroup<"format=2",
[FormatNonLiteral, FormatSecurity, FormatY2K]>;
def Extra : DiagGroup<"extra", [
+ MissingFieldInitializers,
SemiBeforeMethodBody,
SignCompare,
UnusedParameter
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 13ac9ece54..1e1c0aa317 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1562,6 +1562,9 @@ def warn_excess_initializers_in_char_array_initializer : ExtWarn<
"excess elements in char array initializer">;
def warn_initializer_string_for_char_array_too_long : ExtWarn<
"initializer-string for char array is too long">;
+def warn_missing_field_initializers : Warning<
+ "missing field '%0' initializer">,
+ InGroup<MissingFieldInitializers>, DefaultIgnore;
def warn_braces_around_scalar_init : Warning<
"braces around scalar initializer">;
def err_many_braces_around_scalar_init : Error<
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 3540cd02e6..51d2f15376 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -1051,6 +1051,7 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
RecordDecl::field_iterator FieldEnd = RD->field_end();
bool InitializedSomething = false;
+ bool CheckForMissingFields = true;
while (Index < IList->getNumInits()) {
Expr *Init = IList->getInit(Index);
@@ -1070,6 +1071,10 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
hadError = true;
InitializedSomething = true;
+
+ // Disable check for missing fields when designators are used.
+ // This matches gcc behaviour.
+ CheckForMissingFields = false;
continue;
}
@@ -1106,6 +1111,21 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
++Field;
}
+ // Emit warnings for missing struct field initializers.
+ if (CheckForMissingFields && Field != FieldEnd &&
+ !Field->getType()->isIncompleteArrayType() && !DeclType->isUnionType()) {
+ // It is possible we have one or more unnamed bitfields remaining.
+ // Find first (if any) named field and emit warning.
+ for (RecordDecl::field_iterator it = Field, end = RD->field_end();
+ it != end; ++it) {
+ if (!it->isUnnamedBitfield()) {
+ SemaRef.Diag(IList->getSourceRange().getEnd(),
+ diag::warn_missing_field_initializers) << it->getName();
+ break;
+ }
+ }
+ }
+
if (Field == FieldEnd || !Field->getType()->isIncompleteArrayType() ||
Index >= IList->getNumInits())
return;
diff --git a/test/Sema/missing-field-initializers.c b/test/Sema/missing-field-initializers.c
new file mode 100644
index 0000000000..0ceded07f2
--- /dev/null
+++ b/test/Sema/missing-field-initializers.c
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wmissing-field-initializers %s
+
+struct Foo { int a, b; };
+
+struct Foo foo0 = { 1 }; // expected-warning {{missing field 'b' initializer}}
+struct Foo foo1 = { .a = 1 }; // designator avoids MFI warning
+struct Foo foo2 = { .b = 1 }; // designator avoids MFI warning
+
+struct Foo bar0[] = {
+ { 1,2 },
+ { 1 }, // expected-warning {{missing field 'b' initializer}}
+ { 1,2 }
+};
+
+struct Foo bar1[] = {
+ 1, 2,
+ 1, 2,
+ 1
+}; // expected-warning {{missing field 'b' initializer}}
+
+struct One { int a; int b; };
+struct Two { float c; float d; float e; };
+
+struct Three {
+ union {
+ struct One one;
+ struct Two two;
+ } both;
+};
+
+struct Three t0 = {
+ { .one = { 1, 2 } }
+};
+struct Three t1 = {
+ { .two = { 1.0f, 2.0f, 3.0f } }
+};
+
+struct Three data[] = {
+ { { .one = { 1, 2 } } },
+ { { .one = { 1 } } }, // expected-warning {{missing field 'b' initializer}}
+ { { .two = { 1.0f, 2.0f, 3.0f } } },
+ { { .two = { 1.0f, 2.0f } } } // expected-warning {{missing field 'e' initializer}}
+};
+
+struct { int:5; int a; int:5; int b; int:5 } noNamedImplicit[] = {
+ { 1, 2 },
+ { 1 } // expected-warning {{missing field 'b' initializer}}
+};