[clang-tools-extra] b0561b3 - [NFC] Refactor representation of materialized temporaries
via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 19 09:21:06 PST 2019
Author: Tyker
Date: 2019-11-19T18:20:45+01:00
New Revision: b0561b3346e7bf0ae974995ca95b917eebde18e1
URL: https://github.com/llvm/llvm-project/commit/b0561b3346e7bf0ae974995ca95b917eebde18e1
DIFF: https://github.com/llvm/llvm-project/commit/b0561b3346e7bf0ae974995ca95b917eebde18e1.diff
LOG: [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
Added:
Modified:
clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp
clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp
clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp
clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp
clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
clang/include/clang/AST/ASTContext.h
clang/include/clang/AST/DeclCXX.h
clang/include/clang/AST/ExprCXX.h
clang/include/clang/AST/RecursiveASTVisitor.h
clang/include/clang/ASTMatchers/ASTMatchers.h
clang/include/clang/Basic/DeclNodes.td
clang/include/clang/Sema/Template.h
clang/include/clang/Serialization/ASTBitCodes.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/ASTImporter.cpp
clang/lib/AST/DeclBase.cpp
clang/lib/AST/DeclCXX.cpp
clang/lib/AST/Expr.cpp
clang/lib/AST/ExprCXX.cpp
clang/lib/AST/ExprConstant.cpp
clang/lib/AST/ItaniumMangle.cpp
clang/lib/AST/StmtPrinter.cpp
clang/lib/Analysis/CFG.cpp
clang/lib/Analysis/Consumed.cpp
clang/lib/Analysis/ThreadSafetyCommon.cpp
clang/lib/CodeGen/CGDecl.cpp
clang/lib/CodeGen/CGExpr.cpp
clang/lib/CodeGen/CGExprAgg.cpp
clang/lib/CodeGen/CGExprConstant.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/Sema/JumpDiagnostics.cpp
clang/lib/Sema/SemaChecking.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaInit.cpp
clang/lib/Sema/SemaOpenMP.cpp
clang/lib/Sema/SemaStmt.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTCommon.cpp
clang/lib/Serialization/ASTReaderDecl.cpp
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriterDecl.cpp
clang/lib/Serialization/ASTWriterStmt.cpp
clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
clang/tools/libclang/CIndex.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp b/clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp
index a249b1216111..0780924f3557 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<Stmt>,
const Stmt *E = &Node;
while (true) {
if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
- E = MTE->getTemporary();
+ E = MTE->getSubExpr();
if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E))
E = BTE->getSubExpr();
if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
diff --git a/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp b/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp
index c51b6e86b3f6..2d4475c991ca 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<MaterializeTemporaryExpr>(E)) {
- const auto *TE = M->GetTemporaryExpr();
+ const auto *TE = M->getSubExpr();
B.Kind = isa<CallExpr>(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 03efd12ded21..0389a6148954 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<MaterializeTemporaryExpr>(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 e3b90d3b4279..a52065540917 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 4372e74c2358..878eab8b9565 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<CXXConstructExpr>(E)) {
for (const auto *Arg : Constr->arguments()) {
if (const auto *M = dyn_cast<MaterializeTemporaryExpr>(Arg))
- markCanNotBeConst(cast<Expr>(M->getTemporary()), CanNotBeConst);
+ markCanNotBeConst(cast<Expr>(M->getSubExpr()), CanNotBeConst);
}
} else if (const auto *ILE = dyn_cast<InitListExpr>(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 5e2f4031d96c..a0484509fa4a 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -272,12 +272,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// Mapping from __block VarDecls to BlockVarCopyInit.
llvm::DenseMap<const VarDecl *, BlockVarCopyInit> 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<const MaterializeTemporaryExpr *, APValue *>
- MaterializedTemporaryValues;
-
/// Used to cleanups APValues stored in the AST.
mutable llvm::SmallVector<APValue *, 0> APValueCleanups;
@@ -2827,11 +2821,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// 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 66212f72b787..19a62acd9051 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<Expr>(ExprWithTemporary); }
+ const Expr *getTemporaryExpr() const { return cast<Expr>(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 2152e108c7cb..1eac1ce842d8 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<Stmt *, ExtraState *> State;
+ llvm::PointerUnion<Stmt *, LifetimeExtendedTemporaryDecl *> 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<Stmt *>() ? State.get<Stmt *>()
- : State.get<ExtraState *>()->Temporary;
- }
-
/// Retrieve the temporary-generating subexpression whose value will
/// be materialized into a glvalue.
- Expr *GetTemporaryExpr() const { return static_cast<Expr *>(getTemporary()); }
+ Expr *getSubExpr() const {
+ return cast<Expr>(
+ State.is<Stmt *>()
+ ? State.get<Stmt *>()
+ : State.get<LifetimeExtendedTemporaryDecl *>()->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<FieldDecl>(ExtendingDecl))
- return SD_Automatic;
- // FIXME: This only works because storage class specifiers are not allowed
- // on decomposition declarations.
- if (isa<BindingDecl>(ExtendingDecl))
- return ExtendingDecl->getDeclContext()->isFunctionOrMethod()
- ? SD_Automatic
- : SD_Static;
- return cast<VarDecl>(ExtendingDecl)->getStorageDuration();
+ return State.is<Stmt *>() ? SD_FullExpression
+ : State.get<LifetimeExtendedTemporaryDecl *>()
+ ->getStorageDuration();
+ }
+
+ /// Get the storage for the constant value of a materialized temporary
+ /// of static storage duration.
+ APValue *getOrCreateValue(bool MayCreate) const {
+ assert(State.is<LifetimeExtendedTemporaryDecl *>() &&
+ "the temporary has not been lifetime extended");
+ return State.get<LifetimeExtendedTemporaryDecl *>()->getOrCreateValue(
+ MayCreate);
+ }
+
+ LifetimeExtendedTemporaryDecl *getLifetimeExtendedTemporaryDecl() {
+ return State.dyn_cast<LifetimeExtendedTemporaryDecl *>();
+ }
+ const LifetimeExtendedTemporaryDecl *
+ getLifetimeExtendedTemporaryDecl() const {
+ return State.dyn_cast<LifetimeExtendedTemporaryDecl *>();
}
/// Get the declaration which triggered the lifetime-extension of this
/// temporary, if any.
- const ValueDecl *getExtendingDecl() const {
+ ValueDecl *getExtendingDecl() {
return State.is<Stmt *>() ? nullptr
- : State.get<ExtraState *>()->ExtendingDecl;
+ : State.get<LifetimeExtendedTemporaryDecl *>()
+ ->getExtendingDecl();
+ }
+ const ValueDecl *getExtendingDecl() const {
+ return const_cast<MaterializeTemporaryExpr *>(this)->getExtendingDecl();
}
- void setExtendingDecl(const ValueDecl *ExtendedBy, unsigned ManglingNumber);
+ void setExtendingDecl(ValueDecl *ExtendedBy, unsigned ManglingNumber);
unsigned getManglingNumber() const {
- return State.is<Stmt *>() ? 0 : State.get<ExtraState *>()->ManglingNumber;
+ return State.is<Stmt *>() ? 0
+ : State.get<LifetimeExtendedTemporaryDecl *>()
+ ->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<Stmt *>())
- return child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1);
-
- auto ES = State.get<ExtraState *>();
- return child_range(&ES->Temporary, &ES->Temporary + 1);
+ return State.is<Stmt *>()
+ ? child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1)
+ : State.get<LifetimeExtendedTemporaryDecl *>()->childrenExpr();
}
const_child_range children() const {
- if (State.is<Stmt *>())
- return const_child_range(State.getAddrOfPtr1(),
- State.getAddrOfPtr1() + 1);
-
- auto ES = State.get<ExtraState *>();
- return const_child_range(&ES->Temporary, &ES->Temporary + 1);
+ return State.is<Stmt *>()
+ ? const_child_range(State.getAddrOfPtr1(),
+ State.getAddrOfPtr1() + 1)
+ : const_cast<const LifetimeExtendedTemporaryDecl *>(
+ State.get<LifetimeExtendedTemporaryDecl *>())
+ ->childrenExpr();
}
};
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 9fea4980c89a..1b6bb7193321 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 e34b31cbda88..72ae63f9a757 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<MaterializeTemporaryExpr>(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 fa4d1b4f47e7..25d49fc37d4f 100644
--- a/clang/include/clang/Basic/DeclNodes.td
+++ b/clang/include/clang/Basic/DeclNodes.td
@@ -100,4 +100,5 @@ def OMPThreadPrivate : DeclNode<Decl>;
def OMPAllocate : DeclNode<Decl>;
def OMPRequires : DeclNode<Decl>;
def Empty : DeclNode<Decl>;
+def LifetimeExtendedTemporary : DeclNode<Decl>;
diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h
index 68c8c83c3631..54c01c7f52f1 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 52504976692b..b1986b2c934e 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 6a15f99eb7d3..abfa33d0df08 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<const MaterializeTemporaryExpr *, APValue *> &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 7034f411d733..7614da11a2ff 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<ObjCTypeParamList *>
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<Expr>(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 77a3a4c679a1..6ee767ccecf7 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 58b50de944ed..bca560c40aef 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<FieldDecl>(ExtendingDecl))
+ return SD_Automatic;
+ // FIXME: This only works because storage class specifiers are not allowed
+ // on decomposition declarations.
+ if (isa<BindingDecl>(ExtendingDecl))
+ return ExtendingDecl->getDeclContext()->isFunctionOrMethod() ? SD_Automatic
+ : SD_Static;
+ return cast<VarDecl>(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 4fd5fed5beef..d5c35e53059b 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<MaterializeTemporaryExpr>(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<MaterializeTemporaryExpr>(E))
- E = Materialize->GetTemporaryExpr();
+ E = Materialize->getSubExpr();
// Skip any temporary bindings; they're implicit.
if (auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
@@ -2727,8 +2727,9 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
case CXXDeleteExprClass:
return false;
case MaterializeTemporaryExprClass:
- return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr()
- ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
+ return cast<MaterializeTemporaryExpr>(this)
+ ->getSubExpr()
+ ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
case CXXBindTemporaryExprClass:
return cast<CXXBindTemporaryExpr>(this)->getSubExpr()
->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
@@ -2752,8 +2753,8 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {
case ImplicitCastExprClass:
return cast<ImplicitCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
case MaterializeTemporaryExprClass:
- return cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr()
- ->isOBJCGCCandidate(Ctx);
+ return cast<MaterializeTemporaryExpr>(E)->getSubExpr()->isOBJCGCCandidate(
+ Ctx);
case CStyleCastExprClass:
return cast<CStyleCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
case DeclRefExprClass: {
@@ -2828,7 +2829,7 @@ static Expr *IgnoreImpCastsExtraSingleStep(Expr *E) {
return SubE;
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
- return MTE->GetTemporaryExpr();
+ return MTE->getSubExpr();
if (auto *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E))
return NTTP->getReplacement();
@@ -2844,7 +2845,7 @@ static Expr *IgnoreCastsSingleStep(Expr *E) {
return FE->getSubExpr();
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
- return MTE->GetTemporaryExpr();
+ return MTE->getSubExpr();
if (auto *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E))
return NTTP->getReplacement();
@@ -2878,7 +2879,7 @@ static Expr *IgnoreImplicitSingleStep(Expr *E) {
return SubE;
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
- return MTE->GetTemporaryExpr();
+ return MTE->getSubExpr();
if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(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<MaterializeTemporaryExpr>(E))
- E = M->GetTemporaryExpr();
+ E = M->getSubExpr();
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(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<MaterializeTemporaryExpr>(E))
- E = M->GetTemporaryExpr();
+ E = M->getSubExpr();
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
if (ICE->getCastKind() == CK_NoOp)
@@ -3112,7 +3113,7 @@ bool Expr::isImplicitCXXThis() const {
if (const MaterializeTemporaryExpr *M
= dyn_cast<MaterializeTemporaryExpr>(E)) {
- E = M->GetTemporaryExpr();
+ E = M->getSubExpr();
continue;
}
@@ -3289,8 +3290,9 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
break;
}
case MaterializeTemporaryExprClass:
- return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr()
- ->isConstantInitializer(Ctx, false, Culprit);
+ return cast<MaterializeTemporaryExpr>(this)
+ ->getSubExpr()
+ ->isConstantInitializer(Ctx, false, Culprit);
case SubstNonTypeTemplateParmExprClass:
return cast<SubstNonTypeTemplateParmExpr>(this)->getReplacement()
@@ -3757,7 +3759,7 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
return NPCK_GNUNull;
} else if (const MaterializeTemporaryExpr *M
= dyn_cast<MaterializeTemporaryExpr>(this)) {
- return M->GetTemporaryExpr()->isNullPointerConstant(Ctx, NPC);
+ return M->getSubExpr()->isNullPointerConstant(Ctx, NPC);
} else if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(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<ExprWithCleanups>(e))
e = ewc->getSubExpr();
if (const MaterializeTemporaryExpr *m = dyn_cast<MaterializeTemporaryExpr>(e))
- e = m->GetTemporaryExpr();
+ e = m->getSubExpr();
e = cast<CXXConstructExpr>(e)->getArg(0);
while (const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
e = ice->getSubExpr();
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 904928bdf286..0fb132dbe3ff 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<ExtraState *>()) {
- auto *ES = new (ExtendedBy->getASTContext()) ExtraState;
- ES->Temporary = State.get<Stmt *>();
- State = ES;
- }
+ if (!State.is<LifetimeExtendedTemporaryDecl *>())
+ State = LifetimeExtendedTemporaryDecl::Create(
+ cast<Expr>(State.get<Stmt *>()), ExtendedBy, ManglingNumber);
- auto ES = State.get<ExtraState *>();
+ auto ES = State.get<LifetimeExtendedTemporaryDecl *>();
ES->ExtendingDecl = ExtendedBy;
ES->ManglingNumber = ManglingNumber;
}
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f4ca2284224b..79659261388b 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -107,7 +107,7 @@ namespace {
dyn_cast<MaterializeTemporaryExpr>(Base)) {
SmallVector<const Expr *, 2> CommaLHSs;
SmallVector<SubobjectAdjustment, 2> 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<const Expr *, 2> CommaLHSs;
SmallVector<SubobjectAdjustment, 2> 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<MaterializeTemporaryExpr>(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 c55a90137578..8c87c55c792a 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<MaterializeTemporaryExpr>(E)->GetTemporaryExpr());
+ mangleExpression(cast<MaterializeTemporaryExpr>(E)->getSubExpr());
break;
}
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 1602ef567605..1ef847a55b15 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 a533a8d97b84..762b8ecf3439 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<MaterializeTemporaryExpr>(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<MaterializeTemporaryExpr>(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<Expr *>(
cast<MaterializeTemporaryExpr>(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 cde753e8ec57..9560248b173f 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 373dfc77fa9b..1b8c55e56d47 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<CXXBindTemporaryExpr>(S)->getSubExpr(), Ctx);
case Stmt::MaterializeTemporaryExprClass:
- return translate(cast<MaterializeTemporaryExpr>(S)->GetTemporaryExpr(),
- Ctx);
+ return translate(cast<MaterializeTemporaryExpr>(S)->getSubExpr(), Ctx);
// Collect all literals
case Stmt::CharacterLiteralClass:
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 563841c068f6..f60628b9b622 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 384e8f72a619..214378a966f0 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<VarDecl>(M->getExtendingDecl()) ||
!cast<VarDecl>(M->getExtendingDecl())->isARCPseudoStrong()) &&
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 2f0e4937613f..7e69f63fe135 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 96e8c9c0d0e6..9198d7a6fb26 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<const Expr *, 2> CommaLHSs;
SmallVector<SubobjectAdjustment, 2> 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 e253bbc19915..768361d548db 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
diff erent 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 c8743df90e34..960e62d4a2db 100644
--- a/clang/lib/Sema/JumpDiagnostics.cpp
+++ b/clang/lib/Sema/JumpDiagnostics.cpp
@@ -546,8 +546,8 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S,
SmallVector<const Expr *, 4> CommaLHS;
SmallVector<SubobjectAdjustment, 4> 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 806df77cb275..65e4112d5e5a 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<MaterializeTemporaryExpr>(E);
if (!MTE) return false;
- const auto *Num = dyn_cast<IntegerLiteral>(MTE->GetTemporaryExpr());
+ const auto *Num = dyn_cast<IntegerLiteral>(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 76f500f077e8..ea4321cdd728 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<MaterializeTemporaryExpr>(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<MaterializeTemporaryExpr>(Op))
- Op = MTE->GetTemporaryExpr();
+ Op = MTE->getSubExpr();
if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(Op))
Op = BTE->getSubExpr();
if (auto *ICE = dyn_cast<ImplicitCastExpr>(Op)) {
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 1296e767ff0b..80d7cfed711a 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<MaterializeTemporaryExpr>(Init)) {
if (Visit(Path, Local(MTE), RK))
- visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(), Visit,
- true, EnableLifetimeWarnings);
+ visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(), Visit, true,
+ EnableLifetimeWarnings);
}
if (isa<CallExpr>(Init)) {
@@ -7067,9 +7067,8 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
}
} else if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(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 b0d667fbdd53..d0f2e7c30ae6 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<MaterializeTemporaryExpr>(E))
- E = MTE->GetTemporaryExpr();
+ E = MTE->getSubExpr();
while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
E = Binder->getSubExpr();
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 9680720f549e..05f7b30f1391 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<MaterializeTemporaryExpr>(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 0cd8abd8e83d..28c5738eb266 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -3470,7 +3470,7 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
Init = AIL->getCommonExpr();
if (MaterializeTemporaryExpr *MTE = dyn_cast<MaterializeTemporaryExpr>(Init))
- Init = MTE->GetTemporaryExpr();
+ Init = MTE->getSubExpr();
while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init))
Init = Binder->getSubExpr();
@@ -12180,7 +12180,7 @@ template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformMaterializeTemporaryExpr(
MaterializeTemporaryExpr *E) {
- return getDerived().TransformExpr(E->GetTemporaryExpr());
+ return getDerived().TransformExpr(E->getSubExpr());
}
template<typename Derived>
diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp
index dd06e0582ac5..cdb5b17022c2 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<T> but are not actually
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 21d3da90de11..9f799e3646d5 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<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
@@ -2349,6 +2350,16 @@ void ASTDeclReader::VisitEmptyDecl(EmptyDecl *D) {
VisitDecl(D);
}
+void ASTDeclReader::VisitLifetimeExtendedTemporaryDecl(
+ LifetimeExtendedTemporaryDecl *D) {
+ VisitDecl(D);
+ D->ExtendingDecl = ReadDeclAs<ValueDecl>();
+ D->ExprWithTemporary = Record.readStmt();
+ if (Record.readInt())
+ D->Value = new (D->getASTContext()) APValue(Record.readAPValue());
+ D->ManglingNumber = Record.readInt();
+}
+
std::pair<uint64_t, uint64_t>
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 3fd9fff5add4..8837396d03d6 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<ValueDecl>();
- unsigned ManglingNumber = Record.readInt();
- E->setExtendingDecl(VD, ManglingNumber);
+ bool HasMaterialzedDecl = Record.readInt();
+ if (HasMaterialzedDecl)
+ E->State = cast<LifetimeExtendedTemporaryDecl>(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 b9ee8e817190..51902a607ca1 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 <typename T> void VisitRedeclarable(Redeclarable<T> *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<bool>(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 6f4abc449094..e66db4353440 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<bool>(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 a84327f07a52..7ed11146397e 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 5c49231a7123..d63288216220 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<MaterializeTemporaryExpr>(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 058be985540d..b816aab7c18f 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 ada5d7551d73..2078e4719522 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
More information about the cfe-commits
mailing list