]> granicus.if.org Git - clang/commitdiff
AST: Mangle reference temporaries reliably
authorDavid Majnemer <david.majnemer@gmail.com>
Thu, 1 May 2014 17:50:17 +0000 (17:50 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Thu, 1 May 2014 17:50:17 +0000 (17:50 +0000)
Summary:
Previously, we would generate a single name for all reference
temporaries and allow LLVM to rename them for us.  Instead, number the
reference temporaries as we build them in Sema.

Reviewers: rsmith

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D3554

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@207776 91177308-0d34-0410-b5e6-96231b3b80d8

14 files changed:
include/clang/AST/ExprCXX.h
include/clang/AST/Mangle.h
include/clang/Sema/Initialization.h
lib/AST/ExprCXX.cpp
lib/AST/ItaniumMangle.cpp
lib/AST/MicrosoftMangle.cpp
lib/CodeGen/CodeGenModule.cpp
lib/Sema/SemaCast.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaInit.cpp
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriterStmt.cpp
test/CodeGenCXX/const-init-cxx1y.cpp
test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp

index aff0021a77f4e646116d07c4e0423cb20ce22f8a..2381fd9dbcc2fa547dafb78aaa78a712e4e05137 100644 (file)
@@ -3784,39 +3784,51 @@ public:
 /// temporary. When either happens, the expression will also track the
 /// declaration which is responsible for the lifetime extension.
 class MaterializeTemporaryExpr : public Expr {
-public:
-  /// \brief The temporary-generating expression whose value will be
-  /// materialized.
-  Stmt *Temporary;
+private:
+  struct ExtraState {
+    /// \brief The temporary-generating expression whose value will be
+    /// materialized.
+    Stmt *Temporary;
 
-  /// \brief The declaration which lifetime-extended this reference, if any.
-  /// Either a VarDecl, or (for a ctor-initializer) a FieldDecl.
-  const ValueDecl *ExtendingDecl;
+    /// \brief The declaration which lifetime-extended this reference, if any.
+    /// Either a VarDecl, or (for a ctor-initializer) a FieldDecl.
+    const ValueDecl *ExtendingDecl;
+
+    unsigned ManglingNumber;
+  };
+  llvm::PointerUnion<Stmt *, ExtraState *> State;
 
   friend class ASTStmtReader;
   friend class ASTStmtWriter;
 
+  void initializeExtraState(const ValueDecl *ExtendedBy,
+                            unsigned ManglingNumber);
+
 public:
   MaterializeTemporaryExpr(QualType T, Expr *Temporary,
-                           bool BoundToLvalueReference,
-                           const ValueDecl *ExtendedBy)
+                           bool BoundToLvalueReference)
     : Expr(MaterializeTemporaryExprClass, T,
            BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary,
            Temporary->isTypeDependent(), Temporary->isValueDependent(),
            Temporary->isInstantiationDependent(),
            Temporary->containsUnexpandedParameterPack()),
-      Temporary(Temporary), ExtendingDecl(ExtendedBy) {
-  }
+        State(Temporary) {}
 
   MaterializeTemporaryExpr(EmptyShell Empty)
     : Expr(MaterializeTemporaryExprClass, Empty) { }
 
+  Stmt *getTemporary() const {
+    return State.is<Stmt *>() ? State.get<Stmt *>()
+                              : State.get<ExtraState *>()->Temporary;
+  }
+
   /// \brief Retrieve the temporary-generating subexpression whose value will
   /// be materialized into a glvalue.
-  Expr *GetTemporaryExpr() const { return static_cast<Expr *>(Temporary); }
+  Expr *GetTemporaryExpr() const { return static_cast<Expr *>(getTemporary()); }
 
   /// \brief Retrieve the storage duration for the materialized temporary.
   StorageDuration getStorageDuration() const {
+    const ValueDecl *ExtendingDecl = getExtendingDecl();
     if (!ExtendingDecl)
       return SD_FullExpression;
     // FIXME: This is not necessarily correct for a temporary materialized
@@ -3828,10 +3840,15 @@ public:
 
   /// \brief Get the declaration which triggered the lifetime-extension of this
   /// temporary, if any.
-  const ValueDecl *getExtendingDecl() const { return ExtendingDecl; }
+  const ValueDecl *getExtendingDecl() const {
+    return State.is<Stmt *>() ? nullptr
+                              : State.get<ExtraState *>()->ExtendingDecl;
+  }
+
+  void setExtendingDecl(const ValueDecl *ExtendedBy, unsigned ManglingNumber);
 
-  void setExtendingDecl(const ValueDecl *ExtendedBy) {
-    ExtendingDecl = ExtendedBy;
+  unsigned getManglingNumber() const {
+    return State.is<Stmt *>() ? 0 : State.get<ExtraState *>()->ManglingNumber;
   }
 
   /// \brief Determine whether this materialized temporary is bound to an
@@ -3841,10 +3858,10 @@ public:
   }
 
   SourceLocation getLocStart() const LLVM_READONLY {
-    return Temporary->getLocStart();
+    return getTemporary()->getLocStart();
   }
   SourceLocation getLocEnd() const LLVM_READONLY {
-    return Temporary->getLocEnd();
+    return getTemporary()->getLocEnd();
   }
 
   static bool classof(const Stmt *T) {
@@ -3852,7 +3869,13 @@ public:
   }
 
   // Iterators
-  child_range children() { return child_range(&Temporary, &Temporary + 1); }
+  child_range children() {
+    if (State.is<Stmt *>())
+      return child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1);
+
+    auto ES = State.get<ExtraState *>();
+    return child_range(&ES->Temporary, &ES->Temporary + 1);
+  }
 };
 
 }  // end namespace clang
index 28bcd8b30bded8ecee6167dc1fb9674ad015f302..483c1e67bd0e2a74faa888c8839ac77a0fe60533 100644 (file)
@@ -130,6 +130,7 @@ public:
                                   const ThisAdjustment &ThisAdjustment,
                                   raw_ostream &) = 0;
   virtual void mangleReferenceTemporary(const VarDecl *D,
+                                        unsigned ManglingNumber,
                                         raw_ostream &) = 0;
   virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0;
   virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0;
index 83fb2be5f15f27be0c34aac7ee270d6598cfa59b..90618af09032195475c323554198767792f1fc3a 100644 (file)
@@ -103,6 +103,9 @@ private:
   /// \brief The type of the object or reference being initialized.
   QualType Type;
 
+  /// \brief The mangling number for the next reference temporary to be created.
+  mutable unsigned ManglingNumber;
+
   struct LN {
     /// \brief When Kind == EK_Result, EK_Exception, EK_New, the
     /// location of the 'return', 'throw', or 'new' keyword,
@@ -155,11 +158,11 @@ private:
     struct C Capture;
   };
 
-  InitializedEntity() }
+  InitializedEntity() : ManglingNumber(0) {}
 
   /// \brief Create the initialization entity for a variable.
   InitializedEntity(VarDecl *Var)
-    : Kind(EK_Variable), Parent(0), Type(Var->getType()),
+    : Kind(EK_Variable), Parent(0), Type(Var->getType()), ManglingNumber(0),
       VariableOrMember(Var) { }
   
   /// \brief Create the initialization entity for the result of a
@@ -167,7 +170,7 @@ private:
   /// initializing a parameter for which there is no declaration.
   InitializedEntity(EntityKind Kind, SourceLocation Loc, QualType Type,
                     bool NRVO = false)
-    : Kind(Kind), Parent(0), Type(Type)
+    : Kind(Kind), Parent(0), Type(Type), ManglingNumber(0)
   {
     LocAndNRVO.Location = Loc.getRawEncoding();
     LocAndNRVO.NRVO = NRVO;
@@ -176,7 +179,7 @@ private:
   /// \brief Create the initialization entity for a member subobject.
   InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent) 
     : Kind(EK_Member), Parent(Parent), Type(Member->getType()),
-      VariableOrMember(Member) { }
+      ManglingNumber(0), VariableOrMember(Member) { }
   
   /// \brief Create the initialization entity for an array element.
   InitializedEntity(ASTContext &Context, unsigned Index, 
@@ -184,7 +187,7 @@ private:
 
   /// \brief Create the initialization entity for a lambda capture.
   InitializedEntity(IdentifierInfo *VarID, QualType FieldType, SourceLocation Loc)
-    : Kind(EK_LambdaCapture), Parent(0), Type(FieldType) 
+    : Kind(EK_LambdaCapture), Parent(0), Type(FieldType), ManglingNumber(0)
   {
     Capture.VarID = VarID;
     Capture.Location = Loc.getRawEncoding();
@@ -418,6 +421,8 @@ public:
     Kind = EK_Parameter_CF_Audited;
   }
 
+  unsigned allocateManglingNumber() const { return ++ManglingNumber; }
+
   /// Dump a representation of the initialized entity to standard error,
   /// for debugging purposes.
   void dump() const;
index ee4992590a282871c70b905030a1cf0f32a9930e..0181235bff5da2ef527809e44313b2c1dcc28eda 100644 (file)
@@ -1446,6 +1446,25 @@ FunctionParmPackExpr::CreateEmpty(const ASTContext &Context,
     FunctionParmPackExpr(QualType(), 0, SourceLocation(), 0, 0);
 }
 
+void MaterializeTemporaryExpr::setExtendingDecl(const ValueDecl *ExtendedBy,
+                                                unsigned ManglingNumber) {
+  // We only need extra state if we have to remember more than just the Stmt.
+  if (!ExtendedBy)
+    return;
+
+  // We may need to allocate extra storage for the mangling number and the
+  // extended-by ValueDecl.
+  if (!State.is<ExtraState *>()) {
+    auto ES = new (ExtendedBy->getASTContext()) ExtraState;
+    ES->Temporary = State.get<Stmt *>();
+    State = ES;
+  }
+
+  auto ES = State.get<ExtraState *>();
+  ES->ExtendingDecl = ExtendedBy;
+  ES->ManglingNumber = ManglingNumber;
+}
+
 TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
                              ArrayRef<TypeSourceInfo *> Args,
                              SourceLocation RParenLoc,
index f7dbf09d1527ec27e34b3ccb382d369c7cbf548d..7105af2a7616e38a59d6ec91eeb17d85af2c7f49 100644 (file)
@@ -136,7 +136,8 @@ public:
   void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
                           const ThisAdjustment &ThisAdjustment,
                           raw_ostream &) override;
-  void mangleReferenceTemporary(const VarDecl *D, raw_ostream &) override;
+  void mangleReferenceTemporary(const VarDecl *D, unsigned ManglingNumber,
+                                raw_ostream &) override;
   void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) override;
   void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) override;
   void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
@@ -3782,12 +3783,16 @@ ItaniumMangleContextImpl::mangleItaniumThreadLocalWrapper(const VarDecl *D,
 }
 
 void ItaniumMangleContextImpl::mangleReferenceTemporary(const VarDecl *D,
+                                                        unsigned ManglingNumber,
                                                         raw_ostream &Out) {
   // We match the GCC mangling here.
   //  <special-name> ::= GR <object name>
   CXXNameMangler Mangler(*this, Out);
   Mangler.getStream() << "_ZGR";
   Mangler.mangleName(D);
+  assert(ManglingNumber > 0 && "Reference temporary mangling number is zero!");
+  if (ManglingNumber > 1)
+    Mangler.mangleNumber(ManglingNumber - 2);
 }
 
 void ItaniumMangleContextImpl::mangleCXXVTable(const CXXRecordDecl *RD,
index edea497d994575fdedbe7c7e162dc8f9f94a12c9..b615c6f17f4cdfd759ee7d9f1c23747461ce375b 100644 (file)
@@ -117,7 +117,8 @@ public:
                      raw_ostream &) override;
   void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
                      raw_ostream &) override;
-  void mangleReferenceTemporary(const VarDecl *, raw_ostream &) override;
+  void mangleReferenceTemporary(const VarDecl *, unsigned ManglingNumber,
+                                raw_ostream &) override;
   void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out) override;
   void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override;
   void mangleDynamicAtExitDestructor(const VarDecl *D,
@@ -2267,6 +2268,7 @@ void MicrosoftMangleContextImpl::mangleCXXDtor(const CXXDestructorDecl *D,
 }
 
 void MicrosoftMangleContextImpl::mangleReferenceTemporary(const VarDecl *VD,
+                                                          unsigned,
                                                           raw_ostream &) {
   unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
     "cannot mangle this reference temporary yet");
index 610393330085430c5e80063359a014ef11f8c2c4..ac97bdac601a9e040e7e41cbbcf8f43ef23226f3 100644 (file)
@@ -2828,7 +2828,8 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalTemporary(
   // we also need to make the temporaries externally-visible).
   SmallString<256> Name;
   llvm::raw_svector_ostream Out(Name);
-  getCXXABI().getMangleContext().mangleReferenceTemporary(VD, Out);
+  getCXXABI().getMangleContext().mangleReferenceTemporary(
+      VD, E->getManglingNumber(), Out);
   Out.flush();
 
   APValue *Value = 0;
index 33078b0e6419335ca00310bc38283e196c22b1c9..51a339581d80d57c7911f84f5c0b21054d22012a 100644 (file)
@@ -1584,8 +1584,7 @@ static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr,
     // This is a const_cast from a class prvalue to an rvalue reference type.
     // Materialize a temporary to store the result of the conversion.
     SrcExpr = new (Self.Context) MaterializeTemporaryExpr(
-        SrcType, SrcExpr.take(), /*IsLValueReference*/ false,
-        /*ExtendingDecl*/ 0);
+        SrcType, SrcExpr.take(), /*IsLValueReference*/ false);
 
   return TC_Success;
 }
index b410efee3c8225ea09eec22dfce58cf68c196b57..b28165b16844a79511947d974f0a69ae6df3a598 100644 (file)
@@ -8885,7 +8885,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
       return QualType();
     // Materialize the temporary as an lvalue so that we can take its address.
     OrigOp = op = new (Context)
-        MaterializeTemporaryExpr(op->getType(), OrigOp.take(), true, 0);
+        MaterializeTemporaryExpr(op->getType(), OrigOp.take(), true);
   } else if (isa<ObjCSelectorExpr>(op)) {
     return Context.getPointerType(op->getType());
   } else if (lval == Expr::LV_MemberFunction) {
index 2cf559858111839a8366347a75eb60c0b8fbefa2..68f0cc38301f2baa13ded24505e8f62e135a144a 100644 (file)
@@ -5311,25 +5311,25 @@ InitializedEntityOutlivesFullExpression(const InitializedEntity &Entity) {
 /// Determine the declaration which an initialized entity ultimately refers to,
 /// for the purpose of lifetime-extending a temporary bound to a reference in
 /// the initialization of \p Entity.
-static const ValueDecl *
-getDeclForTemporaryLifetimeExtension(const InitializedEntity &Entity,
-                                     const ValueDecl *FallbackDecl = 0) {
+static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
+    const InitializedEntity *Entity,
+    const InitializedEntity *FallbackDecl = 0) {
   // C++11 [class.temporary]p5:
-  switch (Entity.getKind()) {
+  switch (Entity->getKind()) {
   case InitializedEntity::EK_Variable:
     //   The temporary [...] persists for the lifetime of the reference
-    return Entity.getDecl();
+    return Entity;
 
   case InitializedEntity::EK_Member:
     // For subobjects, we look at the complete object.
-    if (Entity.getParent())
-      return getDeclForTemporaryLifetimeExtension(*Entity.getParent(),
-                                                  Entity.getDecl());
+    if (Entity->getParent())
+      return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
+                                                    Entity);
 
     //   except:
     //   -- A temporary bound to a reference member in a constructor's
     //      ctor-initializer persists until the constructor exits.
-    return Entity.getDecl();
+    return Entity;
 
   case InitializedEntity::EK_Parameter:
   case InitializedEntity::EK_Parameter_CF_Audited:
@@ -5344,7 +5344,7 @@ getDeclForTemporaryLifetimeExtension(const InitializedEntity &Entity,
     //   -- A temporary bound to a reference in a new-initializer persists
     //      until the completion of the full-expression containing the
     //      new-initializer.
-    return 0;
+    return nullptr;
 
   case InitializedEntity::EK_Temporary:
   case InitializedEntity::EK_CompoundLiteralInit:
@@ -5352,12 +5352,12 @@ getDeclForTemporaryLifetimeExtension(const InitializedEntity &Entity,
     // We don't yet know the storage duration of the surrounding temporary.
     // Assume it's got full-expression duration for now, it will patch up our
     // storage duration if that's not correct.
-    return 0;
+    return nullptr;
 
   case InitializedEntity::EK_ArrayElement:
     // For subobjects, we look at the complete object.
-    return getDeclForTemporaryLifetimeExtension(*Entity.getParent(),
-                                                FallbackDecl);
+    return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
+                                                  FallbackDecl);
 
   case InitializedEntity::EK_Base:
   case InitializedEntity::EK_Delegating:
@@ -5372,17 +5372,20 @@ getDeclForTemporaryLifetimeExtension(const InitializedEntity &Entity,
   case InitializedEntity::EK_Exception:
   case InitializedEntity::EK_VectorElement:
   case InitializedEntity::EK_ComplexElement:
-    return 0;
+    return nullptr;
   }
   llvm_unreachable("unknown entity kind");
 }
 
-static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD);
+static void performLifetimeExtension(Expr *Init,
+                                     const InitializedEntity *ExtendingEntity);
 
 /// Update a glvalue expression that is used as the initializer of a reference
 /// to note that its lifetime is extended.
 /// \return \c true if any temporary had its lifetime extended.
-static bool performReferenceExtension(Expr *Init, const ValueDecl *ExtendingD) {
+static bool
+performReferenceExtension(Expr *Init,
+                          const InitializedEntity *ExtendingEntity) {
   if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
     if (ILE->getNumInits() == 1 && ILE->isGLValue()) {
       // This is just redundant braces around an initializer. Step over it.
@@ -5416,8 +5419,9 @@ static bool performReferenceExtension(Expr *Init, const ValueDecl *ExtendingD) {
   if (MaterializeTemporaryExpr *ME = dyn_cast<MaterializeTemporaryExpr>(Init)) {
     // Update the storage duration of the materialized temporary.
     // FIXME: Rebuild the expression instead of mutating it.
-    ME->setExtendingDecl(ExtendingD);
-    performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingD);
+    ME->setExtendingDecl(ExtendingEntity->getDecl(),
+                         ExtendingEntity->allocateManglingNumber());
+    performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingEntity);
     return true;
   }
 
@@ -5426,7 +5430,8 @@ static bool performReferenceExtension(Expr *Init, const ValueDecl *ExtendingD) {
 
 /// Update a prvalue expression that is going to be materialized as a
 /// lifetime-extended temporary.
-static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) {
+static void performLifetimeExtension(Expr *Init,
+                                     const InitializedEntity *ExtendingEntity) {
   // Dig out the expression which constructs the extended temporary.
   SmallVector<const Expr *, 2> CommaLHSs;
   SmallVector<SubobjectAdjustment, 2> Adjustments;
@@ -5438,14 +5443,14 @@ static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) {
 
   if (CXXStdInitializerListExpr *ILE =
           dyn_cast<CXXStdInitializerListExpr>(Init)) {
-    performReferenceExtension(ILE->getSubExpr(), ExtendingD);
+    performReferenceExtension(ILE->getSubExpr(), ExtendingEntity);
     return;
   }
 
   if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
     if (ILE->getType()->isArrayType()) {
       for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
-        performLifetimeExtension(ILE->getInit(I), ExtendingD);
+        performLifetimeExtension(ILE->getInit(I), ExtendingEntity);
       return;
     }
 
@@ -5457,7 +5462,7 @@ static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) {
       // bound to temporaries, those temporaries are also lifetime-extended.
       if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
           ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
-        performReferenceExtension(ILE->getInit(0), ExtendingD);
+        performReferenceExtension(ILE->getInit(0), ExtendingEntity);
       else {
         unsigned Index = 0;
         for (const auto *I : RD->fields()) {
@@ -5467,13 +5472,13 @@ static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) {
             continue;
           Expr *SubInit = ILE->getInit(Index);
           if (I->getType()->isReferenceType())
-            performReferenceExtension(SubInit, ExtendingD);
+            performReferenceExtension(SubInit, ExtendingEntity);
           else if (isa<InitListExpr>(SubInit) ||
                    isa<CXXStdInitializerListExpr>(SubInit))
             // This may be either aggregate-initialization of a member or
             // initialization of a std::initializer_list object. Either way,
             // we should recursively lifetime-extend that initializer.
-            performLifetimeExtension(SubInit, ExtendingD);
+            performLifetimeExtension(SubInit, ExtendingEntity);
           ++Index;
         }
       }
@@ -5759,12 +5764,12 @@ InitializationSequence::Perform(Sema &S,
       // Even though we didn't materialize a temporary, the binding may still
       // extend the lifetime of a temporary. This happens if we bind a reference
       // to the result of a cast to reference type.
-      if (const ValueDecl *ExtendingDecl =
-              getDeclForTemporaryLifetimeExtension(Entity)) {
-        if (performReferenceExtension(CurInit.get(), ExtendingDecl))
-          warnOnLifetimeExtension(S, Entity, CurInit.get(), false,
-                                  ExtendingDecl);
-      }
+      if (const InitializedEntity *ExtendingEntity =
+              getEntityForTemporaryLifetimeExtension(&Entity))
+        if (performReferenceExtension(CurInit.get(), ExtendingEntity))
+          warnOnLifetimeExtension(S, Entity, CurInit.get(),
+                                  /*IsInitializerList=*/false,
+                                  ExtendingEntity->getDecl());
 
       break;
 
@@ -5776,19 +5781,18 @@ InitializationSequence::Perform(Sema &S,
       if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
         return ExprError();
 
-      // Maybe lifetime-extend the temporary's subobjects to match the
-      // entity's lifetime.
-      const ValueDecl *ExtendingDecl =
-          getDeclForTemporaryLifetimeExtension(Entity);
-      if (ExtendingDecl) {
-        performLifetimeExtension(CurInit.get(), ExtendingDecl);
-        warnOnLifetimeExtension(S, Entity, CurInit.get(), false, ExtendingDecl);
-      }
-
       // Materialize the temporary into memory.
       MaterializeTemporaryExpr *MTE = new (S.Context) MaterializeTemporaryExpr(
           Entity.getType().getNonReferenceType(), CurInit.get(),
-          Entity.getType()->isLValueReferenceType(), ExtendingDecl);
+          Entity.getType()->isLValueReferenceType());
+
+      // Maybe lifetime-extend the temporary's subobjects to match the
+      // entity's lifetime.
+      if (const InitializedEntity *ExtendingEntity =
+              getEntityForTemporaryLifetimeExtension(&Entity))
+        if (performReferenceExtension(MTE, ExtendingEntity))
+          warnOnLifetimeExtension(S, Entity, CurInit.get(), /*IsInitializerList=*/false,
+                                  ExtendingEntity->getDecl());
 
       // If we're binding to an Objective-C object that has lifetime, we
       // need cleanups. Likewise if we're extending this temporary to automatic
@@ -6176,19 +6180,19 @@ InitializationSequence::Perform(Sema &S,
              diag::warn_cxx98_compat_initializer_list_init)
         << CurInit.get()->getSourceRange();
 
-      // Maybe lifetime-extend the array temporary's subobjects to match the
-      // entity's lifetime.
-      const ValueDecl *ExtendingDecl =
-          getDeclForTemporaryLifetimeExtension(Entity);
-      if (ExtendingDecl) {
-        performLifetimeExtension(CurInit.get(), ExtendingDecl);
-        warnOnLifetimeExtension(S, Entity, CurInit.get(), true, ExtendingDecl);
-      }
-
       // Materialize the temporary into memory.
       MaterializeTemporaryExpr *MTE = new (S.Context)
           MaterializeTemporaryExpr(CurInit.get()->getType(), CurInit.get(),
-                                   /*lvalue reference*/ false, ExtendingDecl);
+                                   /*BoundToLvalueReference=*/false);
+
+      // Maybe lifetime-extend the array temporary's subobjects to match the
+      // entity's lifetime.
+      if (const InitializedEntity *ExtendingEntity =
+              getEntityForTemporaryLifetimeExtension(&Entity))
+        if (performReferenceExtension(MTE, ExtendingEntity))
+          warnOnLifetimeExtension(S, Entity, CurInit.get(),
+                                  /*IsInitializerList=*/true,
+                                  ExtendingEntity->getDecl());
 
       // Wrap it in a construction of a std::initializer_list<T>.
       CurInit = S.Owned(
index da652ff8e3f7d705513f69c08a984621d6022392..b42aa24cd7c1c7d1bf5358904f57f21ea7ced7aa 100644 (file)
@@ -1572,8 +1572,10 @@ void ASTStmtReader::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
 
 void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
   VisitExpr(E);
-  E->Temporary = Reader.ReadSubExpr();
-  E->ExtendingDecl = ReadDeclAs<ValueDecl>(Record, Idx);
+  E->State = Reader.ReadSubExpr();
+  auto VD = ReadDeclAs<ValueDecl>(Record, Idx);
+  unsigned ManglingNumber = Record[Idx++];
+  E->setExtendingDecl(VD, ManglingNumber);
 }
 
 void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
index 958620636ee3fd9de5d9cb707512e6ac6dbd8e07..2fcf5450a3c1606099b713456fd5ec165970ef1b 100644 (file)
@@ -1567,8 +1567,9 @@ void ASTStmtWriter::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
 
 void ASTStmtWriter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
   VisitExpr(E);
-  Writer.AddStmt(E->Temporary);
-  Writer.AddDeclRef(E->ExtendingDecl, Record);
+  Writer.AddStmt(E->getTemporary());
+  Writer.AddDeclRef(E->getExtendingDecl(), Record);
+  Record.push_back(E->getManglingNumber());
   Code = serialization::EXPR_MATERIALIZE_TEMPORARY;
 }
 
index 442cbbc92819cb159d2f3f5a6ef9ec876492c6b3..3f02bfec40ba1d289a54704f66c79b9abb77e31a 100644 (file)
@@ -54,16 +54,16 @@ namespace HiddenVariableTemplateWithConstRef {
   const int &use = i<void>;
 }
 
-// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE = linkonce_odr constant i32 1
-// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE2 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE1 = linkonce_odr constant i32 1
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE0 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE1 }
 // CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE3 = linkonce_odr constant i32 2
-// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE4 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE3 }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE2 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE3 }
 // CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE5 = linkonce_odr constant i32 3
-// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE6 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE5 }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE4 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE5 }
 // CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE7 = linkonce_odr constant i32 4
-// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE8 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE7 }
-// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE9 = linkonce_odr global {{.*}} { {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE2, {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE4, {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE6, {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE8 }
-// CHECK: @_ZN24VariableTemplateWithPack1pE = global {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE9
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE6 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE7 }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE = linkonce_odr global %"struct.VariableTemplateWithPack::S" { {{.*}}* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE0, {{.*}}* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE2, {{.*}}* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE4, {{.*}}* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE6 }
+// CHECK: @_ZN24VariableTemplateWithPack1pE = global {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE
 namespace VariableTemplateWithPack {
   struct A {
     const int &r;
index d36fe1cc60e5736a22f8b2520a2badd24ca1fc89..7fb33671e29fe3af3c6fac4ba02168cacedd8f29 100644 (file)
@@ -55,76 +55,76 @@ std::initializer_list<std::initializer_list<int>> nested = {
   {1, a}, {3, b}, {5, c}
 };
 
-// CHECK-STATIC-BL: @_ZGR6nested = private constant [2 x i32] [i32 1, i32 2], align 4
+// CHECK-STATIC-BL: @_ZGR6nested0 = private constant [2 x i32] [i32 1, i32 2], align 4
 // CHECK-STATIC-BL: @_ZGR6nested1 = private constant [2 x i32] [i32 3, i32 4], align 4
 // CHECK-STATIC-BL: @_ZGR6nested2 = private constant [2 x i32] [i32 5, i32 6], align 4
-// CHECK-STATIC-BL: @_ZGR6nested3 = private constant [3 x {{.*}}] [
-// CHECK-STATIC-BL:   {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested, i32 0, i32 0), i64 2 },
+// CHECK-STATIC-BL: @_ZGR6nested = private constant [3 x {{.*}}] [
+// CHECK-STATIC-BL:   {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0, i32 0, i32 0), i64 2 },
 // CHECK-STATIC-BL:   {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i32 0, i32 0), i64 2 },
 // CHECK-STATIC-BL:   {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i32 0, i32 0), i64 2 }
 // CHECK-STATIC-BL: ], align 8
-// CHECK-STATIC-BL: @nested = global {{.*}} { {{.*}} getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested3, i32 0, i32 0), i64 3 }, align 8
+// CHECK-STATIC-BL: @nested = global {{.*}} { {{.*}} getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i32 0, i32 0), i64 3 }, align 8
 
 // CHECK-DYNAMIC-BL: @nested = global
 // CHECK-DYNAMIC-BL: @_ZGR6nested = private global [3 x
+// CHECK-DYNAMIC-BL: @_ZGR6nested0 = private global [2 x i32] zeroinitializer
 // CHECK-DYNAMIC-BL: @_ZGR6nested1 = private global [2 x i32] zeroinitializer
 // CHECK-DYNAMIC-BL: @_ZGR6nested2 = private global [2 x i32] zeroinitializer
-// CHECK-DYNAMIC-BL: @_ZGR6nested3 = private global [2 x i32] zeroinitializer
-// CHECK-DYNAMIC-BL: store i32 1, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0)
-// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 1)
-// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0),
+// CHECK-DYNAMIC-BL: store i32 1, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0, i64 0, i64 0)
+// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0, i64 0, i64 1)
+// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0, i64 0, i64 0),
 // CHECK-DYNAMIC-BL:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 0), align 8
 // CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 1), align 8
-// CHECK-DYNAMIC-BL: store i32 3, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0)
-// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 1)
-// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0),
+// CHECK-DYNAMIC-BL: store i32 3, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0)
+// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 1)
+// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0),
 // CHECK-DYNAMIC-BL:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 0), align 8
 // CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 1), align 8
-// CHECK-DYNAMIC-BL: store i32 5, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0)
-// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 1)
-// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0),
+// CHECK-DYNAMIC-BL: store i32 5, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0)
+// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 1)
+// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0),
 // CHECK-DYNAMIC-BL:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 0), align 8
 // CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 1), align 8
 // CHECK-DYNAMIC-BL: store {{.*}}* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0),
 // CHECK-DYNAMIC-BL:       {{.*}}** getelementptr inbounds ({{.*}}* @nested, i32 0, i32 0), align 8
 // CHECK-DYNAMIC-BL: store i64 3, i64* getelementptr inbounds ({{.*}}* @nested, i32 0, i32 1), align 8
 
-// CHECK-STATIC-BE: @_ZGR6nested = private constant [2 x i32] [i32 1, i32 2], align 4
+// CHECK-STATIC-BE: @_ZGR6nested0 = private constant [2 x i32] [i32 1, i32 2], align 4
 // CHECK-STATIC-BE: @_ZGR6nested1 = private constant [2 x i32] [i32 3, i32 4], align 4
 // CHECK-STATIC-BE: @_ZGR6nested2 = private constant [2 x i32] [i32 5, i32 6], align 4
-// CHECK-STATIC-BE: @_ZGR6nested3 = private constant [3 x {{.*}}] [
-// CHECK-STATIC-BE:   {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested, i32 0, i32 0),
-// CHECK-STATIC-BE:            i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @_ZGR6nested to i8*), i64 8) to i32*) }
+// CHECK-STATIC-BE: @_ZGR6nested = private constant [3 x {{.*}}] [
+// CHECK-STATIC-BE:   {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0, i32 0, i32 0),
+// CHECK-STATIC-BE:            i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @_ZGR6nested0 to i8*), i64 8) to i32*) }
 // CHECK-STATIC-BE:   {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i32 0, i32 0),
 // CHECK-STATIC-BE:            i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @_ZGR6nested1 to i8*), i64 8) to i32*) }
 // CHECK-STATIC-BE:   {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i32 0, i32 0),
 // CHECK-STATIC-BE:            i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @_ZGR6nested2 to i8*), i64 8) to i32*) }
 // CHECK-STATIC-BE: ], align 8
-// CHECK-STATIC-BE: @nested = global {{.*}} { {{.*}} getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested3, i32 0, i32 0),
-// CHECK-STATIC-BE:                           {{.*}} bitcast ({{.*}}* getelementptr (i8* bitcast ([3 x {{.*}}]* @_ZGR6nested3 to i8*), i64 48) to {{.*}}*) }
+// CHECK-STATIC-BE: @nested = global {{.*}} { {{.*}} getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i32 0, i32 0),
+// CHECK-STATIC-BE:                           {{.*}} bitcast ({{.*}}* getelementptr (i8* bitcast ([3 x {{.*}}]* @_ZGR6nested to i8*), i64 48) to {{.*}}*) }
 
 // CHECK-DYNAMIC-BE: @nested = global
 // CHECK-DYNAMIC-BE: @_ZGR6nested = private global [3 x
+// CHECK-DYNAMIC-BE: @_ZGR6nested0 = private global [2 x i32] zeroinitializer
 // CHECK-DYNAMIC-BE: @_ZGR6nested1 = private global [2 x i32] zeroinitializer
 // CHECK-DYNAMIC-BE: @_ZGR6nested2 = private global [2 x i32] zeroinitializer
-// CHECK-DYNAMIC-BE: @_ZGR6nested3 = private global [2 x i32] zeroinitializer
-// CHECK-DYNAMIC-BE: store i32 1, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0)
+// CHECK-DYNAMIC-BE: store i32 1, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0, i64 0, i64 0)
+// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0, i64 0, i64 1)
+// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0, i64 0, i64 0),
+// CHECK-DYNAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 0), align 8
+// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0, i64 1, i64 0),
+// CHECK-DYNAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 1), align 8
+// CHECK-DYNAMIC-BE: store i32 3, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0)
 // CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 1)
 // CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0),
-// CHECK-DYNAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 0), align 8
+// CHECK-DYNAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 0), align 8
 // CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 1, i64 0),
-// CHECK-DYNAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 1), align 8
-// CHECK-DYNAMIC-BE: store i32 3, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0)
+// CHECK-DYNAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 1), align 8
+// CHECK-DYNAMIC-BE: store i32 5, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0)
 // CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 1)
 // CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0),
-// CHECK-DYNAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 0), align 8
-// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 1, i64 0),
-// CHECK-DYNAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 1), align 8
-// CHECK-DYNAMIC-BE: store i32 5, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0)
-// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 1)
-// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0),
 // CHECK-DYNAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 0), align 8
-// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 1, i64 0),
+// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 1, i64 0),
 // CHECK-DYNAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 1), align 8
 // CHECK-DYNAMIC-BE: store {{.*}}* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0),
 // CHECK-DYNAMIC-BE:       {{.*}}** getelementptr inbounds ({{.*}}* @nested, i32 0, i32 0), align 8