forked from OSchip/llvm-project
[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
This commit is contained in:
parent
dd471dbe99
commit
b0561b3346
|
@ -24,7 +24,7 @@ AST_MATCHER_P(Stmt, IgnoringTemporaries, ast_matchers::internal::Matcher<Stmt>,
|
||||||
const Stmt *E = &Node;
|
const Stmt *E = &Node;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
|
if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
|
||||||
E = MTE->getTemporary();
|
E = MTE->getSubExpr();
|
||||||
if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E))
|
if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E))
|
||||||
E = BTE->getSubExpr();
|
E = BTE->getSubExpr();
|
||||||
if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
|
if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
|
||||||
|
|
|
@ -53,7 +53,7 @@ buildBindArguments(const MatchFinder::MatchResult &Result, const CallExpr *C) {
|
||||||
const Expr *E = C->getArg(I);
|
const Expr *E = C->getArg(I);
|
||||||
BindArgument B;
|
BindArgument B;
|
||||||
if (const auto *M = dyn_cast<MaterializeTemporaryExpr>(E)) {
|
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;
|
B.Kind = isa<CallExpr>(TE) ? BK_CallExpr : BK_Temporary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -177,7 +177,7 @@ const Expr *digThroughConstructors(const Expr *E) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
E = ConstructExpr->getArg(0);
|
E = ConstructExpr->getArg(0);
|
||||||
if (const auto *Temp = dyn_cast<MaterializeTemporaryExpr>(E))
|
if (const auto *Temp = dyn_cast<MaterializeTemporaryExpr>(E))
|
||||||
E = Temp->GetTemporaryExpr();
|
E = Temp->getSubExpr();
|
||||||
return digThroughConstructors(E);
|
return digThroughConstructors(E);
|
||||||
}
|
}
|
||||||
return E;
|
return E;
|
||||||
|
|
|
@ -78,7 +78,7 @@ void ImplicitConversionInLoopCheck::check(
|
||||||
// iterator returns a value instead of a reference, and the loop variable
|
// iterator returns a value instead of a reference, and the loop variable
|
||||||
// is a reference. This situation is fine (it probably produces the same
|
// is a reference. This situation is fine (it probably produces the same
|
||||||
// code at the end).
|
// code at the end).
|
||||||
if (IsNonTrivialImplicitCast(Materialized->getTemporary()))
|
if (IsNonTrivialImplicitCast(Materialized->getSubExpr()))
|
||||||
ReportAndFix(Result.Context, VD, OperatorCall);
|
ReportAndFix(Result.Context, VD, OperatorCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -202,7 +202,7 @@ void NonConstParameterCheck::markCanNotBeConst(const Expr *E,
|
||||||
} else if (const auto *Constr = dyn_cast<CXXConstructExpr>(E)) {
|
} else if (const auto *Constr = dyn_cast<CXXConstructExpr>(E)) {
|
||||||
for (const auto *Arg : Constr->arguments()) {
|
for (const auto *Arg : Constr->arguments()) {
|
||||||
if (const auto *M = dyn_cast<MaterializeTemporaryExpr>(Arg))
|
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)) {
|
} else if (const auto *ILE = dyn_cast<InitListExpr>(E)) {
|
||||||
for (unsigned I = 0U; I < ILE->getNumInits(); ++I)
|
for (unsigned I = 0U; I < ILE->getNumInits(); ++I)
|
||||||
|
|
|
@ -272,12 +272,6 @@ private:
|
||||||
/// Mapping from __block VarDecls to BlockVarCopyInit.
|
/// Mapping from __block VarDecls to BlockVarCopyInit.
|
||||||
llvm::DenseMap<const VarDecl *, BlockVarCopyInit> BlockVarCopyInits;
|
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.
|
/// Used to cleanups APValues stored in the AST.
|
||||||
mutable llvm::SmallVector<APValue *, 0> APValueCleanups;
|
mutable llvm::SmallVector<APValue *, 0> APValueCleanups;
|
||||||
|
|
||||||
|
@ -2827,11 +2821,6 @@ public:
|
||||||
/// index of the parameter when it exceeds the size of the normal bitfield.
|
/// index of the parameter when it exceeds the size of the normal bitfield.
|
||||||
unsigned getParameterIndex(const ParmVarDecl *D) const;
|
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
|
/// Return a string representing the human readable name for the specified
|
||||||
/// function declaration or file name. Used by SourceLocExpr and
|
/// function declaration or file name. Used by SourceLocExpr and
|
||||||
/// PredefinedExpr to cache evaluated results.
|
/// PredefinedExpr to cache evaluated results.
|
||||||
|
|
|
@ -3052,6 +3052,80 @@ public:
|
||||||
static bool classofKind(Kind K) { return K == NamespaceAlias; }
|
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
|
/// Represents a shadow declaration introduced into a scope by a
|
||||||
/// (resolved) using declaration.
|
/// (resolved) using declaration.
|
||||||
///
|
///
|
||||||
|
|
|
@ -4421,70 +4421,66 @@ private:
|
||||||
friend class ASTStmtReader;
|
friend class ASTStmtReader;
|
||||||
friend class ASTStmtWriter;
|
friend class ASTStmtWriter;
|
||||||
|
|
||||||
struct ExtraState {
|
llvm::PointerUnion<Stmt *, LifetimeExtendedTemporaryDecl *> State;
|
||||||
/// 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;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MaterializeTemporaryExpr(QualType T, Expr *Temporary,
|
MaterializeTemporaryExpr(QualType T, Expr *Temporary,
|
||||||
bool BoundToLvalueReference)
|
bool BoundToLvalueReference,
|
||||||
: Expr(MaterializeTemporaryExprClass, T,
|
LifetimeExtendedTemporaryDecl *MTD = nullptr);
|
||||||
BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary,
|
|
||||||
Temporary->isTypeDependent(), Temporary->isValueDependent(),
|
|
||||||
Temporary->isInstantiationDependent(),
|
|
||||||
Temporary->containsUnexpandedParameterPack()),
|
|
||||||
State(Temporary) {}
|
|
||||||
|
|
||||||
MaterializeTemporaryExpr(EmptyShell Empty)
|
MaterializeTemporaryExpr(EmptyShell Empty)
|
||||||
: Expr(MaterializeTemporaryExprClass, 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
|
/// Retrieve the temporary-generating subexpression whose value will
|
||||||
/// be materialized into a glvalue.
|
/// 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.
|
/// Retrieve the storage duration for the materialized temporary.
|
||||||
StorageDuration getStorageDuration() const {
|
StorageDuration getStorageDuration() const {
|
||||||
const ValueDecl *ExtendingDecl = getExtendingDecl();
|
return State.is<Stmt *>() ? SD_FullExpression
|
||||||
if (!ExtendingDecl)
|
: State.get<LifetimeExtendedTemporaryDecl *>()
|
||||||
return SD_FullExpression;
|
->getStorageDuration();
|
||||||
// FIXME: This is not necessarily correct for a temporary materialized
|
}
|
||||||
// within a default initializer.
|
|
||||||
if (isa<FieldDecl>(ExtendingDecl))
|
/// Get the storage for the constant value of a materialized temporary
|
||||||
return SD_Automatic;
|
/// of static storage duration.
|
||||||
// FIXME: This only works because storage class specifiers are not allowed
|
APValue *getOrCreateValue(bool MayCreate) const {
|
||||||
// on decomposition declarations.
|
assert(State.is<LifetimeExtendedTemporaryDecl *>() &&
|
||||||
if (isa<BindingDecl>(ExtendingDecl))
|
"the temporary has not been lifetime extended");
|
||||||
return ExtendingDecl->getDeclContext()->isFunctionOrMethod()
|
return State.get<LifetimeExtendedTemporaryDecl *>()->getOrCreateValue(
|
||||||
? SD_Automatic
|
MayCreate);
|
||||||
: SD_Static;
|
}
|
||||||
return cast<VarDecl>(ExtendingDecl)->getStorageDuration();
|
|
||||||
|
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
|
/// Get the declaration which triggered the lifetime-extension of this
|
||||||
/// temporary, if any.
|
/// temporary, if any.
|
||||||
const ValueDecl *getExtendingDecl() const {
|
ValueDecl *getExtendingDecl() {
|
||||||
return State.is<Stmt *>() ? nullptr
|
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 {
|
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
|
/// Determine whether this materialized temporary is bound to an
|
||||||
|
@ -4494,11 +4490,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceLocation getBeginLoc() const LLVM_READONLY {
|
SourceLocation getBeginLoc() const LLVM_READONLY {
|
||||||
return getTemporary()->getBeginLoc();
|
return getSubExpr()->getBeginLoc();
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceLocation getEndLoc() const LLVM_READONLY {
|
SourceLocation getEndLoc() const LLVM_READONLY {
|
||||||
return getTemporary()->getEndLoc();
|
return getSubExpr()->getEndLoc();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool classof(const Stmt *T) {
|
static bool classof(const Stmt *T) {
|
||||||
|
@ -4507,20 +4503,18 @@ public:
|
||||||
|
|
||||||
// Iterators
|
// Iterators
|
||||||
child_range children() {
|
child_range children() {
|
||||||
if (State.is<Stmt *>())
|
return State.is<Stmt *>()
|
||||||
return child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1);
|
? child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1)
|
||||||
|
: State.get<LifetimeExtendedTemporaryDecl *>()->childrenExpr();
|
||||||
auto ES = State.get<ExtraState *>();
|
|
||||||
return child_range(&ES->Temporary, &ES->Temporary + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const_child_range children() const {
|
const_child_range children() const {
|
||||||
if (State.is<Stmt *>())
|
return State.is<Stmt *>()
|
||||||
return const_child_range(State.getAddrOfPtr1(),
|
? const_child_range(State.getAddrOfPtr1(),
|
||||||
State.getAddrOfPtr1() + 1);
|
State.getAddrOfPtr1() + 1)
|
||||||
|
: const_cast<const LifetimeExtendedTemporaryDecl *>(
|
||||||
auto ES = State.get<ExtraState *>();
|
State.get<LifetimeExtendedTemporaryDecl *>())
|
||||||
return const_child_range(&ES->Temporary, &ES->Temporary + 1);
|
->childrenExpr();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1435,6 +1435,10 @@ DEF_TRAVERSE_DECL(CapturedDecl, {
|
||||||
|
|
||||||
DEF_TRAVERSE_DECL(EmptyDecl, {})
|
DEF_TRAVERSE_DECL(EmptyDecl, {})
|
||||||
|
|
||||||
|
DEF_TRAVERSE_DECL(LifetimeExtendedTemporaryDecl, {
|
||||||
|
TRY_TO(TraverseStmt(D->getTemporaryExpr()));
|
||||||
|
})
|
||||||
|
|
||||||
DEF_TRAVERSE_DECL(FileScopeAsmDecl,
|
DEF_TRAVERSE_DECL(FileScopeAsmDecl,
|
||||||
{ TRY_TO(TraverseStmt(D->getAsmString())); })
|
{ TRY_TO(TraverseStmt(D->getAsmString())); })
|
||||||
|
|
||||||
|
@ -2632,10 +2636,16 @@ DEF_TRAVERSE_STMT(SizeOfPackExpr, {})
|
||||||
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {})
|
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {})
|
||||||
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {})
|
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {})
|
||||||
DEF_TRAVERSE_STMT(FunctionParmPackExpr, {})
|
DEF_TRAVERSE_STMT(FunctionParmPackExpr, {})
|
||||||
DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {})
|
|
||||||
DEF_TRAVERSE_STMT(CXXFoldExpr, {})
|
DEF_TRAVERSE_STMT(CXXFoldExpr, {})
|
||||||
DEF_TRAVERSE_STMT(AtomicExpr, {})
|
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
|
// For coroutines expressions, traverse either the operand
|
||||||
// as written or the implied calls, depending on what the
|
// as written or the implied calls, depending on what the
|
||||||
// derived class requests.
|
// derived class requests.
|
||||||
|
|
|
@ -6621,8 +6621,8 @@ AST_MATCHER_P(Expr, ignoringElidableConstructorCall,
|
||||||
if (CtorExpr->isElidable()) {
|
if (CtorExpr->isElidable()) {
|
||||||
if (const auto *MaterializeTemp =
|
if (const auto *MaterializeTemp =
|
||||||
dyn_cast<MaterializeTemporaryExpr>(CtorExpr->getArg(0))) {
|
dyn_cast<MaterializeTemporaryExpr>(CtorExpr->getArg(0))) {
|
||||||
return InnerMatcher.matches(*MaterializeTemp->GetTemporaryExpr(),
|
return InnerMatcher.matches(*MaterializeTemp->getSubExpr(), Finder,
|
||||||
Finder, Builder);
|
Builder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,4 +100,5 @@ def OMPThreadPrivate : DeclNode<Decl>;
|
||||||
def OMPAllocate : DeclNode<Decl>;
|
def OMPAllocate : DeclNode<Decl>;
|
||||||
def OMPRequires : DeclNode<Decl>;
|
def OMPRequires : DeclNode<Decl>;
|
||||||
def Empty : DeclNode<Decl>;
|
def Empty : DeclNode<Decl>;
|
||||||
|
def LifetimeExtendedTemporary : DeclNode<Decl>;
|
||||||
|
|
||||||
|
|
|
@ -464,8 +464,9 @@ class VarDecl;
|
||||||
#define OBJCPROPERTY(DERIVED, BASE)
|
#define OBJCPROPERTY(DERIVED, BASE)
|
||||||
#define OBJCPROPERTYIMPL(DERIVED, BASE)
|
#define OBJCPROPERTYIMPL(DERIVED, BASE)
|
||||||
#define EMPTY(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 BLOCK(DERIVED, BASE)
|
||||||
#define CAPTURED(DERIVED, BASE)
|
#define CAPTURED(DERIVED, BASE)
|
||||||
#define IMPLICITPARAM(DERIVED, BASE)
|
#define IMPLICITPARAM(DERIVED, BASE)
|
||||||
|
|
|
@ -1537,6 +1537,9 @@ namespace serialization {
|
||||||
/// An EmptyDecl record.
|
/// An EmptyDecl record.
|
||||||
DECL_EMPTY,
|
DECL_EMPTY,
|
||||||
|
|
||||||
|
/// An LifetimeExtendedTemporaryDecl record.
|
||||||
|
DECL_LIFETIME_EXTENDED_TEMPORARY,
|
||||||
|
|
||||||
/// An ObjCTypeParamDecl record.
|
/// An ObjCTypeParamDecl record.
|
||||||
DECL_OBJC_TYPE_PARAM,
|
DECL_OBJC_TYPE_PARAM,
|
||||||
|
|
||||||
|
|
|
@ -877,10 +877,6 @@ ASTContext::~ASTContext() {
|
||||||
A != AEnd; ++A)
|
A != AEnd; ++A)
|
||||||
A->second->~AttrVec();
|
A->second->~AttrVec();
|
||||||
|
|
||||||
for (std::pair<const MaterializeTemporaryExpr *, APValue *> &MTVPair :
|
|
||||||
MaterializedTemporaryValues)
|
|
||||||
MTVPair.second->~APValue();
|
|
||||||
|
|
||||||
for (const auto &Value : ModuleInitializers)
|
for (const auto &Value : ModuleInitializers)
|
||||||
Value.second->~PerModuleInitializers();
|
Value.second->~PerModuleInitializers();
|
||||||
|
|
||||||
|
@ -10326,21 +10322,6 @@ unsigned ASTContext::getParameterIndex(const ParmVarDecl *D) const {
|
||||||
return I->second;
|
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,
|
QualType ASTContext::getStringLiteralArrayType(QualType EltTy,
|
||||||
unsigned Length) const {
|
unsigned Length) const {
|
||||||
// A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
|
// A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
|
||||||
|
|
|
@ -485,6 +485,8 @@ namespace clang {
|
||||||
ExpectedDecl VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
|
ExpectedDecl VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
|
||||||
ExpectedDecl VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
|
ExpectedDecl VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
|
||||||
ExpectedDecl VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D);
|
ExpectedDecl VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D);
|
||||||
|
ExpectedDecl
|
||||||
|
VisitLifetimeExtendedTemporaryDecl(LifetimeExtendedTemporaryDecl *D);
|
||||||
|
|
||||||
Expected<ObjCTypeParamList *>
|
Expected<ObjCTypeParamList *>
|
||||||
ImportObjCTypeParamList(ObjCTypeParamList *list);
|
ImportObjCTypeParamList(ObjCTypeParamList *list);
|
||||||
|
@ -7007,23 +7009,52 @@ ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
|
||||||
E->requiresZeroInitialization());
|
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
|
ExpectedStmt
|
||||||
ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
|
ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
|
||||||
auto Imp = importSeq(
|
auto Imp = importSeq(E->getType(),
|
||||||
E->getType(), E->GetTemporaryExpr(), E->getExtendingDecl());
|
E->getLifetimeExtendedTemporaryDecl() ? nullptr
|
||||||
|
: E->getSubExpr(),
|
||||||
|
E->getLifetimeExtendedTemporaryDecl());
|
||||||
if (!Imp)
|
if (!Imp)
|
||||||
return Imp.takeError();
|
return Imp.takeError();
|
||||||
|
|
||||||
QualType ToType;
|
QualType ToType;
|
||||||
Expr *ToTemporaryExpr;
|
Expr *ToTemporaryExpr;
|
||||||
const ValueDecl *ToExtendingDecl;
|
LifetimeExtendedTemporaryDecl *ToMaterializedDecl;
|
||||||
std::tie(ToType, ToTemporaryExpr, ToExtendingDecl) = *Imp;
|
std::tie(ToType, ToTemporaryExpr, ToMaterializedDecl) = *Imp;
|
||||||
|
if (!ToTemporaryExpr)
|
||||||
|
ToTemporaryExpr = cast<Expr>(ToMaterializedDecl->getTemporaryExpr());
|
||||||
|
|
||||||
auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr(
|
auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr(
|
||||||
ToType, ToTemporaryExpr, E->isBoundToLvalueReference());
|
ToType, ToTemporaryExpr, E->isBoundToLvalueReference(),
|
||||||
|
ToMaterializedDecl);
|
||||||
|
|
||||||
// FIXME: Should ManglingNumber get numbers associated with 'to' context?
|
|
||||||
ToMTE->setExtendingDecl(ToExtendingDecl, E->getManglingNumber());
|
|
||||||
return ToMTE;
|
return ToMTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -803,6 +803,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
||||||
case OMPRequires:
|
case OMPRequires:
|
||||||
case OMPCapturedExpr:
|
case OMPCapturedExpr:
|
||||||
case Empty:
|
case Empty:
|
||||||
|
case LifetimeExtendedTemporary:
|
||||||
// Never looked up by name.
|
// Never looked up by name.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2796,6 +2796,34 @@ NamespaceAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
||||||
SourceLocation(), nullptr);
|
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() {}
|
void UsingShadowDecl::anchor() {}
|
||||||
|
|
||||||
UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC,
|
UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC,
|
||||||
|
|
|
@ -49,7 +49,7 @@ const Expr *Expr::getBestDynamicClassTypeExpr() const {
|
||||||
|
|
||||||
// Step into initializer for materialized temporaries.
|
// Step into initializer for materialized temporaries.
|
||||||
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) {
|
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) {
|
||||||
E = MTE->GetTemporaryExpr();
|
E = MTE->getSubExpr();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1897,7 +1897,7 @@ namespace {
|
||||||
const Expr *skipImplicitTemporary(const Expr *E) {
|
const Expr *skipImplicitTemporary(const Expr *E) {
|
||||||
// Skip through reference binding to temporary.
|
// Skip through reference binding to temporary.
|
||||||
if (auto *Materialize = dyn_cast<MaterializeTemporaryExpr>(E))
|
if (auto *Materialize = dyn_cast<MaterializeTemporaryExpr>(E))
|
||||||
E = Materialize->GetTemporaryExpr();
|
E = Materialize->getSubExpr();
|
||||||
|
|
||||||
// Skip any temporary bindings; they're implicit.
|
// Skip any temporary bindings; they're implicit.
|
||||||
if (auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
|
if (auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
|
||||||
|
@ -2727,7 +2727,8 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
|
||||||
case CXXDeleteExprClass:
|
case CXXDeleteExprClass:
|
||||||
return false;
|
return false;
|
||||||
case MaterializeTemporaryExprClass:
|
case MaterializeTemporaryExprClass:
|
||||||
return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr()
|
return cast<MaterializeTemporaryExpr>(this)
|
||||||
|
->getSubExpr()
|
||||||
->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
|
->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
|
||||||
case CXXBindTemporaryExprClass:
|
case CXXBindTemporaryExprClass:
|
||||||
return cast<CXXBindTemporaryExpr>(this)->getSubExpr()
|
return cast<CXXBindTemporaryExpr>(this)->getSubExpr()
|
||||||
|
@ -2752,8 +2753,8 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {
|
||||||
case ImplicitCastExprClass:
|
case ImplicitCastExprClass:
|
||||||
return cast<ImplicitCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
|
return cast<ImplicitCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
|
||||||
case MaterializeTemporaryExprClass:
|
case MaterializeTemporaryExprClass:
|
||||||
return cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr()
|
return cast<MaterializeTemporaryExpr>(E)->getSubExpr()->isOBJCGCCandidate(
|
||||||
->isOBJCGCCandidate(Ctx);
|
Ctx);
|
||||||
case CStyleCastExprClass:
|
case CStyleCastExprClass:
|
||||||
return cast<CStyleCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
|
return cast<CStyleCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
|
||||||
case DeclRefExprClass: {
|
case DeclRefExprClass: {
|
||||||
|
@ -2828,7 +2829,7 @@ static Expr *IgnoreImpCastsExtraSingleStep(Expr *E) {
|
||||||
return SubE;
|
return SubE;
|
||||||
|
|
||||||
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
|
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
|
||||||
return MTE->GetTemporaryExpr();
|
return MTE->getSubExpr();
|
||||||
|
|
||||||
if (auto *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E))
|
if (auto *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E))
|
||||||
return NTTP->getReplacement();
|
return NTTP->getReplacement();
|
||||||
|
@ -2844,7 +2845,7 @@ static Expr *IgnoreCastsSingleStep(Expr *E) {
|
||||||
return FE->getSubExpr();
|
return FE->getSubExpr();
|
||||||
|
|
||||||
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
|
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
|
||||||
return MTE->GetTemporaryExpr();
|
return MTE->getSubExpr();
|
||||||
|
|
||||||
if (auto *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E))
|
if (auto *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E))
|
||||||
return NTTP->getReplacement();
|
return NTTP->getReplacement();
|
||||||
|
@ -2878,7 +2879,7 @@ static Expr *IgnoreImplicitSingleStep(Expr *E) {
|
||||||
return SubE;
|
return SubE;
|
||||||
|
|
||||||
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
|
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
|
||||||
return MTE->GetTemporaryExpr();
|
return MTE->getSubExpr();
|
||||||
|
|
||||||
if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E))
|
if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E))
|
||||||
return BTE->getSubExpr();
|
return BTE->getSubExpr();
|
||||||
|
@ -3005,7 +3006,7 @@ Expr *Expr::IgnoreParenNoopCasts(const ASTContext &Ctx) {
|
||||||
bool Expr::isDefaultArgument() const {
|
bool Expr::isDefaultArgument() const {
|
||||||
const Expr *E = this;
|
const Expr *E = this;
|
||||||
if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E))
|
if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E))
|
||||||
E = M->GetTemporaryExpr();
|
E = M->getSubExpr();
|
||||||
|
|
||||||
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
|
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
|
||||||
E = ICE->getSubExprAsWritten();
|
E = ICE->getSubExprAsWritten();
|
||||||
|
@ -3017,7 +3018,7 @@ bool Expr::isDefaultArgument() const {
|
||||||
/// expressions.
|
/// expressions.
|
||||||
static const Expr *skipTemporaryBindingsNoOpCastsAndParens(const Expr *E) {
|
static const Expr *skipTemporaryBindingsNoOpCastsAndParens(const Expr *E) {
|
||||||
if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E))
|
if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E))
|
||||||
E = M->GetTemporaryExpr();
|
E = M->getSubExpr();
|
||||||
|
|
||||||
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
|
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
|
||||||
if (ICE->getCastKind() == CK_NoOp)
|
if (ICE->getCastKind() == CK_NoOp)
|
||||||
|
@ -3112,7 +3113,7 @@ bool Expr::isImplicitCXXThis() const {
|
||||||
|
|
||||||
if (const MaterializeTemporaryExpr *M
|
if (const MaterializeTemporaryExpr *M
|
||||||
= dyn_cast<MaterializeTemporaryExpr>(E)) {
|
= dyn_cast<MaterializeTemporaryExpr>(E)) {
|
||||||
E = M->GetTemporaryExpr();
|
E = M->getSubExpr();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3289,7 +3290,8 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MaterializeTemporaryExprClass:
|
case MaterializeTemporaryExprClass:
|
||||||
return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr()
|
return cast<MaterializeTemporaryExpr>(this)
|
||||||
|
->getSubExpr()
|
||||||
->isConstantInitializer(Ctx, false, Culprit);
|
->isConstantInitializer(Ctx, false, Culprit);
|
||||||
|
|
||||||
case SubstNonTypeTemplateParmExprClass:
|
case SubstNonTypeTemplateParmExprClass:
|
||||||
|
@ -3757,7 +3759,7 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
|
||||||
return NPCK_GNUNull;
|
return NPCK_GNUNull;
|
||||||
} else if (const MaterializeTemporaryExpr *M
|
} else if (const MaterializeTemporaryExpr *M
|
||||||
= dyn_cast<MaterializeTemporaryExpr>(this)) {
|
= 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)) {
|
} else if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(this)) {
|
||||||
if (const Expr *Source = OVE->getSourceExpr())
|
if (const Expr *Source = OVE->getSourceExpr())
|
||||||
return Source->isNullPointerConstant(Ctx, NPC);
|
return Source->isNullPointerConstant(Ctx, NPC);
|
||||||
|
@ -4466,7 +4468,7 @@ const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) {
|
||||||
if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(e))
|
if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(e))
|
||||||
e = ewc->getSubExpr();
|
e = ewc->getSubExpr();
|
||||||
if (const MaterializeTemporaryExpr *m = dyn_cast<MaterializeTemporaryExpr>(e))
|
if (const MaterializeTemporaryExpr *m = dyn_cast<MaterializeTemporaryExpr>(e))
|
||||||
e = m->GetTemporaryExpr();
|
e = m->getSubExpr();
|
||||||
e = cast<CXXConstructExpr>(e)->getArg(0);
|
e = cast<CXXConstructExpr>(e)->getArg(0);
|
||||||
while (const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
|
while (const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
|
||||||
e = ice->getSubExpr();
|
e = ice->getSubExpr();
|
||||||
|
|
|
@ -1653,7 +1653,23 @@ FunctionParmPackExpr::CreateEmpty(const ASTContext &Context,
|
||||||
FunctionParmPackExpr(QualType(), nullptr, SourceLocation(), 0, nullptr);
|
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) {
|
unsigned ManglingNumber) {
|
||||||
// We only need extra state if we have to remember more than just the Stmt.
|
// We only need extra state if we have to remember more than just the Stmt.
|
||||||
if (!ExtendedBy)
|
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
|
// We may need to allocate extra storage for the mangling number and the
|
||||||
// extended-by ValueDecl.
|
// extended-by ValueDecl.
|
||||||
if (!State.is<ExtraState *>()) {
|
if (!State.is<LifetimeExtendedTemporaryDecl *>())
|
||||||
auto *ES = new (ExtendedBy->getASTContext()) ExtraState;
|
State = LifetimeExtendedTemporaryDecl::Create(
|
||||||
ES->Temporary = State.get<Stmt *>();
|
cast<Expr>(State.get<Stmt *>()), ExtendedBy, ManglingNumber);
|
||||||
State = ES;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ES = State.get<ExtraState *>();
|
auto ES = State.get<LifetimeExtendedTemporaryDecl *>();
|
||||||
ES->ExtendingDecl = ExtendedBy;
|
ES->ExtendingDecl = ExtendedBy;
|
||||||
ES->ManglingNumber = ManglingNumber;
|
ES->ManglingNumber = ManglingNumber;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,7 @@ namespace {
|
||||||
dyn_cast<MaterializeTemporaryExpr>(Base)) {
|
dyn_cast<MaterializeTemporaryExpr>(Base)) {
|
||||||
SmallVector<const Expr *, 2> CommaLHSs;
|
SmallVector<const Expr *, 2> CommaLHSs;
|
||||||
SmallVector<SubobjectAdjustment, 2> Adjustments;
|
SmallVector<SubobjectAdjustment, 2> Adjustments;
|
||||||
const Expr *Temp = MTE->GetTemporaryExpr();
|
const Expr *Temp = MTE->getSubExpr();
|
||||||
const Expr *Inner = Temp->skipRValueSubobjectAdjustments(CommaLHSs,
|
const Expr *Inner = Temp->skipRValueSubobjectAdjustments(CommaLHSs,
|
||||||
Adjustments);
|
Adjustments);
|
||||||
// Keep any cv-qualifiers from the reference if we generated a temporary
|
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
APValue *V = Info.Ctx.getMaterializedTemporaryValue(MTE, false);
|
APValue *V = MTE->getOrCreateValue(false);
|
||||||
assert(V && "evasluation result refers to uninitialised temporary");
|
assert(V && "evasluation result refers to uninitialised temporary");
|
||||||
if (!CheckEvaluationResult(CheckEvaluationResultKind::ConstantExpression,
|
if (!CheckEvaluationResult(CheckEvaluationResultKind::ConstantExpression,
|
||||||
Info, MTE->getExprLoc(), TempType, *V,
|
Info, MTE->getExprLoc(), TempType, *V,
|
||||||
|
@ -3679,7 +3679,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
|
||||||
return CompleteObject();
|
return CompleteObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseVal = Info.Ctx.getMaterializedTemporaryValue(MTE, false);
|
BaseVal = MTE->getOrCreateValue(false);
|
||||||
assert(BaseVal && "got reference to unevaluated temporary");
|
assert(BaseVal && "got reference to unevaluated temporary");
|
||||||
} else {
|
} else {
|
||||||
if (!IsAccess)
|
if (!IsAccess)
|
||||||
|
@ -7470,8 +7470,8 @@ bool LValueExprEvaluator::VisitMaterializeTemporaryExpr(
|
||||||
// Walk through the expression to find the materialized temporary itself.
|
// Walk through the expression to find the materialized temporary itself.
|
||||||
SmallVector<const Expr *, 2> CommaLHSs;
|
SmallVector<const Expr *, 2> CommaLHSs;
|
||||||
SmallVector<SubobjectAdjustment, 2> Adjustments;
|
SmallVector<SubobjectAdjustment, 2> Adjustments;
|
||||||
const Expr *Inner = E->GetTemporaryExpr()->
|
const Expr *Inner =
|
||||||
skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
|
E->getSubExpr()->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
|
||||||
|
|
||||||
// If we passed any comma operators, evaluate their LHSs.
|
// If we passed any comma operators, evaluate their LHSs.
|
||||||
for (unsigned I = 0, N = CommaLHSs.size(); I != N; ++I)
|
for (unsigned I = 0, N = CommaLHSs.size(); I != N; ++I)
|
||||||
|
@ -7483,7 +7483,7 @@ bool LValueExprEvaluator::VisitMaterializeTemporaryExpr(
|
||||||
// value for use outside this evaluation.
|
// value for use outside this evaluation.
|
||||||
APValue *Value;
|
APValue *Value;
|
||||||
if (E->getStorageDuration() == SD_Static) {
|
if (E->getStorageDuration() == SD_Static) {
|
||||||
Value = Info.Ctx.getMaterializedTemporaryValue(E, true);
|
Value = E->getOrCreateValue(true);
|
||||||
*Value = APValue();
|
*Value = APValue();
|
||||||
Result.set(E);
|
Result.set(E);
|
||||||
} else {
|
} else {
|
||||||
|
@ -9031,7 +9031,7 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
|
||||||
if (E->isElidable() && !ZeroInit)
|
if (E->isElidable() && !ZeroInit)
|
||||||
if (const MaterializeTemporaryExpr *ME
|
if (const MaterializeTemporaryExpr *ME
|
||||||
= dyn_cast<MaterializeTemporaryExpr>(E->getArg(0)))
|
= dyn_cast<MaterializeTemporaryExpr>(E->getArg(0)))
|
||||||
return Visit(ME->GetTemporaryExpr());
|
return Visit(ME->getSubExpr());
|
||||||
|
|
||||||
if (ZeroInit && !ZeroInitialization(E, T))
|
if (ZeroInit && !ZeroInitialization(E, T))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -4338,7 +4338,7 @@ recurse:
|
||||||
}
|
}
|
||||||
|
|
||||||
case Expr::MaterializeTemporaryExprClass: {
|
case Expr::MaterializeTemporaryExprClass: {
|
||||||
mangleExpression(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr());
|
mangleExpression(cast<MaterializeTemporaryExpr>(E)->getSubExpr());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2235,7 +2235,7 @@ void StmtPrinter::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void StmtPrinter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *Node){
|
void StmtPrinter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *Node){
|
||||||
PrintExpr(Node->GetTemporaryExpr());
|
PrintExpr(Node->getSubExpr());
|
||||||
}
|
}
|
||||||
|
|
||||||
void StmtPrinter::VisitCXXFoldExpr(CXXFoldExpr *E) {
|
void StmtPrinter::VisitCXXFoldExpr(CXXFoldExpr *E) {
|
||||||
|
|
|
@ -1428,7 +1428,7 @@ void CFGBuilder::findConstructionContexts(
|
||||||
if (Layer->getItem().getKind() ==
|
if (Layer->getItem().getKind() ==
|
||||||
ConstructionContextItem::ElidableConstructorKind) {
|
ConstructionContextItem::ElidableConstructorKind) {
|
||||||
auto *MTE = cast<MaterializeTemporaryExpr>(Child);
|
auto *MTE = cast<MaterializeTemporaryExpr>(Child);
|
||||||
findConstructionContexts(withExtraLayer(MTE), MTE->GetTemporaryExpr());
|
findConstructionContexts(withExtraLayer(MTE), MTE->getSubExpr());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1694,7 +1694,7 @@ static QualType getReferenceInitTemporaryType(const Expr *Init,
|
||||||
// Skip through the temporary-materialization expression.
|
// Skip through the temporary-materialization expression.
|
||||||
if (const MaterializeTemporaryExpr *MTE
|
if (const MaterializeTemporaryExpr *MTE
|
||||||
= dyn_cast<MaterializeTemporaryExpr>(Init)) {
|
= dyn_cast<MaterializeTemporaryExpr>(Init)) {
|
||||||
Init = MTE->GetTemporaryExpr();
|
Init = MTE->getSubExpr();
|
||||||
if (FoundMTE)
|
if (FoundMTE)
|
||||||
*FoundMTE = true;
|
*FoundMTE = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -3462,7 +3462,7 @@ CFGBuilder::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,
|
||||||
AddStmtChoice asc) {
|
AddStmtChoice asc) {
|
||||||
findConstructionContexts(
|
findConstructionContexts(
|
||||||
ConstructionContextLayer::create(cfg->getBumpVectorContext(), MTE),
|
ConstructionContextLayer::create(cfg->getBumpVectorContext(), MTE),
|
||||||
MTE->getTemporary());
|
MTE->getSubExpr());
|
||||||
|
|
||||||
return VisitStmt(MTE, asc);
|
return VisitStmt(MTE, asc);
|
||||||
}
|
}
|
||||||
|
@ -4649,7 +4649,7 @@ tryAgain:
|
||||||
// Find the expression whose lifetime needs to be extended.
|
// Find the expression whose lifetime needs to be extended.
|
||||||
E = const_cast<Expr *>(
|
E = const_cast<Expr *>(
|
||||||
cast<MaterializeTemporaryExpr>(E)
|
cast<MaterializeTemporaryExpr>(E)
|
||||||
->GetTemporaryExpr()
|
->getSubExpr()
|
||||||
->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
|
->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
|
||||||
// Visit the skipped comma operator left-hand sides for other temporaries.
|
// Visit the skipped comma operator left-hand sides for other temporaries.
|
||||||
for (const Expr *CommaLHS : CommaLHSs) {
|
for (const Expr *CommaLHS : CommaLHSs) {
|
||||||
|
|
|
@ -847,7 +847,7 @@ void ConsumedStmtVisitor::VisitDeclStmt(const DeclStmt *DeclS) {
|
||||||
|
|
||||||
void ConsumedStmtVisitor::VisitMaterializeTemporaryExpr(
|
void ConsumedStmtVisitor::VisitMaterializeTemporaryExpr(
|
||||||
const MaterializeTemporaryExpr *Temp) {
|
const MaterializeTemporaryExpr *Temp) {
|
||||||
forwardInfo(Temp->GetTemporaryExpr(), Temp);
|
forwardInfo(Temp->getSubExpr(), Temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsumedStmtVisitor::VisitMemberExpr(const MemberExpr *MExpr) {
|
void ConsumedStmtVisitor::VisitMemberExpr(const MemberExpr *MExpr) {
|
||||||
|
|
|
@ -244,8 +244,7 @@ til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) {
|
||||||
case Stmt::CXXBindTemporaryExprClass:
|
case Stmt::CXXBindTemporaryExprClass:
|
||||||
return translate(cast<CXXBindTemporaryExpr>(S)->getSubExpr(), Ctx);
|
return translate(cast<CXXBindTemporaryExpr>(S)->getSubExpr(), Ctx);
|
||||||
case Stmt::MaterializeTemporaryExprClass:
|
case Stmt::MaterializeTemporaryExprClass:
|
||||||
return translate(cast<MaterializeTemporaryExpr>(S)->GetTemporaryExpr(),
|
return translate(cast<MaterializeTemporaryExpr>(S)->getSubExpr(), Ctx);
|
||||||
Ctx);
|
|
||||||
|
|
||||||
// Collect all literals
|
// Collect all literals
|
||||||
case Stmt::CharacterLiteralClass:
|
case Stmt::CharacterLiteralClass:
|
||||||
|
|
|
@ -109,6 +109,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
|
||||||
case Decl::OMPRequires:
|
case Decl::OMPRequires:
|
||||||
case Decl::Empty:
|
case Decl::Empty:
|
||||||
case Decl::Concept:
|
case Decl::Concept:
|
||||||
|
case Decl::LifetimeExtendedTemporary:
|
||||||
// None of these decls require codegen support.
|
// None of these decls require codegen support.
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -417,7 +417,7 @@ static Address createReferenceTemporary(CodeGenFunction &CGF,
|
||||||
|
|
||||||
LValue CodeGenFunction::
|
LValue CodeGenFunction::
|
||||||
EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
|
EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
|
||||||
const Expr *E = M->GetTemporaryExpr();
|
const Expr *E = M->getSubExpr();
|
||||||
|
|
||||||
assert((!M->getExtendingDecl() || !isa<VarDecl>(M->getExtendingDecl()) ||
|
assert((!M->getExtendingDecl() || !isa<VarDecl>(M->getExtendingDecl()) ||
|
||||||
!cast<VarDecl>(M->getExtendingDecl())->isARCPseudoStrong()) &&
|
!cast<VarDecl>(M->getExtendingDecl())->isARCPseudoStrong()) &&
|
||||||
|
|
|
@ -637,7 +637,7 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
void AggExprEmitter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E){
|
void AggExprEmitter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E){
|
||||||
Visit(E->GetTemporaryExpr());
|
Visit(E->getSubExpr());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) {
|
void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) {
|
||||||
|
|
|
@ -1173,7 +1173,7 @@ public:
|
||||||
|
|
||||||
llvm::Constant *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E,
|
llvm::Constant *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E,
|
||||||
QualType T) {
|
QualType T) {
|
||||||
return Visit(E->GetTemporaryExpr(), T);
|
return Visit(E->getSubExpr(), T);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Constant *EmitArrayInitialization(InitListExpr *ILE, QualType T) {
|
llvm::Constant *EmitArrayInitialization(InitListExpr *ILE, QualType T) {
|
||||||
|
@ -2003,8 +2003,8 @@ ConstantLValueEmitter::VisitMaterializeTemporaryExpr(
|
||||||
assert(E->getStorageDuration() == SD_Static);
|
assert(E->getStorageDuration() == SD_Static);
|
||||||
SmallVector<const Expr *, 2> CommaLHSs;
|
SmallVector<const Expr *, 2> CommaLHSs;
|
||||||
SmallVector<SubobjectAdjustment, 2> Adjustments;
|
SmallVector<SubobjectAdjustment, 2> Adjustments;
|
||||||
const Expr *Inner = E->GetTemporaryExpr()
|
const Expr *Inner =
|
||||||
->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
|
E->getSubExpr()->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
|
||||||
return CGM.GetAddrOfGlobalTemporary(E, Inner);
|
return CGM.GetAddrOfGlobalTemporary(E, Inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5011,7 +5011,7 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
|
||||||
// If we're not materializing a subobject of the temporary, keep the
|
// If we're not materializing a subobject of the temporary, keep the
|
||||||
// cv-qualifiers from the type of the MaterializeTemporaryExpr.
|
// cv-qualifiers from the type of the MaterializeTemporaryExpr.
|
||||||
QualType MaterializedType = Init->getType();
|
QualType MaterializedType = Init->getType();
|
||||||
if (Init == E->GetTemporaryExpr())
|
if (Init == E->getSubExpr())
|
||||||
MaterializedType = E->getType();
|
MaterializedType = E->getType();
|
||||||
|
|
||||||
CharUnits Align = getContext().getTypeAlignInChars(MaterializedType);
|
CharUnits Align = getContext().getTypeAlignInChars(MaterializedType);
|
||||||
|
@ -5034,7 +5034,7 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
|
||||||
// temporary. Note that this might have a different value from the value
|
// temporary. Note that this might have a different value from the value
|
||||||
// computed by evaluating the initializer if the surrounding constant
|
// computed by evaluating the initializer if the surrounding constant
|
||||||
// expression modifies the temporary.
|
// expression modifies the temporary.
|
||||||
Value = getContext().getMaterializedTemporaryValue(E, false);
|
Value = E->getOrCreateValue(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try evaluating it now, it might have a constant initializer.
|
// Try evaluating it now, it might have a constant initializer.
|
||||||
|
|
|
@ -546,8 +546,8 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S,
|
||||||
SmallVector<const Expr *, 4> CommaLHS;
|
SmallVector<const Expr *, 4> CommaLHS;
|
||||||
SmallVector<SubobjectAdjustment, 4> Adjustments;
|
SmallVector<SubobjectAdjustment, 4> Adjustments;
|
||||||
const Expr *ExtendedObject =
|
const Expr *ExtendedObject =
|
||||||
MTE->GetTemporaryExpr()->skipRValueSubobjectAdjustments(
|
MTE->getSubExpr()->skipRValueSubobjectAdjustments(CommaLHS,
|
||||||
CommaLHS, Adjustments);
|
Adjustments);
|
||||||
if (ExtendedObject->getType().isDestructedType()) {
|
if (ExtendedObject->getType().isDestructedType()) {
|
||||||
Scopes.push_back(GotoScope(ParentScope, 0,
|
Scopes.push_back(GotoScope(ParentScope, 0,
|
||||||
diag::note_exits_temporary_dtor,
|
diag::note_exits_temporary_dtor,
|
||||||
|
|
|
@ -9270,7 +9270,7 @@ void Sema::CheckMaxUnsignedZero(const CallExpr *Call,
|
||||||
auto IsLiteralZeroArg = [](const Expr* E) -> bool {
|
auto IsLiteralZeroArg = [](const Expr* E) -> bool {
|
||||||
const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E);
|
const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E);
|
||||||
if (!MTE) return false;
|
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) return false;
|
||||||
if (Num->getValue() != 0) return false;
|
if (Num->getValue() != 0) return false;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -7646,7 +7646,7 @@ static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode,
|
||||||
E = E->IgnoreConversionOperator();
|
E = E->IgnoreConversionOperator();
|
||||||
E = E->IgnoreImpCasts();
|
E = E->IgnoreImpCasts();
|
||||||
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) {
|
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) {
|
||||||
E = MTE->GetTemporaryExpr();
|
E = MTE->getSubExpr();
|
||||||
E = E->IgnoreImpCasts();
|
E = E->IgnoreImpCasts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8702,7 +8702,7 @@ namespace {
|
||||||
struct OriginalOperand {
|
struct OriginalOperand {
|
||||||
explicit OriginalOperand(Expr *Op) : Orig(Op), Conversion(nullptr) {
|
explicit OriginalOperand(Expr *Op) : Orig(Op), Conversion(nullptr) {
|
||||||
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Op))
|
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Op))
|
||||||
Op = MTE->GetTemporaryExpr();
|
Op = MTE->getSubExpr();
|
||||||
if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(Op))
|
if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(Op))
|
||||||
Op = BTE->getSubExpr();
|
Op = BTE->getSubExpr();
|
||||||
if (auto *ICE = dyn_cast<ImplicitCastExpr>(Op)) {
|
if (auto *ICE = dyn_cast<ImplicitCastExpr>(Op)) {
|
||||||
|
|
|
@ -6946,8 +6946,8 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
|
||||||
|
|
||||||
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) {
|
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) {
|
||||||
if (Visit(Path, Local(MTE), RK))
|
if (Visit(Path, Local(MTE), RK))
|
||||||
visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(), Visit,
|
visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(), Visit, true,
|
||||||
true, EnableLifetimeWarnings);
|
EnableLifetimeWarnings);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isa<CallExpr>(Init)) {
|
if (isa<CallExpr>(Init)) {
|
||||||
|
@ -7067,9 +7067,8 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
|
||||||
}
|
}
|
||||||
} else if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
|
} else if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
|
||||||
if (MTE->getType().isConstQualified())
|
if (MTE->getType().isConstQualified())
|
||||||
visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(),
|
visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(), Visit,
|
||||||
Visit, true,
|
true, EnableLifetimeWarnings);
|
||||||
EnableLifetimeWarnings);
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}, EnableLifetimeWarnings);
|
}, EnableLifetimeWarnings);
|
||||||
|
|
|
@ -908,7 +908,7 @@ static const Expr *getExprAsWritten(const Expr *E) {
|
||||||
E = FE->getSubExpr();
|
E = FE->getSubExpr();
|
||||||
|
|
||||||
if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
|
if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
|
||||||
E = MTE->GetTemporaryExpr();
|
E = MTE->getSubExpr();
|
||||||
|
|
||||||
while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
|
while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
|
||||||
E = Binder->getSubExpr();
|
E = Binder->getSubExpr();
|
||||||
|
|
|
@ -2724,7 +2724,7 @@ static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef,
|
||||||
if (!MTE)
|
if (!MTE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const Expr *E = MTE->GetTemporaryExpr()->IgnoreImpCasts();
|
const Expr *E = MTE->getSubExpr()->IgnoreImpCasts();
|
||||||
|
|
||||||
// Searching for either UnaryOperator for dereference of a pointer or
|
// Searching for either UnaryOperator for dereference of a pointer or
|
||||||
// CXXOperatorCallExpr for handling iterators.
|
// CXXOperatorCallExpr for handling iterators.
|
||||||
|
@ -2736,7 +2736,7 @@ static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef,
|
||||||
E = ME->getBase();
|
E = ME->getBase();
|
||||||
} else {
|
} else {
|
||||||
const MaterializeTemporaryExpr *MTE = cast<MaterializeTemporaryExpr>(E);
|
const MaterializeTemporaryExpr *MTE = cast<MaterializeTemporaryExpr>(E);
|
||||||
E = MTE->GetTemporaryExpr();
|
E = MTE->getSubExpr();
|
||||||
}
|
}
|
||||||
E = E->IgnoreImpCasts();
|
E = E->IgnoreImpCasts();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3470,7 +3470,7 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
|
||||||
Init = AIL->getCommonExpr();
|
Init = AIL->getCommonExpr();
|
||||||
|
|
||||||
if (MaterializeTemporaryExpr *MTE = dyn_cast<MaterializeTemporaryExpr>(Init))
|
if (MaterializeTemporaryExpr *MTE = dyn_cast<MaterializeTemporaryExpr>(Init))
|
||||||
Init = MTE->GetTemporaryExpr();
|
Init = MTE->getSubExpr();
|
||||||
|
|
||||||
while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init))
|
while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init))
|
||||||
Init = Binder->getSubExpr();
|
Init = Binder->getSubExpr();
|
||||||
|
@ -12180,7 +12180,7 @@ template<typename Derived>
|
||||||
ExprResult
|
ExprResult
|
||||||
TreeTransform<Derived>::TransformMaterializeTemporaryExpr(
|
TreeTransform<Derived>::TransformMaterializeTemporaryExpr(
|
||||||
MaterializeTemporaryExpr *E) {
|
MaterializeTemporaryExpr *E) {
|
||||||
return getDerived().TransformExpr(E->GetTemporaryExpr());
|
return getDerived().TransformExpr(E->getSubExpr());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
|
|
|
@ -401,6 +401,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
|
||||||
case Decl::Decomposition:
|
case Decl::Decomposition:
|
||||||
case Decl::Binding:
|
case Decl::Binding:
|
||||||
case Decl::Concept:
|
case Decl::Concept:
|
||||||
|
case Decl::LifetimeExtendedTemporary:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// These indirectly derive from Redeclarable<T> but are not actually
|
// These indirectly derive from Redeclarable<T> but are not actually
|
||||||
|
|
|
@ -405,6 +405,7 @@ namespace clang {
|
||||||
void VisitBlockDecl(BlockDecl *BD);
|
void VisitBlockDecl(BlockDecl *BD);
|
||||||
void VisitCapturedDecl(CapturedDecl *CD);
|
void VisitCapturedDecl(CapturedDecl *CD);
|
||||||
void VisitEmptyDecl(EmptyDecl *D);
|
void VisitEmptyDecl(EmptyDecl *D);
|
||||||
|
void VisitLifetimeExtendedTemporaryDecl(LifetimeExtendedTemporaryDecl *D);
|
||||||
|
|
||||||
std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
|
std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
|
||||||
|
|
||||||
|
@ -2349,6 +2350,16 @@ void ASTDeclReader::VisitEmptyDecl(EmptyDecl *D) {
|
||||||
VisitDecl(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>
|
std::pair<uint64_t, uint64_t>
|
||||||
ASTDeclReader::VisitDeclContext(DeclContext *DC) {
|
ASTDeclReader::VisitDeclContext(DeclContext *DC) {
|
||||||
uint64_t LexicalOffset = ReadLocalOffset();
|
uint64_t LexicalOffset = ReadLocalOffset();
|
||||||
|
@ -3887,6 +3898,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
|
||||||
case DECL_EMPTY:
|
case DECL_EMPTY:
|
||||||
D = EmptyDecl::CreateDeserialized(Context, ID);
|
D = EmptyDecl::CreateDeserialized(Context, ID);
|
||||||
break;
|
break;
|
||||||
|
case DECL_LIFETIME_EXTENDED_TEMPORARY:
|
||||||
|
D = LifetimeExtendedTemporaryDecl::CreateDeserialized(Context, ID);
|
||||||
|
break;
|
||||||
case DECL_OBJC_TYPE_PARAM:
|
case DECL_OBJC_TYPE_PARAM:
|
||||||
D = ObjCTypeParamDecl::CreateDeserialized(Context, ID);
|
D = ObjCTypeParamDecl::CreateDeserialized(Context, ID);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1900,10 +1900,11 @@ void ASTStmtReader::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
|
||||||
|
|
||||||
void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
|
void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
|
||||||
VisitExpr(E);
|
VisitExpr(E);
|
||||||
|
bool HasMaterialzedDecl = Record.readInt();
|
||||||
|
if (HasMaterialzedDecl)
|
||||||
|
E->State = cast<LifetimeExtendedTemporaryDecl>(Record.readDecl());
|
||||||
|
else
|
||||||
E->State = Record.readSubExpr();
|
E->State = Record.readSubExpr();
|
||||||
auto *VD = ReadDeclAs<ValueDecl>();
|
|
||||||
unsigned ManglingNumber = Record.readInt();
|
|
||||||
E->setExtendingDecl(VD, ManglingNumber);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTStmtReader::VisitCXXFoldExpr(CXXFoldExpr *E) {
|
void ASTStmtReader::VisitCXXFoldExpr(CXXFoldExpr *E) {
|
||||||
|
|
|
@ -124,6 +124,7 @@ namespace clang {
|
||||||
void VisitBlockDecl(BlockDecl *D);
|
void VisitBlockDecl(BlockDecl *D);
|
||||||
void VisitCapturedDecl(CapturedDecl *D);
|
void VisitCapturedDecl(CapturedDecl *D);
|
||||||
void VisitEmptyDecl(EmptyDecl *D);
|
void VisitEmptyDecl(EmptyDecl *D);
|
||||||
|
void VisitLifetimeExtendedTemporaryDecl(LifetimeExtendedTemporaryDecl *D);
|
||||||
|
|
||||||
void VisitDeclContext(DeclContext *DC);
|
void VisitDeclContext(DeclContext *DC);
|
||||||
template <typename T> void VisitRedeclarable(Redeclarable<T> *D);
|
template <typename T> void VisitRedeclarable(Redeclarable<T> *D);
|
||||||
|
@ -1134,6 +1135,17 @@ void ASTDeclWriter::VisitEmptyDecl(EmptyDecl *D) {
|
||||||
Code = serialization::DECL_EMPTY;
|
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) {
|
void ASTDeclWriter::VisitBlockDecl(BlockDecl *D) {
|
||||||
VisitDecl(D);
|
VisitDecl(D);
|
||||||
Record.AddStmt(D->getBody());
|
Record.AddStmt(D->getBody());
|
||||||
|
|
|
@ -1835,9 +1835,11 @@ void ASTStmtWriter::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
|
||||||
|
|
||||||
void ASTStmtWriter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
|
void ASTStmtWriter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
|
||||||
VisitExpr(E);
|
VisitExpr(E);
|
||||||
Record.AddStmt(E->getTemporary());
|
Record.push_back(static_cast<bool>(E->getLifetimeExtendedTemporaryDecl()));
|
||||||
Record.AddDeclRef(E->getExtendingDecl());
|
if (E->getLifetimeExtendedTemporaryDecl())
|
||||||
Record.push_back(E->getManglingNumber());
|
Record.AddDeclRef(E->getLifetimeExtendedTemporaryDecl());
|
||||||
|
else
|
||||||
|
Record.AddStmt(E->getSubExpr());
|
||||||
Code = serialization::EXPR_MATERIALIZE_TEMPORARY;
|
Code = serialization::EXPR_MATERIALIZE_TEMPORARY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -800,8 +800,7 @@ void IteratorChecker::checkPostStmt(const MaterializeTemporaryExpr *MTE,
|
||||||
CheckerContext &C) const {
|
CheckerContext &C) const {
|
||||||
/* Transfer iterator state to temporary objects */
|
/* Transfer iterator state to temporary objects */
|
||||||
auto State = C.getState();
|
auto State = C.getState();
|
||||||
const auto *Pos =
|
const auto *Pos = getIteratorPosition(State, C.getSVal(MTE->getSubExpr()));
|
||||||
getIteratorPosition(State, C.getSVal(MTE->GetTemporaryExpr()));
|
|
||||||
if (!Pos)
|
if (!Pos)
|
||||||
return;
|
return;
|
||||||
State = setIteratorPosition(State, C.getSVal(MTE), *Pos);
|
State = setIteratorPosition(State, C.getSVal(MTE), *Pos);
|
||||||
|
|
|
@ -1427,7 +1427,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
|
||||||
|
|
||||||
bool IsTemporary = false;
|
bool IsTemporary = false;
|
||||||
if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(ArgE)) {
|
if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(ArgE)) {
|
||||||
ArgE = MTE->GetTemporaryExpr();
|
ArgE = MTE->getSubExpr();
|
||||||
IsTemporary = true;
|
IsTemporary = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
|
||||||
ExplodedNode *Pred,
|
ExplodedNode *Pred,
|
||||||
ExplodedNodeSet &Dst) {
|
ExplodedNodeSet &Dst) {
|
||||||
StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
|
StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
|
||||||
const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
|
const Expr *tempExpr = ME->getSubExpr()->IgnoreParens();
|
||||||
ProgramStateRef state = Pred->getState();
|
ProgramStateRef state = Pred->getState();
|
||||||
const LocationContext *LCtx = Pred->getLocationContext();
|
const LocationContext *LCtx = Pred->getLocationContext();
|
||||||
|
|
||||||
|
|
|
@ -6313,6 +6313,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
|
||||||
case Decl::PragmaDetectMismatch:
|
case Decl::PragmaDetectMismatch:
|
||||||
case Decl::UsingPack:
|
case Decl::UsingPack:
|
||||||
case Decl::Concept:
|
case Decl::Concept:
|
||||||
|
case Decl::LifetimeExtendedTemporary:
|
||||||
return C;
|
return C;
|
||||||
|
|
||||||
// Declaration kinds that don't make any sense here, but are
|
// Declaration kinds that don't make any sense here, but are
|
||||||
|
|
Loading…
Reference in New Issue