summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaInit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaInit.cpp')
-rw-r--r--lib/Sema/SemaInit.cpp49
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;