diff options
Diffstat (limited to 'lib/Sema/SemaInit.cpp')
-rw-r--r-- | lib/Sema/SemaInit.cpp | 49 |
1 files changed, 37 insertions, 12 deletions
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 011051da58..df64a33954 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -352,6 +352,7 @@ class InitListChecker { bool FillWithNoInit = false); void FillInEmptyInitializations(const InitializedEntity &Entity, InitListExpr *ILE, bool &RequiresSecondPass, + InitListExpr *OuterILE, unsigned OuterIndex, bool FillWithNoInit = false); bool CheckFlexibleArrayInit(const InitializedEntity &Entity, Expr *InitExpr, FieldDecl *Field, @@ -517,12 +518,13 @@ void InitListChecker::FillInEmptyInitForBase( ILE->setInit(Init, BaseInit.getAs<Expr>()); } else if (InitListExpr *InnerILE = dyn_cast<InitListExpr>(ILE->getInit(Init))) { - FillInEmptyInitializations(BaseEntity, InnerILE, - RequiresSecondPass, FillWithNoInit); + FillInEmptyInitializations(BaseEntity, InnerILE, RequiresSecondPass, + ILE, Init, FillWithNoInit); } else if (DesignatedInitUpdateExpr *InnerDIUE = dyn_cast<DesignatedInitUpdateExpr>(ILE->getInit(Init))) { FillInEmptyInitializations(BaseEntity, InnerDIUE->getUpdater(), - RequiresSecondPass, /*FillWithNoInit =*/true); + RequiresSecondPass, ILE, Init, + /*FillWithNoInit =*/true); } } @@ -605,24 +607,43 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, } else if (InitListExpr *InnerILE = dyn_cast<InitListExpr>(ILE->getInit(Init))) FillInEmptyInitializations(MemberEntity, InnerILE, - RequiresSecondPass, FillWithNoInit); + RequiresSecondPass, ILE, Init, FillWithNoInit); else if (DesignatedInitUpdateExpr *InnerDIUE = dyn_cast<DesignatedInitUpdateExpr>(ILE->getInit(Init))) FillInEmptyInitializations(MemberEntity, InnerDIUE->getUpdater(), - RequiresSecondPass, /*FillWithNoInit =*/ true); + RequiresSecondPass, ILE, Init, + /*FillWithNoInit =*/true); } /// Recursively replaces NULL values within the given initializer list /// with expressions that perform value-initialization of the -/// appropriate type. +/// appropriate type, and finish off the InitListExpr formation. void InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, InitListExpr *ILE, bool &RequiresSecondPass, + InitListExpr *OuterILE, + unsigned OuterIndex, bool FillWithNoInit) { assert((ILE->getType() != SemaRef.Context.VoidTy) && "Should not have void type"); + // If this is a nested initializer list, we might have changed its contents + // (and therefore some of its properties, such as instantiation-dependence) + // while filling it in. Inform the outer initializer list so that its state + // can be updated to match. + // FIXME: We should fully build the inner initializers before constructing + // the outer InitListExpr instead of mutating AST nodes after they have + // been used as subexpressions of other nodes. + struct UpdateOuterILEWithUpdatedInit { + InitListExpr *Outer; + unsigned OuterIndex; + ~UpdateOuterILEWithUpdatedInit() { + if (Outer) + Outer->setInit(OuterIndex, Outer->getInit(OuterIndex)); + } + } UpdateOuterRAII = {OuterILE, OuterIndex}; + // A transparent ILE is not performing aggregate initialization and should // not be filled in. if (ILE->isTransparent()) @@ -769,11 +790,12 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, } else if (InitListExpr *InnerILE = dyn_cast_or_null<InitListExpr>(InitExpr)) FillInEmptyInitializations(ElementEntity, InnerILE, RequiresSecondPass, - FillWithNoInit); + ILE, Init, FillWithNoInit); else if (DesignatedInitUpdateExpr *InnerDIUE = dyn_cast_or_null<DesignatedInitUpdateExpr>(InitExpr)) FillInEmptyInitializations(ElementEntity, InnerDIUE->getUpdater(), - RequiresSecondPass, /*FillWithNoInit =*/ true); + RequiresSecondPass, ILE, Init, + /*FillWithNoInit =*/true); } } @@ -795,10 +817,11 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity, if (!hadError && !VerifyOnly) { bool RequiresSecondPass = false; - FillInEmptyInitializations(Entity, FullyStructuredList, RequiresSecondPass); + FillInEmptyInitializations(Entity, FullyStructuredList, RequiresSecondPass, + /*OuterILE=*/nullptr, /*OuterIndex=*/0); if (RequiresSecondPass && !hadError) FillInEmptyInitializations(Entity, FullyStructuredList, - RequiresSecondPass); + RequiresSecondPass, nullptr, 0); } } @@ -1162,10 +1185,12 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, if (!hadError && !VerifyOnly) { bool RequiresSecondPass = false; FillInEmptyInitializations(Entity, InnerStructuredList, - RequiresSecondPass); + RequiresSecondPass, StructuredList, + StructuredIndex); if (RequiresSecondPass && !hadError) FillInEmptyInitializations(Entity, InnerStructuredList, - RequiresSecondPass); + RequiresSecondPass, StructuredList, + StructuredIndex); } ++StructuredIndex; ++Index; |