[llvm-branch-commits] [cfe-branch] r324719 - Merging r324537:

Hans Wennborg via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Feb 9 01:04:00 PST 2018


Author: hans
Date: Fri Feb  9 01:04:00 2018
New Revision: 324719

URL: http://llvm.org/viewvc/llvm-project?rev=324719&view=rev
Log:
Merging r324537:
------------------------------------------------------------------------
r324537 | rsmith | 2018-02-07 23:25:16 +0100 (Wed, 07 Feb 2018) | 14 lines

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/branches/release_60/   (props changed)
    cfe/branches/release_60/lib/Sema/SemaInit.cpp
    cfe/branches/release_60/test/SemaCXX/init-expr-crash.cpp
    cfe/branches/release_60/test/SemaTemplate/instantiate-init.cpp

Propchange: cfe/branches/release_60/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Feb  9 01:04:00 2018
@@ -1,4 +1,4 @@
 /cfe/branches/type-system-rewrite:134693-134817
-/cfe/trunk:321754,321771,321777,321779,321933,322018,322236,322245-322246,322350,322390,322405,322420,322518,322593,322813,322901,322904,322984,323008,323123,323155,323360,323485,323904,323935,324059,324134,324246,324419,324439,324514,324594
+/cfe/trunk:321754,321771,321777,321779,321933,322018,322236,322245-322246,322350,322390,322405,322420,322518,322593,322813,322901,322904,322984,323008,323123,323155,323360,323485,323904,323935,324059,324134,324246,324419,324439,324514,324537,324594
 /cfe/trunk/test:170344
 /cfe/trunk/test/SemaTemplate:126920

Modified: cfe/branches/release_60/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_60/lib/Sema/SemaInit.cpp?rev=324719&r1=324718&r2=324719&view=diff
==============================================================================
--- cfe/branches/release_60/lib/Sema/SemaInit.cpp (original)
+++ cfe/branches/release_60/lib/Sema/SemaInit.cpp Fri Feb  9 01:04:00 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/branches/release_60/test/SemaCXX/init-expr-crash.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_60/test/SemaCXX/init-expr-crash.cpp?rev=324719&r1=324718&r2=324719&view=diff
==============================================================================
--- cfe/branches/release_60/test/SemaCXX/init-expr-crash.cpp (original)
+++ cfe/branches/release_60/test/SemaCXX/init-expr-crash.cpp Fri Feb  9 01:04:00 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/branches/release_60/test/SemaTemplate/instantiate-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_60/test/SemaTemplate/instantiate-init.cpp?rev=324719&r1=324718&r2=324719&view=diff
==============================================================================
--- cfe/branches/release_60/test/SemaTemplate/instantiate-init.cpp (original)
+++ cfe/branches/release_60/test/SemaTemplate/instantiate-init.cpp Fri Feb  9 01:04:00 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}}
+}




More information about the llvm-branch-commits mailing list