Index: clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp =================================================================== --- clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp +++ clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp @@ -24,7 +24,7 @@ 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)) Index: clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp =================================================================== --- clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp +++ clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp @@ -53,7 +53,7 @@ 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; } Index: clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp =================================================================== --- clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp +++ clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp @@ -177,7 +177,7 @@ return nullptr; E = ConstructExpr->getArg(0); if (const auto *Temp = dyn_cast(E)) - E = Temp->GetTemporaryExpr(); + E = Temp->getSubExpr(); return digThroughConstructors(E); } return E; Index: clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp =================================================================== --- clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp +++ clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp @@ -78,7 +78,7 @@ // 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); } Index: clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp =================================================================== --- clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp +++ clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp @@ -202,7 +202,7 @@ } 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) Index: clang/include/clang/AST/ASTContext.h =================================================================== --- clang/include/clang/AST/ASTContext.h +++ clang/include/clang/AST/ASTContext.h @@ -272,12 +272,6 @@ /// 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 @@ /// 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. Index: clang/include/clang/AST/DeclCXX.h =================================================================== --- clang/include/clang/AST/DeclCXX.h +++ clang/include/clang/AST/DeclCXX.h @@ -3052,6 +3052,78 @@ 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; + + /// 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. /// Index: clang/include/clang/AST/ExprCXX.h =================================================================== --- clang/include/clang/AST/ExprCXX.h +++ clang/include/clang/AST/ExprCXX.h @@ -4421,70 +4421,66 @@ 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 @@ } 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 @@ // 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(); } }; Index: clang/include/clang/AST/RecursiveASTVisitor.h =================================================================== --- clang/include/clang/AST/RecursiveASTVisitor.h +++ clang/include/clang/AST/RecursiveASTVisitor.h @@ -1435,6 +1435,10 @@ 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(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. Index: clang/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchers.h +++ clang/include/clang/ASTMatchers/ASTMatchers.h @@ -6621,8 +6621,8 @@ 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); } } } Index: clang/include/clang/Basic/DeclNodes.td =================================================================== --- clang/include/clang/Basic/DeclNodes.td +++ clang/include/clang/Basic/DeclNodes.td @@ -100,4 +100,5 @@ def OMPAllocate : DeclNode; def OMPRequires : DeclNode; def Empty : DeclNode; +def LifetimeExtendedTemporary : DeclNode; Index: clang/include/clang/Sema/Template.h =================================================================== --- clang/include/clang/Sema/Template.h +++ clang/include/clang/Sema/Template.h @@ -464,8 +464,9 @@ #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) Index: clang/include/clang/Serialization/ASTBitCodes.h =================================================================== --- clang/include/clang/Serialization/ASTBitCodes.h +++ clang/include/clang/Serialization/ASTBitCodes.h @@ -1537,6 +1537,9 @@ /// An EmptyDecl record. DECL_EMPTY, + /// An LifetimeExtendedTemporaryDecl record. + DECL_LIFETIME_EXTENDED_TEMPORARY, + /// An ObjCTypeParamDecl record. DECL_OBJC_TYPE_PARAM, Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -875,10 +875,6 @@ 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 @@ 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). Index: clang/lib/AST/ASTImporter.cpp =================================================================== --- clang/lib/AST/ASTImporter.cpp +++ clang/lib/AST/ASTImporter.cpp @@ -485,6 +485,8 @@ ExpectedDecl VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); ExpectedDecl VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); ExpectedDecl VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D); + ExpectedDecl + VisitLifetimeExtendedTemporaryDecl(LifetimeExtendedTemporaryDecl *D); Expected ImportObjCTypeParamList(ObjCTypeParamList *list); @@ -7005,23 +7007,52 @@ 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; } Index: clang/lib/AST/DeclBase.cpp =================================================================== --- clang/lib/AST/DeclBase.cpp +++ clang/lib/AST/DeclBase.cpp @@ -803,6 +803,7 @@ case OMPRequires: case OMPCapturedExpr: case Empty: + case LifetimeExtendedTemporary: // Never looked up by name. return 0; } Index: clang/lib/AST/DeclCXX.cpp =================================================================== --- clang/lib/AST/DeclCXX.cpp +++ clang/lib/AST/DeclCXX.cpp @@ -2796,6 +2796,34 @@ 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, Index: clang/lib/AST/Expr.cpp =================================================================== --- clang/lib/AST/Expr.cpp +++ clang/lib/AST/Expr.cpp @@ -49,7 +49,7 @@ // Step into initializer for materialized temporaries. if (auto *MTE = dyn_cast(E)) { - E = MTE->GetTemporaryExpr(); + E = MTE->getSubExpr(); continue; } @@ -1891,7 +1891,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ /// 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 @@ if (const MaterializeTemporaryExpr *M = dyn_cast(E)) { - E = M->GetTemporaryExpr(); + E = M->getSubExpr(); continue; } @@ -3283,8 +3284,9 @@ 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 @@ 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 @@ 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(); Index: clang/lib/AST/ExprCXX.cpp =================================================================== --- clang/lib/AST/ExprCXX.cpp +++ clang/lib/AST/ExprCXX.cpp @@ -1653,7 +1653,23 @@ 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 @@ // 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; } Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -107,7 +107,7 @@ 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 @@ 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 @@ 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 @@ // 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 @@ // 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 @@ 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; Index: clang/lib/AST/ItaniumMangle.cpp =================================================================== --- clang/lib/AST/ItaniumMangle.cpp +++ clang/lib/AST/ItaniumMangle.cpp @@ -4338,7 +4338,7 @@ } case Expr::MaterializeTemporaryExprClass: { - mangleExpression(cast(E)->GetTemporaryExpr()); + mangleExpression(cast(E)->getSubExpr()); break; } Index: clang/lib/AST/StmtPrinter.cpp =================================================================== --- clang/lib/AST/StmtPrinter.cpp +++ clang/lib/AST/StmtPrinter.cpp @@ -2235,7 +2235,7 @@ } void StmtPrinter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *Node){ - PrintExpr(Node->GetTemporaryExpr()); + PrintExpr(Node->getSubExpr()); } void StmtPrinter::VisitCXXFoldExpr(CXXFoldExpr *E) { Index: clang/lib/Analysis/CFG.cpp =================================================================== --- clang/lib/Analysis/CFG.cpp +++ clang/lib/Analysis/CFG.cpp @@ -1428,7 +1428,7 @@ 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 @@ // 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 @@ AddStmtChoice asc) { findConstructionContexts( ConstructionContextLayer::create(cfg->getBumpVectorContext(), MTE), - MTE->getTemporary()); + MTE->getSubExpr()); return VisitStmt(MTE, asc); } @@ -4649,7 +4649,7 @@ // 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) { Index: clang/lib/Analysis/Consumed.cpp =================================================================== --- clang/lib/Analysis/Consumed.cpp +++ clang/lib/Analysis/Consumed.cpp @@ -847,7 +847,7 @@ void ConsumedStmtVisitor::VisitMaterializeTemporaryExpr( const MaterializeTemporaryExpr *Temp) { - forwardInfo(Temp->GetTemporaryExpr(), Temp); + forwardInfo(Temp->getSubExpr(), Temp); } void ConsumedStmtVisitor::VisitMemberExpr(const MemberExpr *MExpr) { Index: clang/lib/Analysis/ThreadSafetyCommon.cpp =================================================================== --- clang/lib/Analysis/ThreadSafetyCommon.cpp +++ clang/lib/Analysis/ThreadSafetyCommon.cpp @@ -244,8 +244,7 @@ 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: Index: clang/lib/CodeGen/CGDecl.cpp =================================================================== --- clang/lib/CodeGen/CGDecl.cpp +++ clang/lib/CodeGen/CGDecl.cpp @@ -109,6 +109,7 @@ case Decl::OMPRequires: case Decl::Empty: case Decl::Concept: + case Decl::LifetimeExtendedTemporary: // None of these decls require codegen support. return; Index: clang/lib/CodeGen/CGExpr.cpp =================================================================== --- clang/lib/CodeGen/CGExpr.cpp +++ clang/lib/CodeGen/CGExpr.cpp @@ -417,7 +417,7 @@ 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()) && Index: clang/lib/CodeGen/CGExprAgg.cpp =================================================================== --- clang/lib/CodeGen/CGExprAgg.cpp +++ clang/lib/CodeGen/CGExprAgg.cpp @@ -637,7 +637,7 @@ //===----------------------------------------------------------------------===// void AggExprEmitter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E){ - Visit(E->GetTemporaryExpr()); + Visit(E->getSubExpr()); } void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) { Index: clang/lib/CodeGen/CGExprConstant.cpp =================================================================== --- clang/lib/CodeGen/CGExprConstant.cpp +++ clang/lib/CodeGen/CGExprConstant.cpp @@ -1173,7 +1173,7 @@ 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 @@ 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); } Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -5010,7 +5010,7 @@ // 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); @@ -5033,7 +5033,7 @@ // 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. Index: clang/lib/Sema/JumpDiagnostics.cpp =================================================================== --- clang/lib/Sema/JumpDiagnostics.cpp +++ clang/lib/Sema/JumpDiagnostics.cpp @@ -546,8 +546,8 @@ 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, Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -9270,7 +9270,7 @@ 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; Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -7645,7 +7645,7 @@ E = E->IgnoreConversionOperator(); E = E->IgnoreImpCasts(); if (auto *MTE = dyn_cast(E)) { - E = MTE->GetTemporaryExpr(); + E = MTE->getSubExpr(); E = E->IgnoreImpCasts(); } @@ -8701,7 +8701,7 @@ 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)) { Index: clang/lib/Sema/SemaInit.cpp =================================================================== --- clang/lib/Sema/SemaInit.cpp +++ clang/lib/Sema/SemaInit.cpp @@ -6946,8 +6946,8 @@ 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 @@ } } 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); Index: clang/lib/Sema/SemaOpenMP.cpp =================================================================== --- clang/lib/Sema/SemaOpenMP.cpp +++ clang/lib/Sema/SemaOpenMP.cpp @@ -862,7 +862,7 @@ 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(); Index: clang/lib/Sema/SemaStmt.cpp =================================================================== --- clang/lib/Sema/SemaStmt.cpp +++ clang/lib/Sema/SemaStmt.cpp @@ -2724,7 +2724,7 @@ 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 @@ E = ME->getBase(); } else { const MaterializeTemporaryExpr *MTE = cast(E); - E = MTE->GetTemporaryExpr(); + E = MTE->getSubExpr(); } E = E->IgnoreImpCasts(); } Index: clang/lib/Sema/TreeTransform.h =================================================================== --- clang/lib/Sema/TreeTransform.h +++ clang/lib/Sema/TreeTransform.h @@ -3455,7 +3455,7 @@ Init = AIL->getCommonExpr(); if (MaterializeTemporaryExpr *MTE = dyn_cast(Init)) - Init = MTE->GetTemporaryExpr(); + Init = MTE->getSubExpr(); while (CXXBindTemporaryExpr *Binder = dyn_cast(Init)) Init = Binder->getSubExpr(); @@ -12157,7 +12157,7 @@ ExprResult TreeTransform::TransformMaterializeTemporaryExpr( MaterializeTemporaryExpr *E) { - return getDerived().TransformExpr(E->GetTemporaryExpr()); + return getDerived().TransformExpr(E->getSubExpr()); } template Index: clang/lib/Serialization/ASTCommon.cpp =================================================================== --- clang/lib/Serialization/ASTCommon.cpp +++ clang/lib/Serialization/ASTCommon.cpp @@ -401,6 +401,7 @@ case Decl::Decomposition: case Decl::Binding: case Decl::Concept: + case Decl::LifetimeExtendedTemporary: return false; // These indirectly derive from Redeclarable but are not actually Index: clang/lib/Serialization/ASTReaderDecl.cpp =================================================================== --- clang/lib/Serialization/ASTReaderDecl.cpp +++ clang/lib/Serialization/ASTReaderDecl.cpp @@ -405,6 +405,7 @@ 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 @@ 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 @@ 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; Index: clang/lib/Serialization/ASTReaderStmt.cpp =================================================================== --- clang/lib/Serialization/ASTReaderStmt.cpp +++ clang/lib/Serialization/ASTReaderStmt.cpp @@ -1900,10 +1900,11 @@ 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) { Index: clang/lib/Serialization/ASTWriterDecl.cpp =================================================================== --- clang/lib/Serialization/ASTWriterDecl.cpp +++ clang/lib/Serialization/ASTWriterDecl.cpp @@ -124,6 +124,7 @@ 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 @@ 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()); Index: clang/lib/Serialization/ASTWriterStmt.cpp =================================================================== --- clang/lib/Serialization/ASTWriterStmt.cpp +++ clang/lib/Serialization/ASTWriterStmt.cpp @@ -1835,9 +1835,11 @@ 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; } Index: clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp @@ -800,8 +800,7 @@ 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); Index: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1427,7 +1427,7 @@ bool IsTemporary = false; if (const auto *MTE = dyn_cast(ArgE)) { - ArgE = MTE->GetTemporaryExpr(); + ArgE = MTE->getSubExpr(); IsTemporary = true; } Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -27,7 +27,7 @@ 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(); Index: clang/tools/libclang/CIndex.cpp =================================================================== --- clang/tools/libclang/CIndex.cpp +++ clang/tools/libclang/CIndex.cpp @@ -6313,6 +6313,7 @@ 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