From b0561b3346e7bf0ae974995ca95b917eebde18e1 Mon Sep 17 00:00:00 2001 From: Tyker Date: Sun, 17 Nov 2019 11:41:55 +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: thakis, sammccall, ilya-biryukov, 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 +- .../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 | 12 +- clang/include/clang/ASTMatchers/ASTMatchers.h | 4 +- clang/include/clang/Basic/DeclNodes.td | 1 + clang/include/clang/Sema/Template.h | 3 +- .../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 +- .../Checkers/IteratorChecker.cpp | 3 +- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 2 +- .../lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 2 +- clang/tools/libclang/CIndex.cpp | 1 + 46 files changed, 333 insertions(+), 175 deletions(-) diff --git a/clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp b/clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp index a249b12161119..0780924f35575 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 c51b6e86b3f61..2d4475c991ca2 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 03efd12ded215..0389a6148954d 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 e3b90d3b4279b..a52065540917e 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 4372e74c23584..878eab8b95650 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 5e2f4031d96cc..a0484509fa4a0 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -272,12 +272,6 @@ class ASTContext : public RefCountedBase { /// 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 @@ class ASTContext : public RefCountedBase { /// 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 66212f72b7875..19a62acd9051a 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -3052,6 +3052,80 @@ class NamespaceAliasDecl : public NamedDecl, 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 2152e108c7cba..1eac1ce842d8b 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -4421,70 +4421,66 @@ class MaterializeTemporaryExpr : public Expr { 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 @@ class MaterializeTemporaryExpr : public Expr { } 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 @@ class MaterializeTemporaryExpr : public Expr { // 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 9fea4980c89ad..1b6bb71933219 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,16 @@ 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())); + ShouldVisitChildren = false; + } +}) // 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 e34b31cbda880..72ae63f9a7573 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 fa4d1b4f47e7a..25d49fc37d4f0 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 68c8c83c36316..54c01c7f52f1b 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 52504976692bd..b1986b2c934e1 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 6a15f99eb7d35..abfa33d0df088 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -877,10 +877,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(); @@ -10326,21 +10322,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 7034f411d733a..7614da11a2ff5 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 77a3a4c679a1a..6ee767ccecf7d 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 58b50de944ed0..bca560c40aefd 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 4fd5fed5beef1..d5c35e53059b2 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; } @@ -1897,7 +1897,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)) @@ -2727,8 +2727,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); @@ -2752,8 +2753,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: { @@ -2828,7 +2829,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(); @@ -2844,7 +2845,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(); @@ -2878,7 +2879,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(); @@ -3005,7 +3006,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(); @@ -3017,7 +3018,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) @@ -3112,7 +3113,7 @@ bool Expr::isImplicitCXXThis() const { if (const MaterializeTemporaryExpr *M = dyn_cast(E)) { - E = M->GetTemporaryExpr(); + E = M->getSubExpr(); continue; } @@ -3289,8 +3290,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() @@ -3757,7 +3759,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); @@ -4466,7 +4468,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 904928bdf2861..0fb132dbe3ff7 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 f4ca2284224b3..79659261388b4 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 c55a901375787..8c87c55c792ad 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -4338,7 +4338,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } 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 1602ef5676054..1ef847a55b159 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 a533a8d97b848..762b8ecf34393 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 @@ CFGBlock *CFGBuilder::VisitForTemporaryDtors(Stmt *E, bool ExternallyDestructed, // 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 cde753e8ec576..9560248b173fb 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 373dfc77fa9b9..1b8c55e56d470 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 563841c068f60..f60628b9b622d 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 384e8f72a6198..214378a966f04 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 2f0e4937613f4..7e69f63fe1354 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 96e8c9c0d0e61..9198d7a6fb26c 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1173,7 +1173,7 @@ class ConstExprEmitter : 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 e253bbc199156..768361d548dbd 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 c8743df90e340..960e62d4a2db8 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 806df77cb2752..65e4112d5e5ad 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 76f500f077e85..ea4321cdd7288 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 1296e767ff0bc..80d7cfed711a8 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 b0d667fbdd53b..d0f2e7c30ae6f 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -908,7 +908,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 9680720f549e0..05f7b30f1391e 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 0cd8abd8e83dc..28c5738eb2660 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 dd06e0582ac56..cdb5b17022c2f 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 21d3da90de11c..9f799e3646d59 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 3fd9fff5add43..8837396d03d65 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 b9ee8e817190f..51902a607ca12 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 6f4abc4490944..e66db43534406 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 a84327f07a52a..7ed11146397e5 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 5c49231a71231..d63288216220d 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 058be985540d3..b816aab7c18f8 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 ada5d7551d731..2078e47195226 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