@@ -349,17 +349,13 @@ class InitListChecker {
349
349
bool SubobjectIsDesignatorContext, unsigned &Index,
350
350
InitListExpr *StructuredList,
351
351
unsigned &StructuredIndex);
352
- bool CheckDesignatedInitializer (const InitializedEntity &Entity,
353
- InitListExpr *IList, DesignatedInitExpr *DIE,
354
- unsigned DesigIdx,
355
- QualType &CurrentObjectType,
356
- RecordDecl::field_iterator *NextField,
357
- llvm::APSInt *NextElementIndex,
358
- unsigned &Index,
359
- InitListExpr *StructuredList,
360
- unsigned &StructuredIndex,
361
- bool FinishSubobjectInit,
362
- bool TopLevelObject);
352
+ bool CheckDesignatedInitializer (
353
+ const InitializedEntity &Entity, InitListExpr *IList,
354
+ DesignatedInitExpr *DIE, unsigned DesigIdx, QualType &CurrentObjectType,
355
+ RecordDecl::field_iterator *NextField, llvm::APSInt *NextElementIndex,
356
+ unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex,
357
+ bool FinishSubobjectInit, bool TopLevelObject,
358
+ llvm::SmallPtrSetImpl<FieldDecl *> *InitializedFields = nullptr );
363
359
InitListExpr *getStructuredSubobjectInit (InitListExpr *IList, unsigned Index,
364
360
QualType CurrentObjectType,
365
361
InitListExpr *StructuredList,
@@ -2248,15 +2244,15 @@ void InitListChecker::CheckStructUnionTypes(
2248
2244
// the next field that we'll be initializing.
2249
2245
bool DesignatedInitFailed = CheckDesignatedInitializer (
2250
2246
Entity, IList, DIE, 0 , DeclType, &Field, nullptr , Index,
2251
- StructuredList, StructuredIndex, true , TopLevelObject);
2247
+ StructuredList, StructuredIndex, true , TopLevelObject,
2248
+ &InitializedFields);
2252
2249
if (DesignatedInitFailed)
2253
2250
hadError = true ;
2254
2251
2255
2252
// Find the field named by the designated initializer.
2256
2253
DesignatedInitExpr::Designator *D = DIE->getDesignator (0 );
2257
2254
if (!VerifyOnly && D->isFieldDesignator ()) {
2258
2255
FieldDecl *F = D->getFieldDecl ();
2259
- InitializedFields.insert (F);
2260
2256
if (!DesignatedInitFailed) {
2261
2257
QualType ET = SemaRef.Context .getBaseElementType (F->getType ());
2262
2258
if (checkDestructorReference (ET, InitLoc, SemaRef)) {
@@ -2365,21 +2361,43 @@ void InitListChecker::CheckStructUnionTypes(
2365
2361
!RD->isUnion ()) {
2366
2362
// It is possible we have one or more unnamed bitfields remaining.
2367
2363
// 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 ;
2364
+ auto MissingFieldCheck = [&](const RecordDecl *Record,
2365
+ RecordDecl::field_iterator StartField,
2366
+ auto &&MissingFieldCheck) -> bool {
2367
+ FieldDecl *FirstUninitialized = nullptr ;
2368
+ for (RecordDecl::field_iterator it = StartField,
2369
+ end = Record->field_end ();
2370
+ it != end; ++it) {
2371
+ bool AllSet = false ;
2372
+ if (it->isAnonymousStructOrUnion ()) {
2373
+ RecordDecl *RDAnon = it->getType ()->getAsRecordDecl ();
2374
+ AllSet = MissingFieldCheck (RDAnon, RDAnon->field_begin (),
2375
+ MissingFieldCheck);
2376
+ }
2377
+
2378
+ if ((HasDesignatedInit && InitializedFields.count (*it)) ||
2379
+ it->hasInClassInitializer () || AllSet) {
2380
+ if (Record->isUnion ())
2381
+ return true ;
2382
+ continue ;
2383
+ }
2374
2384
2375
- if (!it->isUnnamedBitfield () && !it->hasInClassInitializer () &&
2376
- !it->getType ()->isIncompleteArrayType ()) {
2385
+ if (!it->isUnnamedBitfield () &&
2386
+ !it->getType ()->isIncompleteArrayType () &&
2387
+ !it->isAnonymousStructOrUnion () && !FirstUninitialized)
2388
+ FirstUninitialized = *it;
2389
+ }
2390
+
2391
+ if (FirstUninitialized) {
2377
2392
SemaRef.Diag (IList->getSourceRange ().getEnd (),
2378
2393
diag::warn_missing_field_initializers)
2379
- << *it ;
2380
- break ;
2394
+ << FirstUninitialized ;
2395
+ return false ;
2381
2396
}
2382
- }
2397
+ return true ;
2398
+ };
2399
+ MissingFieldCheck (RD, HasDesignatedInit ? RD->field_begin () : Field,
2400
+ MissingFieldCheck);
2383
2401
}
2384
2402
2385
2403
// Check that any remaining fields can be value-initialized if we're not
@@ -2537,19 +2555,13 @@ class FieldInitializerValidatorCCC final : public CorrectionCandidateCallback {
2537
2555
// / actually be initialized.
2538
2556
// /
2539
2557
// / @returns true if there was an error, false otherwise.
2540
- bool
2541
- InitListChecker::CheckDesignatedInitializer (const InitializedEntity &Entity,
2542
- InitListExpr *IList,
2543
- DesignatedInitExpr *DIE,
2544
- unsigned DesigIdx,
2545
- QualType &CurrentObjectType,
2546
- RecordDecl::field_iterator *NextField,
2547
- llvm::APSInt *NextElementIndex,
2548
- unsigned &Index,
2549
- InitListExpr *StructuredList,
2550
- unsigned &StructuredIndex,
2551
- bool FinishSubobjectInit,
2552
- bool TopLevelObject) {
2558
+ bool InitListChecker::CheckDesignatedInitializer (
2559
+ const InitializedEntity &Entity, InitListExpr *IList,
2560
+ DesignatedInitExpr *DIE, unsigned DesigIdx, QualType &CurrentObjectType,
2561
+ RecordDecl::field_iterator *NextField, llvm::APSInt *NextElementIndex,
2562
+ unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex,
2563
+ bool FinishSubobjectInit, bool TopLevelObject,
2564
+ llvm::SmallPtrSetImpl<FieldDecl *> *InitializedFields) {
2553
2565
if (DesigIdx == DIE->size ()) {
2554
2566
// C++20 designated initialization can result in direct-list-initialization
2555
2567
// of the designated subobject. This is the only way that we can end up
@@ -2853,8 +2865,11 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
2853
2865
2854
2866
2855
2867
// Update the designator with the field declaration.
2856
- if (!VerifyOnly)
2868
+ if (!VerifyOnly) {
2857
2869
D->setFieldDecl (*Field);
2870
+ if (InitializedFields)
2871
+ InitializedFields->insert (*Field);
2872
+ }
2858
2873
2859
2874
// Make sure that our non-designated initializer list has space
2860
2875
// for a subobject corresponding to this field.
@@ -2929,10 +2944,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
2929
2944
2930
2945
InitializedEntity MemberEntity =
2931
2946
InitializedEntity::InitializeMember (*Field, &Entity);
2932
- if (CheckDesignatedInitializer (MemberEntity, IList, DIE, DesigIdx + 1 ,
2933
- FieldType, nullptr , nullptr , Index ,
2934
- StructuredList, newStructuredIndex,
2935
- FinishSubobjectInit, false ))
2947
+ if (CheckDesignatedInitializer (
2948
+ MemberEntity, IList, DIE, DesigIdx + 1 , FieldType, nullptr ,
2949
+ nullptr , Index, StructuredList, newStructuredIndex,
2950
+ FinishSubobjectInit, false , InitializedFields ))
2936
2951
return true ;
2937
2952
}
2938
2953
0 commit comments