Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -199,7 +199,6 @@ bool b = nullptr; // Was incorrectly rejected by Clang, is now accepted. - Non-comprehensive list of changes in this release ------------------------------------------------- - Clang now saves the address of ABI-indirect function parameters on the stack, @@ -339,6 +338,8 @@ can be controlled using ``-fcaret-diagnostics-max-lines=``. - Clang no longer emits ``-Wunused-variable`` warnings for variables declared with ``__attribute__((cleanup(...)))`` to match GCC's behavior. +- Add ``-Wincomplete-array-initializer-list`` warning to detect missing + elements in initializer lists assigned to array types. Bug Fixes in This Version ------------------------- Index: clang/include/clang/Basic/DiagnosticGroups.td =================================================================== --- clang/include/clang/Basic/DiagnosticGroups.td +++ clang/include/clang/Basic/DiagnosticGroups.td @@ -734,6 +734,7 @@ def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes, UninitializedStaticSelfInit, UninitializedConstReference]>; +def IncompleteArrayInitializerList : DiagGroup<"incomplete-array-initializer-list">; def IgnoredPragmaIntrinsic : DiagGroup<"ignored-pragma-intrinsic">; // #pragma optimize is often used to avoid to work around MSVC codegen bugs or // to disable inlining. It's not completely clear what alternative to suggest Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2223,6 +2223,9 @@ "reference %0 is not yet bound to a value when used within its own" " initialization">, InGroup; +def warn_incomplete_array_initializer_list : Warning< + "incomplete array initializer list">, + InGroup, DefaultIgnore; def warn_uninit_var : Warning< "variable %0 is uninitialized when %select{used here|captured by block}1">, InGroup, DefaultIgnore; Index: clang/lib/Sema/SemaInit.cpp =================================================================== --- clang/lib/Sema/SemaInit.cpp +++ clang/lib/Sema/SemaInit.cpp @@ -986,6 +986,21 @@ if (RequiresSecondPass && !hadError) FillInEmptyInitializations(Entity, FullyStructuredList, RequiresSecondPass, nullptr, 0); + + if (T->isArrayType() && VerifyOnly) { + const auto *CAType = dyn_cast(T); + if (CAType && FullyStructuredList->getNumInits() < + CAType->getSize().getZExtValue()) { + S.Diag(IL->getBeginLoc(), diag::warn_incomplete_array_initializer_list) + << IL->getSourceRange(); + } else { + auto inits = FullyStructuredList->inits(); + if (llvm::find(inits, nullptr) != inits.end()) + S.Diag(IL->getBeginLoc(), + diag::warn_incomplete_array_initializer_list) + << IL->getSourceRange(); + } + } } if (hadError && FullyStructuredList) FullyStructuredList->markError(); Index: clang/test/Sema/warn-incomplete-initializer-list.c =================================================================== --- /dev/null +++ clang/test/Sema/warn-incomplete-initializer-list.c @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -fsyntax-only -Wincomplete-initializer-list -verify -std=c99 %s + +// missing array initializer in between +enum { + FOO1_A, + FOO1_MISSING, + FOO1_B, + FOO1_COUNT +}; +const char *foo1[] = { // expected-warning{{incomplete initializer list}} + [FOO1_A] = "a", + [FOO1_B] = "b", +}; + +// missing array initializer at end +enum { + FOO2_A, + FOO2_B, + FOO2_MISSING, + FOO2_COUNT +}; +const char *foo2[FOO2_COUNT] = { //expected-warning{{incomplete initializer list}} + [FOO2_A] = "a", + [FOO2_B] = "b", +}; + +// complete array initializer +int foo3[4] = { 1, 1, 1, 1 }; + +// missing struct initializer in between +struct { + int a, b, c, d; +} bar1 = { + .a = 1, + .b = 1, + .d = 1 +}; + +// missing struct initializer at end +struct { + int a, b, c, d; +} bar2 = { + .a = 1, + .b = 1, + .c = 1 +}; + +// complete struct initializer +struct { + int a, b, c, d; +} bar3 = { 1, 1, 1, 1 };