From 08ea1ee2db5f9d6460fef1d79d0d1d1a5eb78982 Mon Sep 17 00:00:00 2001 From: Tyker Date: Sat, 16 Nov 2019 17:04:34 +0100 Subject: [PATCH] [NFC] Refactor representation of materialized temporaries Summary: this patch refactor representation of materialized temporaries to prevent an issue raised by rsmith in https://reviews.llvm.org/D63640#inline-612718 Reviewers: rsmith, martong, shafik Reviewed By: rsmith Subscribers: rnkovacs, arphaman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D69360 --- .../clang-tidy/abseil/StrCatAppendCheck.cpp | 2 +- .../clang-tidy/modernize/AvoidBindCheck.cpp | 2 +- .../clang-tidy/modernize/LoopConvertUtils.cpp | 2 +- .../performance/ImplicitConversionInLoopCheck.cpp | 2 +- .../readability/NonConstParameterCheck.cpp | 2 +- clang/include/clang/AST/ASTContext.h | 11 --- clang/include/clang/AST/DeclCXX.h | 74 ++++++++++++++ clang/include/clang/AST/ExprCXX.h | 106 ++++++++++----------- clang/include/clang/AST/RecursiveASTVisitor.h | 10 +- clang/include/clang/ASTMatchers/ASTMatchers.h | 4 +- clang/include/clang/Basic/DeclNodes.td | 1 + clang/include/clang/Sema/Template.h | 3 +- clang/include/clang/Serialization/ASTBitCodes.h | 3 + clang/lib/AST/ASTContext.cpp | 19 ---- clang/lib/AST/ASTImporter.cpp | 47 +++++++-- clang/lib/AST/DeclBase.cpp | 1 + clang/lib/AST/DeclCXX.cpp | 28 ++++++ clang/lib/AST/Expr.cpp | 34 +++---- clang/lib/AST/ExprCXX.cpp | 28 ++++-- clang/lib/AST/ExprConstant.cpp | 14 +-- clang/lib/AST/ItaniumMangle.cpp | 2 +- clang/lib/AST/StmtPrinter.cpp | 2 +- clang/lib/Analysis/CFG.cpp | 8 +- clang/lib/Analysis/Consumed.cpp | 2 +- clang/lib/Analysis/ThreadSafetyCommon.cpp | 3 +- clang/lib/CodeGen/CGDecl.cpp | 1 + clang/lib/CodeGen/CGExpr.cpp | 2 +- clang/lib/CodeGen/CGExprAgg.cpp | 2 +- clang/lib/CodeGen/CGExprConstant.cpp | 6 +- clang/lib/CodeGen/CodeGenModule.cpp | 4 +- clang/lib/Sema/JumpDiagnostics.cpp | 4 +- clang/lib/Sema/SemaChecking.cpp | 2 +- clang/lib/Sema/SemaExpr.cpp | 4 +- clang/lib/Sema/SemaInit.cpp | 9 +- clang/lib/Sema/SemaOpenMP.cpp | 2 +- clang/lib/Sema/SemaStmt.cpp | 4 +- clang/lib/Sema/TreeTransform.h | 4 +- clang/lib/Serialization/ASTCommon.cpp | 1 + clang/lib/Serialization/ASTReaderDecl.cpp | 14 +++ clang/lib/Serialization/ASTReaderStmt.cpp | 9 +- clang/lib/Serialization/ASTWriterDecl.cpp | 12 +++ clang/lib/Serialization/ASTWriterStmt.cpp | 8 +- .../StaticAnalyzer/Checkers/IteratorChecker.cpp | 3 +- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 2 +- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 2 +- clang/tools/libclang/CIndex.cpp | 1 + 46 files changed, 331 insertions(+), 175 deletions(-) diff --git a/clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp b/clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp index a249b12..0780924 100644 --- a/clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp @@ -24,7 +24,7 @@ AST_MATCHER_P(Stmt, IgnoringTemporaries, ast_matchers::internal::Matcher, const Stmt *E = &Node; while (true) { if (const auto *MTE = dyn_cast(E)) - E = MTE->getTemporary(); + E = MTE->getSubExpr(); if (const auto *BTE = dyn_cast(E)) E = BTE->getSubExpr(); if (const auto *ICE = dyn_cast(E)) diff --git a/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp b/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp index c51b6e8..2d4475c 100644 --- a/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp @@ -53,7 +53,7 @@ buildBindArguments(const MatchFinder::MatchResult &Result, const CallExpr *C) { const Expr *E = C->getArg(I); BindArgument B; if (const auto *M = dyn_cast(E)) { - const auto *TE = M->GetTemporaryExpr(); + const auto *TE = M->getSubExpr(); B.Kind = isa(TE) ? BK_CallExpr : BK_Temporary; } diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp index 03efd12..0389a61 100644 --- a/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp +++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp @@ -177,7 +177,7 @@ const Expr *digThroughConstructors(const Expr *E) { return nullptr; E = ConstructExpr->getArg(0); if (const auto *Temp = dyn_cast(E)) - E = Temp->GetTemporaryExpr(); + E = Temp->getSubExpr(); return digThroughConstructors(E); } return E; diff --git a/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp b/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp index e3b90d3..a520655 100644 --- a/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp @@ -78,7 +78,7 @@ void ImplicitConversionInLoopCheck::check( // iterator returns a value instead of a reference, and the loop variable // is a reference. This situation is fine (it probably produces the same // code at the end). - if (IsNonTrivialImplicitCast(Materialized->getTemporary())) + if (IsNonTrivialImplicitCast(Materialized->getSubExpr())) ReportAndFix(Result.Context, VD, OperatorCall); } diff --git a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp index 4372e74..878eab8 100644 --- a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp @@ -202,7 +202,7 @@ void NonConstParameterCheck::markCanNotBeConst(const Expr *E, } else if (const auto *Constr = dyn_cast(E)) { for (const auto *Arg : Constr->arguments()) { if (const auto *M = dyn_cast(Arg)) - markCanNotBeConst(cast(M->getTemporary()), CanNotBeConst); + markCanNotBeConst(cast(M->getSubExpr()), CanNotBeConst); } } else if (const auto *ILE = dyn_cast(E)) { for (unsigned I = 0U; I < ILE->getNumInits(); ++I) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 5e2f403..a048450 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -272,12 +272,6 @@ private: /// Mapping from __block VarDecls to BlockVarCopyInit. llvm::DenseMap BlockVarCopyInits; - /// Mapping from materialized temporaries with static storage duration - /// that appear in constant initializers to their evaluated values. These are - /// allocated in a std::map because their address must be stable. - llvm::DenseMap - MaterializedTemporaryValues; - /// Used to cleanups APValues stored in the AST. mutable llvm::SmallVector APValueCleanups; @@ -2827,11 +2821,6 @@ public: /// index of the parameter when it exceeds the size of the normal bitfield. unsigned getParameterIndex(const ParmVarDecl *D) const; - /// Get the storage for the constant value of a materialized temporary - /// of static storage duration. - APValue *getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E, - bool MayCreate); - /// Return a string representing the human readable name for the specified /// function declaration or file name. Used by SourceLocExpr and /// PredefinedExpr to cache evaluated results. diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 66212f7..19a62ac 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -3052,6 +3052,80 @@ public: static bool classofKind(Kind K) { return K == NamespaceAlias; } }; +/// Implicit declaration of a temporary that was materialized by +/// a MaterializeTemporaryExpr and lifetime-extended by a declaration +class LifetimeExtendedTemporaryDecl final : public Decl { + friend class MaterializeTemporaryExpr; + friend class ASTDeclReader; + + Stmt *ExprWithTemporary = nullptr; + + /// The declaration which lifetime-extended this reference, if any. + /// Either a VarDecl, or (for a ctor-initializer) a FieldDecl. + ValueDecl *ExtendingDecl = nullptr; + unsigned ManglingNumber; + + mutable APValue *Value = nullptr; + + virtual void anchor(); + + LifetimeExtendedTemporaryDecl(Expr *Temp, ValueDecl *EDecl, unsigned Mangling) + : Decl(Decl::LifetimeExtendedTemporary, EDecl->getDeclContext(), + EDecl->getLocation()), + ExprWithTemporary(Temp), ExtendingDecl(EDecl), + ManglingNumber(Mangling) {} + + LifetimeExtendedTemporaryDecl(EmptyShell) + : Decl(Decl::LifetimeExtendedTemporary, EmptyShell{}) {} + +public: + static LifetimeExtendedTemporaryDecl *Create(Expr *Temp, ValueDecl *EDec, + unsigned Mangling) { + return new (EDec->getASTContext(), EDec->getDeclContext()) + LifetimeExtendedTemporaryDecl(Temp, EDec, Mangling); + } + static LifetimeExtendedTemporaryDecl *CreateDeserialized(ASTContext &C, + unsigned ID) { + return new (C, ID) LifetimeExtendedTemporaryDecl(EmptyShell{}); + } + + ValueDecl *getExtendingDecl() { return ExtendingDecl; } + const ValueDecl *getExtendingDecl() const { return ExtendingDecl; } + + /// Retrieve the storage duration for the materialized temporary. + StorageDuration getStorageDuration() const; + + /// Retrieve the expression to which the temporary materialization conversion + /// was applied. This isn't necessarily the initializer of the temporary due + /// to the C++98 delayed materialization rules, but + /// skipRValueSubobjectAdjustments can be used to find said initializer within + /// the subexpression. + Expr *getTemporaryExpr() { return cast(ExprWithTemporary); } + const Expr *getTemporaryExpr() const { return cast(ExprWithTemporary); } + + unsigned getManglingNumber() const { return ManglingNumber; } + + /// Get the storage for the constant value of a materialized temporary + /// of static storage duration. + APValue *getOrCreateValue(bool MayCreate) const; + + APValue *getValue() const { return Value; } + + // Iterators + Stmt::child_range childrenExpr() { + return Stmt::child_range(&ExprWithTemporary, &ExprWithTemporary + 1); + } + + Stmt::const_child_range childrenExpr() const { + return Stmt::const_child_range(&ExprWithTemporary, &ExprWithTemporary + 1); + } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { + return K == Decl::LifetimeExtendedTemporary; + } +}; + /// Represents a shadow declaration introduced into a scope by a /// (resolved) using declaration. /// diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 2152e10..1eac1ce 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -4421,70 +4421,66 @@ private: friend class ASTStmtReader; friend class ASTStmtWriter; - struct ExtraState { - /// The temporary-generating expression whose value will be - /// materialized. - Stmt *Temporary; - - /// 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; + llvm::PointerUnion State; public: MaterializeTemporaryExpr(QualType T, Expr *Temporary, - bool BoundToLvalueReference) - : Expr(MaterializeTemporaryExprClass, T, - BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary, - Temporary->isTypeDependent(), Temporary->isValueDependent(), - Temporary->isInstantiationDependent(), - Temporary->containsUnexpandedParameterPack()), - State(Temporary) {} + bool BoundToLvalueReference, + LifetimeExtendedTemporaryDecl *MTD = nullptr); MaterializeTemporaryExpr(EmptyShell Empty) : Expr(MaterializeTemporaryExprClass, Empty) {} - Stmt *getTemporary() const { - return State.is() ? State.get() - : State.get()->Temporary; - } - /// Retrieve the temporary-generating subexpression whose value will /// be materialized into a glvalue. - Expr *GetTemporaryExpr() const { return static_cast(getTemporary()); } + Expr *getSubExpr() const { + return cast( + State.is() + ? State.get() + : State.get()->getTemporaryExpr()); + } /// 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 - // within a default initializer. - if (isa(ExtendingDecl)) - return SD_Automatic; - // FIXME: This only works because storage class specifiers are not allowed - // on decomposition declarations. - if (isa(ExtendingDecl)) - return ExtendingDecl->getDeclContext()->isFunctionOrMethod() - ? SD_Automatic - : SD_Static; - return cast(ExtendingDecl)->getStorageDuration(); + return State.is() ? SD_FullExpression + : State.get() + ->getStorageDuration(); + } + + /// Get the storage for the constant value of a materialized temporary + /// of static storage duration. + APValue *getOrCreateValue(bool MayCreate) const { + assert(State.is() && + "the temporary has not been lifetime extended"); + return State.get()->getOrCreateValue( + MayCreate); + } + + LifetimeExtendedTemporaryDecl *getLifetimeExtendedTemporaryDecl() { + return State.dyn_cast(); + } + const LifetimeExtendedTemporaryDecl * + getLifetimeExtendedTemporaryDecl() const { + return State.dyn_cast(); } /// Get the declaration which triggered the lifetime-extension of this /// temporary, if any. - const ValueDecl *getExtendingDecl() const { + ValueDecl *getExtendingDecl() { return State.is() ? nullptr - : State.get()->ExtendingDecl; + : State.get() + ->getExtendingDecl(); + } + const ValueDecl *getExtendingDecl() const { + return const_cast(this)->getExtendingDecl(); } - void setExtendingDecl(const ValueDecl *ExtendedBy, unsigned ManglingNumber); + void setExtendingDecl(ValueDecl *ExtendedBy, unsigned ManglingNumber); unsigned getManglingNumber() const { - return State.is() ? 0 : State.get()->ManglingNumber; + return State.is() ? 0 + : State.get() + ->getManglingNumber(); } /// Determine whether this materialized temporary is bound to an @@ -4494,11 +4490,11 @@ public: } SourceLocation getBeginLoc() const LLVM_READONLY { - return getTemporary()->getBeginLoc(); + return getSubExpr()->getBeginLoc(); } SourceLocation getEndLoc() const LLVM_READONLY { - return getTemporary()->getEndLoc(); + return getSubExpr()->getEndLoc(); } static bool classof(const Stmt *T) { @@ -4507,20 +4503,18 @@ public: // Iterators 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); + return State.is() + ? child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1) + : State.get()->childrenExpr(); } const_child_range children() const { - if (State.is()) - return const_child_range(State.getAddrOfPtr1(), - State.getAddrOfPtr1() + 1); - - auto ES = State.get(); - return const_child_range(&ES->Temporary, &ES->Temporary + 1); + return State.is() + ? const_child_range(State.getAddrOfPtr1(), + State.getAddrOfPtr1() + 1) + : const_cast( + State.get()) + ->childrenExpr(); } }; diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 9fea498..f1384e4 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -1435,6 +1435,10 @@ DEF_TRAVERSE_DECL(CapturedDecl, { DEF_TRAVERSE_DECL(EmptyDecl, {}) +DEF_TRAVERSE_DECL(LifetimeExtendedTemporaryDecl, { + TRY_TO(TraverseStmt(D->getTemporaryExpr())); +}) + DEF_TRAVERSE_DECL(FileScopeAsmDecl, { TRY_TO(TraverseStmt(D->getAsmString())); }) @@ -2632,10 +2636,14 @@ DEF_TRAVERSE_STMT(SizeOfPackExpr, {}) DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {}) DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {}) DEF_TRAVERSE_STMT(FunctionParmPackExpr, {}) -DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {}) DEF_TRAVERSE_STMT(CXXFoldExpr, {}) DEF_TRAVERSE_STMT(AtomicExpr, {}) +DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, { + if (S->getLifetimeExtendedTemporaryDecl()) + TRY_TO(TraverseLifetimeExtendedTemporaryDecl( + S->getLifetimeExtendedTemporaryDecl())); +}) // For coroutines expressions, traverse either the operand // as written or the implied calls, depending on what the // derived class requests. diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index e34b31c..72ae63f 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -6621,8 +6621,8 @@ AST_MATCHER_P(Expr, ignoringElidableConstructorCall, if (CtorExpr->isElidable()) { if (const auto *MaterializeTemp = dyn_cast(CtorExpr->getArg(0))) { - return InnerMatcher.matches(*MaterializeTemp->GetTemporaryExpr(), - Finder, Builder); + return InnerMatcher.matches(*MaterializeTemp->getSubExpr(), Finder, + Builder); } } } diff --git a/clang/include/clang/Basic/DeclNodes.td b/clang/include/clang/Basic/DeclNodes.td index fa4d1b4..25d49fc 100644 --- a/clang/include/clang/Basic/DeclNodes.td +++ b/clang/include/clang/Basic/DeclNodes.td @@ -100,4 +100,5 @@ def OMPThreadPrivate : DeclNode; def OMPAllocate : DeclNode; def OMPRequires : DeclNode; def Empty : DeclNode; +def LifetimeExtendedTemporary : DeclNode; diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h index 68c8c83..54c01c7 100644 --- a/clang/include/clang/Sema/Template.h +++ b/clang/include/clang/Sema/Template.h @@ -464,8 +464,9 @@ class VarDecl; #define OBJCPROPERTY(DERIVED, BASE) #define OBJCPROPERTYIMPL(DERIVED, BASE) #define EMPTY(DERIVED, BASE) +#define LIFETIMEEXTENDEDTEMPORARY(DERIVED, BASE) -// Decls which use special-case instantiation code. + // Decls which use special-case instantiation code. #define BLOCK(DERIVED, BASE) #define CAPTURED(DERIVED, BASE) #define IMPLICITPARAM(DERIVED, BASE) diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 5250497..b1986b2 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1537,6 +1537,9 @@ namespace serialization { /// An EmptyDecl record. DECL_EMPTY, + /// An LifetimeExtendedTemporaryDecl record. + DECL_LIFETIME_EXTENDED_TEMPORARY, + /// An ObjCTypeParamDecl record. DECL_OBJC_TYPE_PARAM, diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index cda51ec..752c100 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -875,10 +875,6 @@ ASTContext::~ASTContext() { A != AEnd; ++A) A->second->~AttrVec(); - for (std::pair &MTVPair : - MaterializedTemporaryValues) - MTVPair.second->~APValue(); - for (const auto &Value : ModuleInitializers) Value.second->~PerModuleInitializers(); @@ -10324,21 +10320,6 @@ unsigned ASTContext::getParameterIndex(const ParmVarDecl *D) const { return I->second; } -APValue * -ASTContext::getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E, - bool MayCreate) { - assert(E && E->getStorageDuration() == SD_Static && - "don't need to cache the computed value for this temporary"); - if (MayCreate) { - APValue *&MTVI = MaterializedTemporaryValues[E]; - if (!MTVI) - MTVI = new (*this) APValue; - return MTVI; - } - - return MaterializedTemporaryValues.lookup(E); -} - QualType ASTContext::getStringLiteralArrayType(QualType EltTy, unsigned Length) const { // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 7034f41..7614da1 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -485,6 +485,8 @@ namespace clang { ExpectedDecl VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); ExpectedDecl VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); ExpectedDecl VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D); + ExpectedDecl + VisitLifetimeExtendedTemporaryDecl(LifetimeExtendedTemporaryDecl *D); Expected ImportObjCTypeParamList(ObjCTypeParamList *list); @@ -7007,23 +7009,52 @@ ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { E->requiresZeroInitialization()); } +ExpectedDecl ASTNodeImporter::VisitLifetimeExtendedTemporaryDecl( + LifetimeExtendedTemporaryDecl *D) { + DeclContext *DC, *LexicalDC; + if (Error Err = ImportDeclContext(D, DC, LexicalDC)) + return std::move(Err); + + auto Imp = importSeq(D->getTemporaryExpr(), D->getExtendingDecl()); + // FIXME: the APValue should be imported as well if present. + if (!Imp) + return Imp.takeError(); + + Expr *Temporary; + ValueDecl *ExtendingDecl; + std::tie(Temporary, ExtendingDecl) = *Imp; + // FIXME: Should ManglingNumber get numbers associated with 'to' context? + + LifetimeExtendedTemporaryDecl *To; + if (GetImportedOrCreateDecl(To, D, Temporary, ExtendingDecl, + D->getManglingNumber())) + return To; + + To->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(To); + return To; +} + ExpectedStmt ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { - auto Imp = importSeq( - E->getType(), E->GetTemporaryExpr(), E->getExtendingDecl()); + auto Imp = importSeq(E->getType(), + E->getLifetimeExtendedTemporaryDecl() ? nullptr + : E->getSubExpr(), + E->getLifetimeExtendedTemporaryDecl()); if (!Imp) return Imp.takeError(); QualType ToType; Expr *ToTemporaryExpr; - const ValueDecl *ToExtendingDecl; - std::tie(ToType, ToTemporaryExpr, ToExtendingDecl) = *Imp; + LifetimeExtendedTemporaryDecl *ToMaterializedDecl; + std::tie(ToType, ToTemporaryExpr, ToMaterializedDecl) = *Imp; + if (!ToTemporaryExpr) + ToTemporaryExpr = cast(ToMaterializedDecl->getTemporaryExpr()); - auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr( - ToType, ToTemporaryExpr, E->isBoundToLvalueReference()); + auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr( + ToType, ToTemporaryExpr, E->isBoundToLvalueReference(), + ToMaterializedDecl); - // FIXME: Should ManglingNumber get numbers associated with 'to' context? - ToMTE->setExtendingDecl(ToExtendingDecl, E->getManglingNumber()); return ToMTE; } diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 77a3a4c..6ee767c 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -803,6 +803,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case OMPRequires: case OMPCapturedExpr: case Empty: + case LifetimeExtendedTemporary: // Never looked up by name. return 0; } diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 58b50de..bca560c 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -2796,6 +2796,34 @@ NamespaceAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { SourceLocation(), nullptr); } +void LifetimeExtendedTemporaryDecl::anchor() {} + +/// Retrieve the storage duration for the materialized temporary. +StorageDuration LifetimeExtendedTemporaryDecl::getStorageDuration() const { + const ValueDecl *ExtendingDecl = getExtendingDecl(); + if (!ExtendingDecl) + return SD_FullExpression; + // FIXME: This is not necessarily correct for a temporary materialized + // within a default initializer. + if (isa(ExtendingDecl)) + return SD_Automatic; + // FIXME: This only works because storage class specifiers are not allowed + // on decomposition declarations. + if (isa(ExtendingDecl)) + return ExtendingDecl->getDeclContext()->isFunctionOrMethod() ? SD_Automatic + : SD_Static; + return cast(ExtendingDecl)->getStorageDuration(); +} + +APValue *LifetimeExtendedTemporaryDecl::getOrCreateValue(bool MayCreate) const { + assert(getStorageDuration() == SD_Static && + "don't need to cache the computed value for this temporary"); + if (MayCreate && !Value) + Value = (new (getASTContext()) APValue); + assert(Value && "may not be null"); + return Value; +} + void UsingShadowDecl::anchor() {} UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC, diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 3438c3a..c465f9d 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -49,7 +49,7 @@ const Expr *Expr::getBestDynamicClassTypeExpr() const { // Step into initializer for materialized temporaries. if (auto *MTE = dyn_cast(E)) { - E = MTE->GetTemporaryExpr(); + E = MTE->getSubExpr(); continue; } @@ -1891,7 +1891,7 @@ namespace { const Expr *skipImplicitTemporary(const Expr *E) { // Skip through reference binding to temporary. if (auto *Materialize = dyn_cast(E)) - E = Materialize->GetTemporaryExpr(); + E = Materialize->getSubExpr(); // Skip any temporary bindings; they're implicit. if (auto *Binder = dyn_cast(E)) @@ -2721,8 +2721,9 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, case CXXDeleteExprClass: return false; case MaterializeTemporaryExprClass: - return cast(this)->GetTemporaryExpr() - ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); + return cast(this) + ->getSubExpr() + ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); case CXXBindTemporaryExprClass: return cast(this)->getSubExpr() ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); @@ -2746,8 +2747,8 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const { case ImplicitCastExprClass: return cast(E)->getSubExpr()->isOBJCGCCandidate(Ctx); case MaterializeTemporaryExprClass: - return cast(E)->GetTemporaryExpr() - ->isOBJCGCCandidate(Ctx); + return cast(E)->getSubExpr()->isOBJCGCCandidate( + Ctx); case CStyleCastExprClass: return cast(E)->getSubExpr()->isOBJCGCCandidate(Ctx); case DeclRefExprClass: { @@ -2822,7 +2823,7 @@ static Expr *IgnoreImpCastsExtraSingleStep(Expr *E) { return SubE; if (auto *MTE = dyn_cast(E)) - return MTE->GetTemporaryExpr(); + return MTE->getSubExpr(); if (auto *NTTP = dyn_cast(E)) return NTTP->getReplacement(); @@ -2838,7 +2839,7 @@ static Expr *IgnoreCastsSingleStep(Expr *E) { return FE->getSubExpr(); if (auto *MTE = dyn_cast(E)) - return MTE->GetTemporaryExpr(); + return MTE->getSubExpr(); if (auto *NTTP = dyn_cast(E)) return NTTP->getReplacement(); @@ -2872,7 +2873,7 @@ static Expr *IgnoreImplicitSingleStep(Expr *E) { return SubE; if (auto *MTE = dyn_cast(E)) - return MTE->GetTemporaryExpr(); + return MTE->getSubExpr(); if (auto *BTE = dyn_cast(E)) return BTE->getSubExpr(); @@ -2999,7 +3000,7 @@ Expr *Expr::IgnoreParenNoopCasts(const ASTContext &Ctx) { bool Expr::isDefaultArgument() const { const Expr *E = this; if (const MaterializeTemporaryExpr *M = dyn_cast(E)) - E = M->GetTemporaryExpr(); + E = M->getSubExpr(); while (const ImplicitCastExpr *ICE = dyn_cast(E)) E = ICE->getSubExprAsWritten(); @@ -3011,7 +3012,7 @@ bool Expr::isDefaultArgument() const { /// expressions. static const Expr *skipTemporaryBindingsNoOpCastsAndParens(const Expr *E) { if (const MaterializeTemporaryExpr *M = dyn_cast(E)) - E = M->GetTemporaryExpr(); + E = M->getSubExpr(); while (const ImplicitCastExpr *ICE = dyn_cast(E)) { if (ICE->getCastKind() == CK_NoOp) @@ -3106,7 +3107,7 @@ bool Expr::isImplicitCXXThis() const { if (const MaterializeTemporaryExpr *M = dyn_cast(E)) { - E = M->GetTemporaryExpr(); + E = M->getSubExpr(); continue; } @@ -3283,8 +3284,9 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, break; } case MaterializeTemporaryExprClass: - return cast(this)->GetTemporaryExpr() - ->isConstantInitializer(Ctx, false, Culprit); + return cast(this) + ->getSubExpr() + ->isConstantInitializer(Ctx, false, Culprit); case SubstNonTypeTemplateParmExprClass: return cast(this)->getReplacement() @@ -3751,7 +3753,7 @@ Expr::isNullPointerConstant(ASTContext &Ctx, return NPCK_GNUNull; } else if (const MaterializeTemporaryExpr *M = dyn_cast(this)) { - return M->GetTemporaryExpr()->isNullPointerConstant(Ctx, NPC); + return M->getSubExpr()->isNullPointerConstant(Ctx, NPC); } else if (const OpaqueValueExpr *OVE = dyn_cast(this)) { if (const Expr *Source = OVE->getSourceExpr()) return Source->isNullPointerConstant(Ctx, NPC); @@ -4460,7 +4462,7 @@ const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) { if (const ExprWithCleanups *ewc = dyn_cast(e)) e = ewc->getSubExpr(); if (const MaterializeTemporaryExpr *m = dyn_cast(e)) - e = m->GetTemporaryExpr(); + e = m->getSubExpr(); e = cast(e)->getArg(0); while (const ImplicitCastExpr *ice = dyn_cast(e)) e = ice->getSubExpr(); diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 904928b..0fb132d 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -1653,7 +1653,23 @@ FunctionParmPackExpr::CreateEmpty(const ASTContext &Context, FunctionParmPackExpr(QualType(), nullptr, SourceLocation(), 0, nullptr); } -void MaterializeTemporaryExpr::setExtendingDecl(const ValueDecl *ExtendedBy, +MaterializeTemporaryExpr::MaterializeTemporaryExpr( + QualType T, Expr *Temporary, bool BoundToLvalueReference, + LifetimeExtendedTemporaryDecl *MTD) + : Expr(MaterializeTemporaryExprClass, T, + BoundToLvalueReference ? VK_LValue : VK_XValue, OK_Ordinary, + Temporary->isTypeDependent(), Temporary->isValueDependent(), + Temporary->isInstantiationDependent(), + Temporary->containsUnexpandedParameterPack()) { + if (MTD) { + State = MTD; + MTD->ExprWithTemporary = Temporary; + return; + } + State = Temporary; +} + +void MaterializeTemporaryExpr::setExtendingDecl(ValueDecl *ExtendedBy, unsigned ManglingNumber) { // We only need extra state if we have to remember more than just the Stmt. if (!ExtendedBy) @@ -1661,13 +1677,11 @@ void MaterializeTemporaryExpr::setExtendingDecl(const ValueDecl *ExtendedBy, // 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; - } + if (!State.is()) + State = LifetimeExtendedTemporaryDecl::Create( + cast(State.get()), ExtendedBy, ManglingNumber); - auto ES = State.get(); + auto ES = State.get(); ES->ExtendingDecl = ExtendedBy; ES->ManglingNumber = ManglingNumber; } diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index f4ca228..7965926 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -107,7 +107,7 @@ namespace { dyn_cast(Base)) { SmallVector CommaLHSs; SmallVector Adjustments; - const Expr *Temp = MTE->GetTemporaryExpr(); + const Expr *Temp = MTE->getSubExpr(); const Expr *Inner = Temp->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); // Keep any cv-qualifiers from the reference if we generated a temporary @@ -2075,7 +2075,7 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, return false; } - APValue *V = Info.Ctx.getMaterializedTemporaryValue(MTE, false); + APValue *V = MTE->getOrCreateValue(false); assert(V && "evasluation result refers to uninitialised temporary"); if (!CheckEvaluationResult(CheckEvaluationResultKind::ConstantExpression, Info, MTE->getExprLoc(), TempType, *V, @@ -3679,7 +3679,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, return CompleteObject(); } - BaseVal = Info.Ctx.getMaterializedTemporaryValue(MTE, false); + BaseVal = MTE->getOrCreateValue(false); assert(BaseVal && "got reference to unevaluated temporary"); } else { if (!IsAccess) @@ -7470,8 +7470,8 @@ bool LValueExprEvaluator::VisitMaterializeTemporaryExpr( // Walk through the expression to find the materialized temporary itself. SmallVector CommaLHSs; SmallVector Adjustments; - const Expr *Inner = E->GetTemporaryExpr()-> - skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); + const Expr *Inner = + E->getSubExpr()->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); // If we passed any comma operators, evaluate their LHSs. for (unsigned I = 0, N = CommaLHSs.size(); I != N; ++I) @@ -7483,7 +7483,7 @@ bool LValueExprEvaluator::VisitMaterializeTemporaryExpr( // value for use outside this evaluation. APValue *Value; if (E->getStorageDuration() == SD_Static) { - Value = Info.Ctx.getMaterializedTemporaryValue(E, true); + Value = E->getOrCreateValue(true); *Value = APValue(); Result.set(E); } else { @@ -9031,7 +9031,7 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, if (E->isElidable() && !ZeroInit) if (const MaterializeTemporaryExpr *ME = dyn_cast(E->getArg(0))) - return Visit(ME->GetTemporaryExpr()); + return Visit(ME->getSubExpr()); if (ZeroInit && !ZeroInitialization(E, T)) return false; diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index c55a901..8c87c55 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -4338,7 +4338,7 @@ recurse: } case Expr::MaterializeTemporaryExprClass: { - mangleExpression(cast(E)->GetTemporaryExpr()); + mangleExpression(cast(E)->getSubExpr()); break; } diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 1602ef5..1ef847a 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -2235,7 +2235,7 @@ void StmtPrinter::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) { } void StmtPrinter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *Node){ - PrintExpr(Node->GetTemporaryExpr()); + PrintExpr(Node->getSubExpr()); } void StmtPrinter::VisitCXXFoldExpr(CXXFoldExpr *E) { diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index a533a8d..762b8ec 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -1428,7 +1428,7 @@ void CFGBuilder::findConstructionContexts( if (Layer->getItem().getKind() == ConstructionContextItem::ElidableConstructorKind) { auto *MTE = cast(Child); - findConstructionContexts(withExtraLayer(MTE), MTE->GetTemporaryExpr()); + findConstructionContexts(withExtraLayer(MTE), MTE->getSubExpr()); } break; } @@ -1694,7 +1694,7 @@ static QualType getReferenceInitTemporaryType(const Expr *Init, // Skip through the temporary-materialization expression. if (const MaterializeTemporaryExpr *MTE = dyn_cast(Init)) { - Init = MTE->GetTemporaryExpr(); + Init = MTE->getSubExpr(); if (FoundMTE) *FoundMTE = true; continue; @@ -3462,7 +3462,7 @@ CFGBuilder::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE, AddStmtChoice asc) { findConstructionContexts( ConstructionContextLayer::create(cfg->getBumpVectorContext(), MTE), - MTE->getTemporary()); + MTE->getSubExpr()); return VisitStmt(MTE, asc); } @@ -4649,7 +4649,7 @@ tryAgain: // Find the expression whose lifetime needs to be extended. E = const_cast( cast(E) - ->GetTemporaryExpr() + ->getSubExpr() ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments)); // Visit the skipped comma operator left-hand sides for other temporaries. for (const Expr *CommaLHS : CommaLHSs) { diff --git a/clang/lib/Analysis/Consumed.cpp b/clang/lib/Analysis/Consumed.cpp index cde753e..9560248 100644 --- a/clang/lib/Analysis/Consumed.cpp +++ b/clang/lib/Analysis/Consumed.cpp @@ -847,7 +847,7 @@ void ConsumedStmtVisitor::VisitDeclStmt(const DeclStmt *DeclS) { void ConsumedStmtVisitor::VisitMaterializeTemporaryExpr( const MaterializeTemporaryExpr *Temp) { - forwardInfo(Temp->GetTemporaryExpr(), Temp); + forwardInfo(Temp->getSubExpr(), Temp); } void ConsumedStmtVisitor::VisitMemberExpr(const MemberExpr *MExpr) { diff --git a/clang/lib/Analysis/ThreadSafetyCommon.cpp b/clang/lib/Analysis/ThreadSafetyCommon.cpp index 373dfc7..1b8c55e 100644 --- a/clang/lib/Analysis/ThreadSafetyCommon.cpp +++ b/clang/lib/Analysis/ThreadSafetyCommon.cpp @@ -244,8 +244,7 @@ til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) { case Stmt::CXXBindTemporaryExprClass: return translate(cast(S)->getSubExpr(), Ctx); case Stmt::MaterializeTemporaryExprClass: - return translate(cast(S)->GetTemporaryExpr(), - Ctx); + return translate(cast(S)->getSubExpr(), Ctx); // Collect all literals case Stmt::CharacterLiteralClass: diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 563841c0..f60628b 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -109,6 +109,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::OMPRequires: case Decl::Empty: case Decl::Concept: + case Decl::LifetimeExtendedTemporary: // None of these decls require codegen support. return; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 384e8f7..214378a96 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -417,7 +417,7 @@ static Address createReferenceTemporary(CodeGenFunction &CGF, LValue CodeGenFunction:: EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) { - const Expr *E = M->GetTemporaryExpr(); + const Expr *E = M->getSubExpr(); assert((!M->getExtendingDecl() || !isa(M->getExtendingDecl()) || !cast(M->getExtendingDecl())->isARCPseudoStrong()) && diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 2f0e493..7e69f63 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -637,7 +637,7 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, //===----------------------------------------------------------------------===// void AggExprEmitter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E){ - Visit(E->GetTemporaryExpr()); + Visit(E->getSubExpr()); } void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) { diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 96e8c9c..9198d7a 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1173,7 +1173,7 @@ public: llvm::Constant *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E, QualType T) { - return Visit(E->GetTemporaryExpr(), T); + return Visit(E->getSubExpr(), T); } llvm::Constant *EmitArrayInitialization(InitListExpr *ILE, QualType T) { @@ -2003,8 +2003,8 @@ ConstantLValueEmitter::VisitMaterializeTemporaryExpr( assert(E->getStorageDuration() == SD_Static); SmallVector CommaLHSs; SmallVector Adjustments; - const Expr *Inner = E->GetTemporaryExpr() - ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); + const Expr *Inner = + E->getSubExpr()->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); return CGM.GetAddrOfGlobalTemporary(E, Inner); } diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index e253bbc..768361d 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -5011,7 +5011,7 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( // If we're not materializing a subobject of the temporary, keep the // cv-qualifiers from the type of the MaterializeTemporaryExpr. QualType MaterializedType = Init->getType(); - if (Init == E->GetTemporaryExpr()) + if (Init == E->getSubExpr()) MaterializedType = E->getType(); CharUnits Align = getContext().getTypeAlignInChars(MaterializedType); @@ -5034,7 +5034,7 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( // temporary. Note that this might have a different value from the value // computed by evaluating the initializer if the surrounding constant // expression modifies the temporary. - Value = getContext().getMaterializedTemporaryValue(E, false); + Value = E->getOrCreateValue(false); } // Try evaluating it now, it might have a constant initializer. diff --git a/clang/lib/Sema/JumpDiagnostics.cpp b/clang/lib/Sema/JumpDiagnostics.cpp index c8743df..960e62d 100644 --- a/clang/lib/Sema/JumpDiagnostics.cpp +++ b/clang/lib/Sema/JumpDiagnostics.cpp @@ -546,8 +546,8 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, SmallVector CommaLHS; SmallVector Adjustments; const Expr *ExtendedObject = - MTE->GetTemporaryExpr()->skipRValueSubobjectAdjustments( - CommaLHS, Adjustments); + MTE->getSubExpr()->skipRValueSubobjectAdjustments(CommaLHS, + Adjustments); if (ExtendedObject->getType().isDestructedType()) { Scopes.push_back(GotoScope(ParentScope, 0, diag::note_exits_temporary_dtor, diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 806df77..65e4112d 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -9270,7 +9270,7 @@ void Sema::CheckMaxUnsignedZero(const CallExpr *Call, auto IsLiteralZeroArg = [](const Expr* E) -> bool { const auto *MTE = dyn_cast(E); if (!MTE) return false; - const auto *Num = dyn_cast(MTE->GetTemporaryExpr()); + const auto *Num = dyn_cast(MTE->getSubExpr()); if (!Num) return false; if (Num->getValue() != 0) return false; return true; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 76f500f..ea4321c 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7646,7 +7646,7 @@ static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode, E = E->IgnoreConversionOperator(); E = E->IgnoreImpCasts(); if (auto *MTE = dyn_cast(E)) { - E = MTE->GetTemporaryExpr(); + E = MTE->getSubExpr(); E = E->IgnoreImpCasts(); } @@ -8702,7 +8702,7 @@ namespace { struct OriginalOperand { explicit OriginalOperand(Expr *Op) : Orig(Op), Conversion(nullptr) { if (auto *MTE = dyn_cast(Op)) - Op = MTE->GetTemporaryExpr(); + Op = MTE->getSubExpr(); if (auto *BTE = dyn_cast(Op)) Op = BTE->getSubExpr(); if (auto *ICE = dyn_cast(Op)) { diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 1296e76..80d7cfe 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -6946,8 +6946,8 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, if (auto *MTE = dyn_cast(Init)) { if (Visit(Path, Local(MTE), RK)) - visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(), Visit, - true, EnableLifetimeWarnings); + visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(), Visit, true, + EnableLifetimeWarnings); } if (isa(Init)) { @@ -7067,9 +7067,8 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, } } else if (auto *MTE = dyn_cast(L)) { if (MTE->getType().isConstQualified()) - visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(), - Visit, true, - EnableLifetimeWarnings); + visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(), Visit, + true, EnableLifetimeWarnings); } return false; }, EnableLifetimeWarnings); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 50dd31a..d039dac 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -907,7 +907,7 @@ static const Expr *getExprAsWritten(const Expr *E) { E = FE->getSubExpr(); if (const auto *MTE = dyn_cast(E)) - E = MTE->GetTemporaryExpr(); + E = MTE->getSubExpr(); while (const auto *Binder = dyn_cast(E)) E = Binder->getSubExpr(); diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 9680720..05f7b30 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -2724,7 +2724,7 @@ static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef, if (!MTE) return; - const Expr *E = MTE->GetTemporaryExpr()->IgnoreImpCasts(); + const Expr *E = MTE->getSubExpr()->IgnoreImpCasts(); // Searching for either UnaryOperator for dereference of a pointer or // CXXOperatorCallExpr for handling iterators. @@ -2736,7 +2736,7 @@ static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef, E = ME->getBase(); } else { const MaterializeTemporaryExpr *MTE = cast(E); - E = MTE->GetTemporaryExpr(); + E = MTE->getSubExpr(); } E = E->IgnoreImpCasts(); } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 0cd8abd..28c5738 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -3470,7 +3470,7 @@ ExprResult TreeTransform::TransformInitializer(Expr *Init, Init = AIL->getCommonExpr(); if (MaterializeTemporaryExpr *MTE = dyn_cast(Init)) - Init = MTE->GetTemporaryExpr(); + Init = MTE->getSubExpr(); while (CXXBindTemporaryExpr *Binder = dyn_cast(Init)) Init = Binder->getSubExpr(); @@ -12180,7 +12180,7 @@ template ExprResult TreeTransform::TransformMaterializeTemporaryExpr( MaterializeTemporaryExpr *E) { - return getDerived().TransformExpr(E->GetTemporaryExpr()); + return getDerived().TransformExpr(E->getSubExpr()); } template diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp index dd06e05..cdb5b17 100644 --- a/clang/lib/Serialization/ASTCommon.cpp +++ b/clang/lib/Serialization/ASTCommon.cpp @@ -401,6 +401,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) { case Decl::Decomposition: case Decl::Binding: case Decl::Concept: + case Decl::LifetimeExtendedTemporary: return false; // These indirectly derive from Redeclarable but are not actually diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 21d3da9..9f799e3 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -405,6 +405,7 @@ namespace clang { void VisitBlockDecl(BlockDecl *BD); void VisitCapturedDecl(CapturedDecl *CD); void VisitEmptyDecl(EmptyDecl *D); + void VisitLifetimeExtendedTemporaryDecl(LifetimeExtendedTemporaryDecl *D); std::pair VisitDeclContext(DeclContext *DC); @@ -2349,6 +2350,16 @@ void ASTDeclReader::VisitEmptyDecl(EmptyDecl *D) { VisitDecl(D); } +void ASTDeclReader::VisitLifetimeExtendedTemporaryDecl( + LifetimeExtendedTemporaryDecl *D) { + VisitDecl(D); + D->ExtendingDecl = ReadDeclAs(); + D->ExprWithTemporary = Record.readStmt(); + if (Record.readInt()) + D->Value = new (D->getASTContext()) APValue(Record.readAPValue()); + D->ManglingNumber = Record.readInt(); +} + std::pair ASTDeclReader::VisitDeclContext(DeclContext *DC) { uint64_t LexicalOffset = ReadLocalOffset(); @@ -3887,6 +3898,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_EMPTY: D = EmptyDecl::CreateDeserialized(Context, ID); break; + case DECL_LIFETIME_EXTENDED_TEMPORARY: + D = LifetimeExtendedTemporaryDecl::CreateDeserialized(Context, ID); + break; case DECL_OBJC_TYPE_PARAM: D = ObjCTypeParamDecl::CreateDeserialized(Context, ID); break; diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 3fd9fff..8837396 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1900,10 +1900,11 @@ void ASTStmtReader::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) { void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { VisitExpr(E); - E->State = Record.readSubExpr(); - auto *VD = ReadDeclAs(); - unsigned ManglingNumber = Record.readInt(); - E->setExtendingDecl(VD, ManglingNumber); + bool HasMaterialzedDecl = Record.readInt(); + if (HasMaterialzedDecl) + E->State = cast(Record.readDecl()); + else + E->State = Record.readSubExpr(); } void ASTStmtReader::VisitCXXFoldExpr(CXXFoldExpr *E) { diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index b9ee8e8..51902a6 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -124,6 +124,7 @@ namespace clang { void VisitBlockDecl(BlockDecl *D); void VisitCapturedDecl(CapturedDecl *D); void VisitEmptyDecl(EmptyDecl *D); + void VisitLifetimeExtendedTemporaryDecl(LifetimeExtendedTemporaryDecl *D); void VisitDeclContext(DeclContext *DC); template void VisitRedeclarable(Redeclarable *D); @@ -1134,6 +1135,17 @@ void ASTDeclWriter::VisitEmptyDecl(EmptyDecl *D) { Code = serialization::DECL_EMPTY; } +void ASTDeclWriter::VisitLifetimeExtendedTemporaryDecl( + LifetimeExtendedTemporaryDecl *D) { + VisitDecl(D); + Record.AddDeclRef(D->getExtendingDecl()); + Record.AddStmt(D->getTemporaryExpr()); + Record.push_back(static_cast(D->getValue())); + if (D->getValue()) + Record.AddAPValue(*D->getValue()); + Record.push_back(D->getManglingNumber()); + Code = serialization::DECL_LIFETIME_EXTENDED_TEMPORARY; +} void ASTDeclWriter::VisitBlockDecl(BlockDecl *D) { VisitDecl(D); Record.AddStmt(D->getBody()); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 6f4abc4..e66db43 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1835,9 +1835,11 @@ void ASTStmtWriter::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) { void ASTStmtWriter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { VisitExpr(E); - Record.AddStmt(E->getTemporary()); - Record.AddDeclRef(E->getExtendingDecl()); - Record.push_back(E->getManglingNumber()); + Record.push_back(static_cast(E->getLifetimeExtendedTemporaryDecl())); + if (E->getLifetimeExtendedTemporaryDecl()) + Record.AddDeclRef(E->getLifetimeExtendedTemporaryDecl()); + else + Record.AddStmt(E->getSubExpr()); Code = serialization::EXPR_MATERIALIZE_TEMPORARY; } diff --git a/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp index a84327f..7ed1114 100644 --- a/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp @@ -800,8 +800,7 @@ void IteratorChecker::checkPostStmt(const MaterializeTemporaryExpr *MTE, CheckerContext &C) const { /* Transfer iterator state to temporary objects */ auto State = C.getState(); - const auto *Pos = - getIteratorPosition(State, C.getSVal(MTE->GetTemporaryExpr())); + const auto *Pos = getIteratorPosition(State, C.getSVal(MTE->getSubExpr())); if (!Pos) return; State = setIteratorPosition(State, C.getSVal(MTE), *Pos); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 5c49231..d632882 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1427,7 +1427,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, bool IsTemporary = false; if (const auto *MTE = dyn_cast(ArgE)) { - ArgE = MTE->GetTemporaryExpr(); + ArgE = MTE->getSubExpr(); IsTemporary = true; } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 058be98..b816aab 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -27,7 +27,7 @@ void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, ExplodedNode *Pred, ExplodedNodeSet &Dst) { StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); - const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens(); + const Expr *tempExpr = ME->getSubExpr()->IgnoreParens(); ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index ada5d75..2078e47 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -6313,6 +6313,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) { case Decl::PragmaDetectMismatch: case Decl::UsingPack: case Decl::Concept: + case Decl::LifetimeExtendedTemporary: return C; // Declaration kinds that don't make any sense here, but are -- 2.7.4