r324537 - PR36055: fix computation of *-dependence in nested initializer lists.
Hans Wennborg via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 9 01:05:53 PST 2018
Merged to 6.0 in r324719.
On Wed, Feb 7, 2018 at 11:25 PM, Richard Smith via cfe-commits
<cfe-commits at lists.llvm.org> wrote:
> Author: rsmith
> Date: Wed Feb 7 14:25:16 2018
> New Revision: 324537
>
> URL: http://llvm.org/viewvc/llvm-project?rev=324537&view=rev
> Log:
> PR36055: fix computation of *-dependence in nested initializer lists.
>
> When we synthesize an implicit inner initializer list when analyzing an outer
> initializer list, we add it to the outer list immediately, and then fill in the
> inner list. This gives the outer list no chance to update its *-dependence bits
> with those of the completed inner list. To fix this, re-add the inner list to
> the outer list once it's completed.
>
> Note that we do not recompute the *-dependence bits from scratch when we
> complete an outer list; this would give the wrong result for the case where a
> designated initializer overwrites a dependent initializer with a non-dependent
> one. The resulting list in that case should still be dependent, even though all
> traces of the dependence were removed from the semantic form.
>
> Modified:
> cfe/trunk/lib/Sema/SemaInit.cpp
> cfe/trunk/test/SemaCXX/init-expr-crash.cpp
> cfe/trunk/test/SemaTemplate/instantiate-init.cpp
>
> Modified: cfe/trunk/lib/Sema/SemaInit.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=324537&r1=324536&r2=324537&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaInit.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaInit.cpp Wed Feb 7 14:25:16 2018
> @@ -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::FillInEmptyInitFor
> 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::FillInEmptyInitFor
> } 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::FillInEmptyInitializati
> } 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
>
> 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::CheckSubElementTyp
> 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;
>
> Modified: cfe/trunk/test/SemaCXX/init-expr-crash.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/init-expr-crash.cpp?rev=324537&r1=324536&r2=324537&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/init-expr-crash.cpp (original)
> +++ cfe/trunk/test/SemaCXX/init-expr-crash.cpp Wed Feb 7 14:25:16 2018
> @@ -29,3 +29,11 @@ template <class T> struct B {
> return 0;
> }
> };
> +
> +// This test checks for a crash that resulted from us miscomputing the
> +// dependence of a nested initializer list.
> +template<int> struct X {
> + static constexpr int n = 4;
> + static constexpr int a[1][1] = {n};
> +};
> +
>
> Modified: cfe/trunk/test/SemaTemplate/instantiate-init.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-init.cpp?rev=324537&r1=324536&r2=324537&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaTemplate/instantiate-init.cpp (original)
> +++ cfe/trunk/test/SemaTemplate/instantiate-init.cpp Wed Feb 7 14:25:16 2018
> @@ -142,3 +142,17 @@ namespace ReturnStmtIsInitialization {
> template<typename T> X f() { return {}; }
> auto &&x = f<void>();
> }
> +
> +namespace InitListUpdate {
> + struct A { int n; };
> + using AA = A[1];
> +
> + // Check that an init list update doesn't "lose" the pack-ness of an expression.
> + template <int... N> void f() {
> + g(AA{0, [0].n = N} ...); // expected-warning 3{{overrides prior init}} expected-note 3{{previous init}}
> + g(AA{N, [0].n = 0} ...); // expected-warning 3{{overrides prior init}} expected-note 3{{previous init}}
> + };
> +
> + void g(AA, AA);
> + void h() { f<1, 2>(); } // expected-note {{instantiation of}}
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list