@@ -465,8 +465,7 @@ class InitListChecker {
465
465
void FillInEmptyInitForField (unsigned Init, FieldDecl *Field,
466
466
const InitializedEntity &ParentEntity,
467
467
InitListExpr *ILE, bool &RequiresSecondPass,
468
- bool FillWithNoInit = false ,
469
- bool WarnIfMissing = false );
468
+ bool FillWithNoInit = false );
470
469
void FillInEmptyInitializations (const InitializedEntity &Entity,
471
470
InitListExpr *ILE, bool &RequiresSecondPass,
472
471
InitListExpr *OuterILE, unsigned OuterIndex,
@@ -655,16 +654,11 @@ void InitListChecker::FillInEmptyInitForBase(
655
654
}
656
655
}
657
656
658
- static bool hasAnyDesignatedInits (const InitListExpr *IL) {
659
- return llvm::any_of (*IL, [=](const Stmt *Init) {
660
- return isa_and_nonnull<DesignatedInitExpr>(Init);
661
- });
662
- }
663
-
664
- void InitListChecker::FillInEmptyInitForField (
665
- unsigned Init, FieldDecl *Field, const InitializedEntity &ParentEntity,
666
- InitListExpr *ILE, bool &RequiresSecondPass, bool FillWithNoInit,
667
- bool WarnIfMissing) {
657
+ void InitListChecker::FillInEmptyInitForField (unsigned Init, FieldDecl *Field,
658
+ const InitializedEntity &ParentEntity,
659
+ InitListExpr *ILE,
660
+ bool &RequiresSecondPass,
661
+ bool FillWithNoInit) {
668
662
SourceLocation Loc = ILE->getEndLoc ();
669
663
unsigned NumInits = ILE->getNumInits ();
670
664
InitializedEntity MemberEntity
@@ -732,52 +726,15 @@ void InitListChecker::FillInEmptyInitForField(
732
726
733
727
if (hadError || VerifyOnly) {
734
728
// Do nothing
735
- } else {
736
- if (WarnIfMissing) {
737
- auto CheckAnonMember = [&](const FieldDecl *FD,
738
- auto &&CheckAnonMember) -> FieldDecl * {
739
- FieldDecl *Uninitialized = nullptr ;
740
- RecordDecl *RD = FD->getType ()->getAsRecordDecl ();
741
- assert (RD && " Not anonymous member checked?" );
742
- for (auto *F : RD->fields ()) {
743
- FieldDecl *UninitializedFieldInF = nullptr ;
744
- if (F->isAnonymousStructOrUnion ())
745
- UninitializedFieldInF = CheckAnonMember (F, CheckAnonMember);
746
- else if (!F->isUnnamedBitfield () &&
747
- !F->getType ()->isIncompleteArrayType () &&
748
- !F->hasInClassInitializer ())
749
- UninitializedFieldInF = F;
750
-
751
- if (RD->isUnion () && !UninitializedFieldInF)
752
- return nullptr ;
753
- if (!Uninitialized)
754
- Uninitialized = UninitializedFieldInF;
755
- }
756
- return Uninitialized;
757
- };
758
-
759
- FieldDecl *FieldToDiagnose = nullptr ;
760
- if (Field->isAnonymousStructOrUnion ())
761
- FieldToDiagnose = CheckAnonMember (Field, CheckAnonMember);
762
- else if (!Field->isUnnamedBitfield () &&
763
- !Field->getType ()->isIncompleteArrayType ())
764
- FieldToDiagnose = Field;
765
-
766
- if (FieldToDiagnose)
767
- SemaRef.Diag (Loc, diag::warn_missing_field_initializers)
768
- << FieldToDiagnose;
769
- }
770
-
771
- if (Init < NumInits) {
772
- ILE->setInit (Init, MemberInit.getAs <Expr>());
773
- } else if (!isa<ImplicitValueInitExpr>(MemberInit.get ())) {
774
- // Empty initialization requires a constructor call, so
775
- // extend the initializer list to include the constructor
776
- // call and make a note that we'll need to take another pass
777
- // through the initializer list.
778
- ILE->updateInit (SemaRef.Context , Init, MemberInit.getAs <Expr>());
779
- RequiresSecondPass = true ;
780
- }
729
+ } else if (Init < NumInits) {
730
+ ILE->setInit (Init, MemberInit.getAs <Expr>());
731
+ } else if (!isa<ImplicitValueInitExpr>(MemberInit.get ())) {
732
+ // Empty initialization requires a constructor call, so
733
+ // extend the initializer list to include the constructor
734
+ // call and make a note that we'll need to take another pass
735
+ // through the initializer list.
736
+ ILE->updateInit (SemaRef.Context , Init, MemberInit.getAs <Expr>());
737
+ RequiresSecondPass = true ;
781
738
}
782
739
} else if (InitListExpr *InnerILE
783
740
= dyn_cast<InitListExpr>(ILE->getInit (Init))) {
@@ -845,36 +802,9 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
845
802
}
846
803
}
847
804
} else {
848
- InitListExpr *SForm =
849
- ILE->isSyntacticForm () ? ILE : ILE->getSyntacticForm ();
850
805
// The fields beyond ILE->getNumInits() are default initialized, so in
851
806
// order to leave them uninitialized, the ILE is expanded and the extra
852
807
// fields are then filled with NoInitExpr.
853
-
854
- // Some checks that are required for missing fields warning are bound to
855
- // how many elements the initializer list originally was provided; perform
856
- // them before the list is expanded.
857
- bool WarnIfMissingField =
858
- !SForm->isIdiomaticZeroInitializer (SemaRef.getLangOpts ()) &&
859
- ILE->getNumInits ();
860
-
861
- // Disable check for missing fields when designators are used in C to
862
- // match gcc behaviour.
863
- // FIXME: Should we emulate possible gcc warning bug?
864
- WarnIfMissingField &=
865
- SemaRef.getLangOpts ().CPlusPlus || !hasAnyDesignatedInits (SForm);
866
-
867
- if (OuterILE) {
868
- // When nested designators are present, there might be two nested init
869
- // lists created and only outer will contain designated initializer
870
- // expression, so check outer list as well.
871
- InitListExpr *OuterSForm = OuterILE->isSyntacticForm ()
872
- ? OuterILE
873
- : OuterILE->getSyntacticForm ();
874
- WarnIfMissingField &= SemaRef.getLangOpts ().CPlusPlus ||
875
- !hasAnyDesignatedInits (OuterSForm);
876
- }
877
-
878
808
unsigned NumElems = numStructUnionElements (ILE->getType ());
879
809
if (!RDecl->isUnion () && RDecl->hasFlexibleArrayMember ())
880
810
++NumElems;
@@ -902,7 +832,7 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
902
832
return ;
903
833
904
834
FillInEmptyInitForField (Init, Field, Entity, ILE, RequiresSecondPass,
905
- FillWithNoInit, WarnIfMissingField );
835
+ FillWithNoInit);
906
836
if (hadError)
907
837
return ;
908
838
@@ -1017,6 +947,13 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
1017
947
}
1018
948
}
1019
949
950
+ static bool hasAnyDesignatedInits (const InitListExpr *IL) {
951
+ for (const Stmt *Init : *IL)
952
+ if (isa_and_nonnull<DesignatedInitExpr>(Init))
953
+ return true ;
954
+ return false ;
955
+ }
956
+
1020
957
InitListChecker::InitListChecker (
1021
958
Sema &S, const InitializedEntity &Entity, InitListExpr *IL, QualType &T,
1022
959
bool VerifyOnly, bool TreatUnavailableAsInvalid, bool InOverloadResolution,
@@ -2288,8 +2225,12 @@ void InitListChecker::CheckStructUnionTypes(
2288
2225
size_t NumRecordDecls = llvm::count_if (RD->decls (), [&](const Decl *D) {
2289
2226
return isa<FieldDecl>(D) || isa<RecordDecl>(D);
2290
2227
});
2228
+ bool CheckForMissingFields =
2229
+ !IList->isIdiomaticZeroInitializer (SemaRef.getLangOpts ());
2291
2230
bool HasDesignatedInit = false ;
2292
2231
2232
+ llvm::SmallPtrSet<FieldDecl *, 4 > InitializedFields;
2233
+
2293
2234
while (Index < IList->getNumInits ()) {
2294
2235
Expr *Init = IList->getInit (Index);
2295
2236
SourceLocation InitLoc = Init->getBeginLoc ();
@@ -2313,17 +2254,24 @@ void InitListChecker::CheckStructUnionTypes(
2313
2254
2314
2255
// Find the field named by the designated initializer.
2315
2256
DesignatedInitExpr::Designator *D = DIE->getDesignator (0 );
2316
- if (!VerifyOnly && D->isFieldDesignator () && !DesignatedInitFailed ) {
2257
+ if (!VerifyOnly && D->isFieldDesignator ()) {
2317
2258
FieldDecl *F = D->getFieldDecl ();
2318
- QualType ET = SemaRef.Context .getBaseElementType (F->getType ());
2319
- if (checkDestructorReference (ET, InitLoc, SemaRef)) {
2320
- hadError = true ;
2321
- return ;
2259
+ InitializedFields.insert (F);
2260
+ if (!DesignatedInitFailed) {
2261
+ QualType ET = SemaRef.Context .getBaseElementType (F->getType ());
2262
+ if (checkDestructorReference (ET, InitLoc, SemaRef)) {
2263
+ hadError = true ;
2264
+ return ;
2265
+ }
2322
2266
}
2323
2267
}
2324
2268
2325
2269
InitializedSomething = true ;
2326
2270
2271
+ // Disable check for missing fields when designators are used.
2272
+ // This matches gcc behaviour.
2273
+ if (!SemaRef.getLangOpts ().CPlusPlus )
2274
+ CheckForMissingFields = false ;
2327
2275
continue ;
2328
2276
}
2329
2277
@@ -2402,6 +2350,7 @@ void InitListChecker::CheckStructUnionTypes(
2402
2350
CheckSubElementType (MemberEntity, IList, Field->getType (), Index,
2403
2351
StructuredList, StructuredIndex);
2404
2352
InitializedSomething = true ;
2353
+ InitializedFields.insert (*Field);
2405
2354
2406
2355
if (RD->isUnion () && StructuredList) {
2407
2356
// Initialize the first field within the union.
@@ -2411,6 +2360,28 @@ void InitListChecker::CheckStructUnionTypes(
2411
2360
++Field;
2412
2361
}
2413
2362
2363
+ // Emit warnings for missing struct field initializers.
2364
+ if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
2365
+ !RD->isUnion ()) {
2366
+ // It is possible we have one or more unnamed bitfields remaining.
2367
+ // Find first (if any) named field and emit warning.
2368
+ for (RecordDecl::field_iterator it = HasDesignatedInit ? RD->field_begin ()
2369
+ : Field,
2370
+ end = RD->field_end ();
2371
+ it != end; ++it) {
2372
+ if (HasDesignatedInit && InitializedFields.count (*it))
2373
+ continue ;
2374
+
2375
+ if (!it->isUnnamedBitfield () && !it->hasInClassInitializer () &&
2376
+ !it->getType ()->isIncompleteArrayType ()) {
2377
+ SemaRef.Diag (IList->getSourceRange ().getEnd (),
2378
+ diag::warn_missing_field_initializers)
2379
+ << *it;
2380
+ break ;
2381
+ }
2382
+ }
2383
+ }
2384
+
2414
2385
// Check that any remaining fields can be value-initialized if we're not
2415
2386
// building a structured list. (If we are, we'll check this later.)
2416
2387
if (!StructuredList && Field != FieldEnd && !RD->isUnion () &&
0 commit comments