From: David Majnemer Date: Thu, 1 May 2014 17:50:17 +0000 (+0000) Subject: AST: Mangle reference temporaries reliably X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=781a1d06be959c6d64f33ff12f047cf4d13cb148;p=clang AST: Mangle reference temporaries reliably 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 --- diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index aff0021a77..2381fd9dbc 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -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 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() ? State.get() + : State.get()->Temporary; + } + /// \brief Retrieve the temporary-generating subexpression whose value will /// be materialized into a glvalue. - Expr *GetTemporaryExpr() const { return static_cast(Temporary); } + Expr *GetTemporaryExpr() const { return static_cast(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() ? nullptr + : State.get()->ExtendingDecl; + } + + void setExtendingDecl(const ValueDecl *ExtendedBy, unsigned ManglingNumber); - void setExtendingDecl(const ValueDecl *ExtendedBy) { - ExtendingDecl = ExtendedBy; + unsigned getManglingNumber() const { + return State.is() ? 0 : State.get()->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()) + return child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1); + + auto ES = State.get(); + return child_range(&ES->Temporary, &ES->Temporary + 1); + } }; } // end namespace clang diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h index 28bcd8b30b..483c1e67bd 100644 --- a/include/clang/AST/Mangle.h +++ b/include/clang/AST/Mangle.h @@ -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; diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index 83fb2be5f1..90618af090 100644 --- a/include/clang/Sema/Initialization.h +++ b/include/clang/Sema/Initialization.h @@ -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; diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index ee4992590a..0181235bff 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -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()) { + auto ES = new (ExtendedBy->getASTContext()) ExtraState; + ES->Temporary = State.get(); + State = ES; + } + + auto ES = State.get(); + ES->ExtendingDecl = ExtendedBy; + ES->ManglingNumber = ManglingNumber; +} + TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind, ArrayRef Args, SourceLocation RParenLoc, diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index f7dbf09d15..7105af2a76 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -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. // ::= GR 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, diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index edea497d99..b615c6f17f 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -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"); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 6103933300..ac97bdac60 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -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; diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index 33078b0e64..51a339581d 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -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; } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index b410efee3c..b28165b168 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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(op)) { return Context.getPointerType(op->getType()); } else if (lval == Expr::LV_MemberFunction) { diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 2cf5598581..68f0cc3830 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -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(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(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 CommaLHSs; SmallVector Adjustments; @@ -5438,14 +5443,14 @@ static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) { if (CXXStdInitializerListExpr *ILE = dyn_cast(Init)) { - performReferenceExtension(ILE->getSubExpr(), ExtendingD); + performReferenceExtension(ILE->getSubExpr(), ExtendingEntity); return; } if (InitListExpr *ILE = dyn_cast(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(SubInit) || isa(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. CurInit = S.Owned( diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index da652ff8e3..b42aa24cd7 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -1572,8 +1572,10 @@ void ASTStmtReader::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) { void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { VisitExpr(E); - E->Temporary = Reader.ReadSubExpr(); - E->ExtendingDecl = ReadDeclAs(Record, Idx); + E->State = Reader.ReadSubExpr(); + auto VD = ReadDeclAs(Record, Idx); + unsigned ManglingNumber = Record[Idx++]; + E->setExtendingDecl(VD, ManglingNumber); } void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) { diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 958620636e..2fcf5450a3 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -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; } diff --git a/test/CodeGenCXX/const-init-cxx1y.cpp b/test/CodeGenCXX/const-init-cxx1y.cpp index 442cbbc928..3f02bfec40 100644 --- a/test/CodeGenCXX/const-init-cxx1y.cpp +++ b/test/CodeGenCXX/const-init-cxx1y.cpp @@ -54,16 +54,16 @@ namespace HiddenVariableTemplateWithConstRef { const int &use = i; } -// 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; diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp index d36fe1cc60..7fb33671e2 100644 --- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp +++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp @@ -55,76 +55,76 @@ std::initializer_list> 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