Fznamznon created this revision. Herald added a project: All. Fznamznon requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
Prior to this change clang didn't emit missing-field-initializers warning for designated initializers. The comments say that it is done to match gcc behavior. However, gcc behaves so only for C. For C++ warnings are emitted. Fixes https://github.com/llvm/llvm-project/issues/56628 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D157879 Files: clang/lib/Sema/SemaInit.cpp clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp
Index: clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp =================================================================== --- clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp +++ clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp @@ -4,6 +4,7 @@ // RUN: %clang_cc1 -std=c++20 %s -verify=cxx20,expected,reorder -Wno-c99-designator -Werror=reorder-init-list -Wno-initializer-overrides // RUN: %clang_cc1 -std=c++20 %s -verify=cxx20,expected,override -Wno-c99-designator -Wno-reorder-init-list -Werror=initializer-overrides // RUN: %clang_cc1 -std=c++20 %s -verify=cxx20,expected -Wno-c99-designator -Wno-reorder-init-list -Wno-initializer-overrides +// RUN: %clang_cc1 -std=c++20 %s -verify=cxx20,expected,wmissing -Wmissing-field-initializers -Wno-c99-designator -Wno-reorder-init-list -Wno-initializer-overrides namespace class_with_ctor { @@ -49,15 +50,18 @@ A a4 = { .x = 1, // override-note {{previous}} .x = 1 // override-error {{overrides prior initialization}} -}; +}; // wmissing-warning {{missing field 'y' initializer}} A a5 = { .y = 1, // override-note {{previous}} .y = 1 // override-error {{overrides prior initialization}} -}; +}; // wmissing-warning {{missing field 'x' initializer}} B b2 = {.a = 1}; // pedantic-error {{brace elision for designated initializer is a C99 extension}} + // wmissing-warning@-1 {{missing field 'y' initializer}} B b3 = {.a = 1, 2}; // pedantic-error {{mixture of designated and non-designated}} pedantic-note {{first non-designated}} pedantic-error {{brace elision}} B b4 = {.a = 1, 2, 3}; // pedantic-error {{mixture of designated and non-designated}} pedantic-note {{first non-designated}} pedantic-error {{brace elision}} expected-error {{excess elements}} B b5 = {.a = nullptr}; // expected-error {{cannot initialize}} + // wmissing-warning@-1 {{missing field 'y' initializer}} + // wmissing-warning@-2 {{missing field 'a' initializer}} struct C { int :0, x, :0, y, :0; }; C c = { .x = 1, // override-note {{previous}} @@ -66,7 +70,14 @@ .y = 1, // override-error {{overrides prior initialization}} // reorder-note {{previous initialization for field 'y' is here}} .x = 1, // reorder-error {{declaration order}} override-error {{overrides prior initialization}} override-note {{previous}} .x = 1, // override-error {{overrides prior initialization}} -}; +}; //wmissing-warning {{missing field 'x' initializer}} + +struct Foo { int a, b; }; + +struct Foo foo0 = { 1 }; // wmissing-warning {{missing field 'b' initializer}} +struct Foo foo1 = { .a = 1 }; // wmissing-warning {{missing field 'b' initializer}} +struct Foo foo2 = { .b = 1 }; // wmissing-warning {{missing field 'a' initializer}} + } namespace base_class { @@ -215,5 +226,5 @@ .c = 1, // reorder-error {{field 'd' will be initialized after field 'c'}} // reorder-note {{previous initialization for field 'c' is here}} .b = 1, // reorder-error {{field 'c' will be initialized after field 'b'}} // reorder-note {{previous initialization for field 'b' is here}} .a = 1, // reorder-error {{field 'b' will be initialized after field 'a'}} -}; +}; // wmissing-warning {{missing field 'a' initializer}} } Index: clang/lib/Sema/SemaInit.cpp =================================================================== --- clang/lib/Sema/SemaInit.cpp +++ clang/lib/Sema/SemaInit.cpp @@ -2252,6 +2252,8 @@ !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()); bool HasDesignatedInit = false; + llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields; + while (Index < IList->getNumInits()) { Expr *Init = IList->getInit(Index); SourceLocation InitLoc = Init->getBeginLoc(); @@ -2277,6 +2279,7 @@ RecordDecl::field_iterator F = RD->field_begin(); while (std::next(F) != Field) ++F; + InitializedFields.insert(*F); QualType ET = SemaRef.Context.getBaseElementType(F->getType()); if (checkDestructorReference(ET, InitLoc, SemaRef)) { hadError = true; @@ -2288,7 +2291,8 @@ // Disable check for missing fields when designators are used. // This matches gcc behaviour. - CheckForMissingFields = false; + if (!SemaRef.getLangOpts().CPlusPlus) + CheckForMissingFields = false; continue; } @@ -2367,6 +2371,7 @@ CheckSubElementType(MemberEntity, IList, Field->getType(), Index, StructuredList, StructuredIndex); InitializedSomething = true; + InitializedFields.insert(*Field); if (RD->isUnion() && StructuredList) { // Initialize the first field within the union. @@ -2378,15 +2383,20 @@ // Emit warnings for missing struct field initializers. if (!VerifyOnly && InitializedSomething && CheckForMissingFields && - Field != FieldEnd && !Field->getType()->isIncompleteArrayType() && !RD->isUnion()) { // 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(); + for (RecordDecl::field_iterator it = HasDesignatedInit ? RD->field_begin() + : Field, + end = RD->field_end(); it != end; ++it) { + if (HasDesignatedInit && InitializedFields.count(*it)) + continue; + if (!it->isUnnamedBitfield() && !it->hasInClassInitializer()) { SemaRef.Diag(IList->getSourceRange().getEnd(), - diag::warn_missing_field_initializers) << *it; + diag::warn_missing_field_initializers) + << *it; break; } }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits