aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-06-21 17:03:29 +0000
committerDouglas Gregor <dgregor@apple.com>2011-06-21 17:03:29 +0000
commit03e80030515c800d1ab44125b9052dfffd1bd04c (patch)
tree4ef971a4ce700937aabf19c08f2bfd4f826a7a91 /lib
parent65aa6885818d4b4eea2e5a9d12085b2398148662 (diff)
Introduce a new AST node describing reference binding to temporaries.
MaterializeTemporaryExpr captures a reference binding to a temporary value, making explicit that the temporary value (a prvalue) needs to be materialized into memory so that its address can be used. The intended AST invariant here is that a reference will always bind to a glvalue, and MaterializeTemporaryExpr will be used to convert prvalues into glvalues for that binding to happen. For example, given const int& r = 1.0; The initializer of "r" will be a MaterializeTemporaryExpr whose subexpression is an implicit conversion from the double literal "1.0" to an integer value. IR generation benefits most from this new node, since it was previously guessing (badly) when to materialize temporaries for the purposes of reference binding. There are likely more refactoring and cleanups we could perform there, but the introduction of MaterializeTemporaryExpr fixes PR9565, a case where IR generation would effectively bind a const reference directly to a bitfield in a struct. Addresses <rdar://problem/9552231>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133521 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/Decl.cpp14
-rw-r--r--lib/AST/Expr.cpp53
-rw-r--r--lib/AST/ExprClassification.cpp5
-rw-r--r--lib/AST/ExprConstant.cpp1
-rw-r--r--lib/AST/ItaniumMangle.cpp5
-rw-r--r--lib/AST/StmtPrinter.cpp4
-rw-r--r--lib/AST/StmtProfile.cpp5
-rw-r--r--lib/Analysis/CFG.cpp6
-rw-r--r--lib/CodeGen/CGExpr.cpp18
-rw-r--r--lib/CodeGen/CGExprAgg.cpp6
-rw-r--r--lib/CodeGen/CGExprConstant.cpp4
-rw-r--r--lib/CodeGen/CodeGenFunction.h1
-rw-r--r--lib/Sema/SemaChecking.cpp16
-rw-r--r--lib/Sema/SemaInit.cpp5
-rw-r--r--lib/Sema/TreeTransform.h7
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp10
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp7
-rw-r--r--lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp27
-rw-r--r--lib/StaticAnalyzer/Core/Environment.cpp3
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp24
20 files changed, 195 insertions, 26 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index c2abe1a5a9..cdec049cb1 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -1312,6 +1312,20 @@ void VarDecl::setInit(Expr *I) {
Init = I;
}
+bool VarDecl::extendsLifetimeOfTemporary() const {
+ if (!getType()->isReferenceType())
+ return false;
+
+ const Expr *E = getInit();
+ if (!E)
+ return false;
+
+ if (const ExprWithCleanups *Cleanups = dyn_cast<ExprWithCleanups>(E))
+ E = Cleanups->getSubExpr();
+
+ return isa<MaterializeTemporaryExpr>(E);
+}
+
VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const {
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
return cast<VarDecl>(MSI->getInstantiatedFrom());
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 2f303da7b5..31972bdd23 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1060,7 +1060,12 @@ Expr *CastExpr::getSubExprAsWritten() {
CastExpr *E = this;
do {
SubExpr = E->getSubExpr();
-
+
+ // Skip through reference binding to temporary.
+ if (MaterializeTemporaryExpr *Materialize
+ = dyn_cast<MaterializeTemporaryExpr>(SubExpr))
+ SubExpr = Materialize->GetTemporaryExpr();
+
// Skip any temporary bindings; they're implicit.
if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(SubExpr))
SubExpr = Binder->getSubExpr();
@@ -1568,6 +1573,10 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
return (cast<ImplicitCastExpr>(this)
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
+ case MaterializeTemporaryExprClass:
+ return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr()
+ ->isUnusedResultAWarning(Loc, R1, R2, Ctx);
+
case CXXDefaultArgExprClass:
return (cast<CXXDefaultArgExpr>(this)
->getExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
@@ -1599,6 +1608,9 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {
return cast<UnaryOperator>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
case ImplicitCastExprClass:
return cast<ImplicitCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
+ case MaterializeTemporaryExprClass:
+ return cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr()
+ ->isOBJCGCCandidate(Ctx);
case CStyleCastExprClass:
return cast<CStyleCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
case DeclRefExprClass: {
@@ -1873,7 +1885,8 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
case CXXStaticCastExprClass:
case CXXFunctionalCastExprClass:
case BinaryOperatorClass:
- case CompoundAssignOperatorClass: {
+ case CompoundAssignOperatorClass:
+ case MaterializeTemporaryExprClass: {
CanThrowResult CT = isTypeDependent() ? CT_Dependent : CT_Cannot;
return MergeCanThrow(CT, CanSubExprsThrow(C, this));
}
@@ -1953,6 +1966,12 @@ Expr *Expr::IgnoreParenCasts() {
continue;
}
}
+ if (MaterializeTemporaryExpr *Materialize
+ = dyn_cast<MaterializeTemporaryExpr>(E)) {
+ E = Materialize->GetTemporaryExpr();
+ continue;
+ }
+
return E;
}
}
@@ -1982,6 +2001,10 @@ Expr *Expr::IgnoreParenLValueCasts() {
E = P->getResultExpr();
continue;
}
+ } else if (MaterializeTemporaryExpr *Materialize
+ = dyn_cast<MaterializeTemporaryExpr>(E)) {
+ E = Materialize->GetTemporaryExpr();
+ continue;
}
break;
}
@@ -2011,6 +2034,11 @@ Expr *Expr::IgnoreParenImpCasts() {
continue;
}
}
+ if (MaterializeTemporaryExpr *Materialize
+ = dyn_cast<MaterializeTemporaryExpr>(E)) {
+ E = Materialize->GetTemporaryExpr();
+ continue;
+ }
return E;
}
}
@@ -2074,6 +2102,9 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) {
bool Expr::isDefaultArgument() const {
const Expr *E = this;
+ if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E))
+ E = M->GetTemporaryExpr();
+
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
E = ICE->getSubExprAsWritten();
@@ -2083,6 +2114,9 @@ bool Expr::isDefaultArgument() const {
/// \brief Skip over any no-op casts and any temporary-binding
/// expressions.
static const Expr *skipTemporaryBindingsNoOpCastsAndParens(const Expr *E) {
+ if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E))
+ E = M->GetTemporaryExpr();
+
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
if (ICE->getCastKind() == CK_NoOp)
E = ICE->getSubExpr();
@@ -2170,6 +2204,12 @@ bool Expr::isImplicitCXXThis() const {
}
}
+ if (const MaterializeTemporaryExpr *M
+ = dyn_cast<MaterializeTemporaryExpr>(E)) {
+ E = M->GetTemporaryExpr();
+ continue;
+ }
+
break;
}
@@ -2302,6 +2342,10 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const {
->isConstantInitializer(Ctx, false);
break;
+
+ case MaterializeTemporaryExprClass:
+ return llvm::cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr()
+ ->isConstantInitializer(Ctx, false);
}
return isEvaluatable(Ctx);
}
@@ -2360,6 +2404,9 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
} else if (isa<GNUNullExpr>(this)) {
// The GNU __null extension is always a null pointer constant.
return NPCK_GNUNull;
+ } else if (const MaterializeTemporaryExpr *M
+ = dyn_cast<MaterializeTemporaryExpr>(this)) {
+ return M->GetTemporaryExpr()->isNullPointerConstant(Ctx, NPC);
}
// C++0x nullptr_t is always a null pointer constant.
@@ -3011,6 +3058,8 @@ ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc,
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 = cast<CXXConstructExpr>(e)->getArg(0);
while (const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
e = ice->getSubExpr();
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index 1a1fa91a40..2d824ce8fd 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -341,6 +341,11 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::PackExpansionExprClass:
return ClassifyInternal(Ctx, cast<PackExpansionExpr>(E)->getPattern());
+
+ case Expr::MaterializeTemporaryExprClass:
+ return cast<MaterializeTemporaryExpr>(E)->BoundToLvalueReference()
+ ? Cl::CL_LValue
+ : Cl::CL_XValue;
}
llvm_unreachable("unhandled expression kind in classification");
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 432ffee08d..7d2ea13d0a 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -2787,6 +2787,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::SubstNonTypeTemplateParmPackExprClass:
case Expr::AsTypeExprClass:
case Expr::ObjCIndirectCopyRestoreExprClass:
+ case Expr::MaterializeTemporaryExprClass:
return ICEDiag(2, E->getLocStart());
case Expr::SizeOfPackExprClass:
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 5f0b2a6eff..92e166a34a 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -2591,6 +2591,11 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
}
break;
}
+
+ case Expr::MaterializeTemporaryExprClass: {
+ mangleExpression(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr());
+ break;
+ }
}
}
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index d6a67b13ef..f8edaf7ccf 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1413,6 +1413,10 @@ void StmtPrinter::VisitSubstNonTypeTemplateParmPackExpr(
OS << Node->getParameterPack()->getNameAsString();
}
+void StmtPrinter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *Node){
+ PrintExpr(Node->GetTemporaryExpr());
+}
+
// Obj-C
void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 52b5a103e7..7c1aa9c6f7 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -911,6 +911,11 @@ void StmtProfiler::VisitSubstNonTypeTemplateParmPackExpr(
VisitTemplateArgument(S->getArgumentPack());
}
+void StmtProfiler::VisitMaterializeTemporaryExpr(
+ const MaterializeTemporaryExpr *S) {
+ VisitExpr(S);
+}
+
void StmtProfiler::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
VisitExpr(E);
}
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index 3e540203ea..f231c147f1 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -776,7 +776,7 @@ LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl* VD,
QT = RT->getPointeeType();
if (!QT.isConstQualified())
return Scope;
- if (!VD->getInit() || !VD->getInit()->Classify(*Context).isRValue())
+ if (!VD->extendsLifetimeOfTemporary())
return Scope;
}
@@ -2763,6 +2763,10 @@ tryAgain:
case Stmt::ParenExprClass:
E = cast<ParenExpr>(E)->getSubExpr();
goto tryAgain;
+
+ case Stmt::MaterializeTemporaryExprClass:
+ E = cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr();
+ goto tryAgain;
}
}
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 20ccdb7f9c..d5c18eba70 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -207,6 +207,10 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
const NamedDecl *InitializedDecl) {
ObjCARCReferenceLifetimeType = QualType();
+ // Look through expressions for materialized temporaries (for now).
+ if (isa<MaterializeTemporaryExpr>(E))
+ E = cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr();
+
if (const CXXDefaultArgExpr *DAE = dyn_cast<CXXDefaultArgExpr>(E))
E = DAE->getExpr();
@@ -667,6 +671,9 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
case Expr::CXXConstCastExprClass:
case Expr::ObjCBridgedCastExprClass:
return EmitCastLValue(cast<CastExpr>(E));
+
+ case Expr::MaterializeTemporaryExprClass:
+ return EmitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(E));
}
}
@@ -2067,11 +2074,20 @@ LValue CodeGenFunction::EmitOpaqueValueLValue(const OpaqueValueExpr *e) {
return getOpaqueLValueMapping(e);
}
+LValue CodeGenFunction::EmitMaterializeTemporaryExpr(
+ const MaterializeTemporaryExpr *E) {
+ RValue RV = EmitReferenceBindingToExpr(E->GetTemporaryExpr(),
+ /*InitializedDecl=*/0);
+ return LValue::MakeAddr(RV.getScalarVal(), E->getType(),
+ CGM.getContext().getTypeAlign(E->getType()),
+ CGM.getContext());
+}
+
+
//===--------------------------------------------------------------------===//
// Expression Emission
//===--------------------------------------------------------------------===//
-
RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
ReturnValueSlot ReturnValue) {
if (CGDebugInfo *DI = getDebugInfo()) {
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index b1ac731f21..1cd196a0e4 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -129,7 +129,7 @@ public:
void VisitExprWithCleanups(ExprWithCleanups *E);
void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
void VisitCXXTypeidExpr(CXXTypeidExpr *E) { EmitAggLoadOfLValue(E); }
-
+ void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E);
void VisitOpaqueValueExpr(OpaqueValueExpr *E);
void VisitVAArgExpr(VAArgExpr *E);
@@ -241,6 +241,10 @@ void AggExprEmitter::EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore) {
// Visitor Methods
//===----------------------------------------------------------------------===//
+void AggExprEmitter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E){
+ Visit(E->GetTemporaryExpr());
+}
+
void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) {
EmitFinalDestCopy(e, CGF.getOpaqueLValueMapping(e));
}
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 5184f47537..e88c28737c 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -662,6 +662,10 @@ public:
return Visit(DAE->getExpr());
}
+ llvm::Constant *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
+ return Visit(E->GetTemporaryExpr());
+ }
+
llvm::Constant *EmitArrayInitialization(InitListExpr *ILE) {
unsigned NumInitElements = ILE->getNumInits();
if (NumInitElements == 1 && ILE->getType() == ILE->getInit(0)->getType() &&
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index f34a70c5d9..e72d6ced92 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -1850,6 +1850,7 @@ public:
LValue EmitConditionalOperatorLValue(const AbstractConditionalOperator *E);
LValue EmitCastLValue(const CastExpr *E);
LValue EmitNullInitializationLValue(const CXXScalarValueInitExpr *E);
+ LValue EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e);
llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface,
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 54900e0cf1..1b9fd7769b 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -2205,6 +2205,14 @@ static Expr *EvalAddr(Expr *E, llvm::SmallVectorImpl<DeclRefExpr *> &refVars) {
return NULL;
}
+ case Stmt::MaterializeTemporaryExprClass:
+ if (Expr *Result = EvalAddr(
+ cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
+ refVars))
+ return Result;
+
+ return E;
+
// Everything else: we simply don't reason about them.
default:
return NULL;
@@ -2306,6 +2314,14 @@ do {
return EvalVal(M->getBase(), refVars);
}
+ case Stmt::MaterializeTemporaryExprClass:
+ if (Expr *Result = EvalVal(
+ cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
+ refVars))
+ return Result;
+
+ return E;
+
default:
// Check that we don't return or take the address of a reference to a
// temporary. This is only useful in C++.
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 5bdadc6166..3231455f5a 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -4075,12 +4075,13 @@ InitializationSequence::Perform(Sema &S,
break;
case SK_BindReferenceToTemporary:
- // Reference binding does not have any corresponding ASTs.
-
// Check exception specifications
if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
return ExprError();
+ // Materialize the temporary into memory.
+ CurInit = new (S.Context) MaterializeTemporaryExpr(CurInit.get(),
+ Entity.getType()->isLValueReferenceType());
break;
case SK_ExtraneousCopyToTemporary:
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 121ff00628..b8060277ed 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -7657,6 +7657,13 @@ TreeTransform<Derived>::TransformSubstNonTypeTemplateParmPackExpr(
template<typename Derived>
ExprResult
+TreeTransform<Derived>::TransformMaterializeTemporaryExpr(
+ MaterializeTemporaryExpr *E) {
+ return getDerived().TransformExpr(E->GetTemporaryExpr());
+}
+
+template<typename Derived>
+ExprResult
TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) {
return SemaRef.Owned(E);
}
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index 0af3546223..f6c27d4106 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -189,6 +189,7 @@ namespace clang {
void VisitSizeOfPackExpr(SizeOfPackExpr *E);
void VisitSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E);
+ void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E);
void VisitOpaqueValueExpr(OpaqueValueExpr *E);
// CUDA Expressions
@@ -1426,6 +1427,11 @@ void ASTStmtReader::VisitSubstNonTypeTemplateParmPackExpr(
E->NameLoc = ReadSourceLocation(Record, Idx);
}
+void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
+ VisitExpr(E);
+ E->Temporary = Reader.ReadSubExpr();
+}
+
void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
VisitExpr(E);
Idx++; // skip ID
@@ -2014,6 +2020,10 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
S = new (Context) SubstNonTypeTemplateParmPackExpr(Empty);
break;
+ case EXPR_MATERIALIZE_TEMPORARY:
+ S = new (Context) MaterializeTemporaryExpr(Empty);
+ break;
+
case EXPR_OPAQUE_VALUE: {
unsigned key = Record[ASTStmtReader::NumExprFields];
OpaqueValueExpr *&expr = OpaqueValueExprs[key];
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index c6d182d425..b66fdfa558 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -164,6 +164,7 @@ namespace clang {
void VisitSizeOfPackExpr(SizeOfPackExpr *E);
void VisitSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E);
+ void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E);
void VisitOpaqueValueExpr(OpaqueValueExpr *E);
// CUDA Expressions
@@ -1443,6 +1444,12 @@ void ASTStmtWriter::VisitSubstNonTypeTemplateParmPackExpr(
Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK;
}
+void ASTStmtWriter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
+ VisitExpr(E);
+ Writer.AddStmt(E->Temporary);
+ Code = serialization::EXPR_MATERIALIZE_TEMPORARY;
+}
+
void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
VisitExpr(E);
Record.push_back(Writer.getOpaqueValueID(E));
diff --git a/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp b/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp
index e4e5f54770..de6da4f8c3 100644
--- a/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp
@@ -237,8 +237,11 @@ const GRState *IteratorsChecker::invalidateIterators(const GRState *state,
const GRState *IteratorsChecker::handleAssign(const GRState *state,
const Expr *lexp, const Expr *rexp, const LocationContext *LC) const {
// Skip the cast if present.
- if (isa<ImplicitCastExpr>(lexp))
- lexp = dyn_cast<ImplicitCastExpr>(lexp)->getSubExpr();
+ if (const MaterializeTemporaryExpr *M
+ = dyn_cast<MaterializeTemporaryExpr>(lexp))
+ lexp = M->GetTemporaryExpr();
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(lexp))
+ lexp = ICE->getSubExpr();
SVal sv = state->getSVal(lexp);
const MemRegion *MR = sv.getAsRegion();
if (!MR)
@@ -260,8 +263,11 @@ const GRState *IteratorsChecker::handleAssign(const GRState *state,
const MemRegion *MR, const Expr *rexp, const LocationContext *LC) const {
// Assume unknown until we find something definite.
state = state->set<IteratorState>(MR, RefState::getUnknown());
- if (isa<ImplicitCastExpr>(rexp))
- rexp = dyn_cast<ImplicitCastExpr>(rexp)->getSubExpr();
+ if (const MaterializeTemporaryExpr *M
+ = dyn_cast<MaterializeTemporaryExpr>(rexp))
+ rexp = M->GetTemporaryExpr();
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(rexp))
+ rexp = ICE->getSubExpr();
// Need to handle three cases: MemberCall, copy, copy with addition.
if (const CallExpr *CE = dyn_cast<CallExpr>(rexp)) {
// Handle MemberCall.
@@ -347,8 +353,10 @@ const DeclRefExpr *IteratorsChecker::getDeclRefExpr(const Expr *E) const {
E = CE->getArg(0);
}
}
- if (isa<ImplicitCastExpr>(E))
- E = dyn_cast<ImplicitCastExpr>(E)->getSubExpr();
+ if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E))
+ E = M->GetTemporaryExpr();
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
+ E = ICE->getSubExpr();
// If it isn't one of our types, don't do anything.
if (getTemplateKind(E->getType()) != VectorIteratorKind)
return NULL;
@@ -520,8 +528,11 @@ void IteratorsChecker::checkPreStmt(const DeclStmt *DS,
if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(InitEx)) {
if (CE->getNumArgs() == 1) {
const Expr *E = CE->getArg(0);
- if (isa<ImplicitCastExpr>(E))
- InitEx = dyn_cast<ImplicitCastExpr>(E)->getSubExpr();
+ if (const MaterializeTemporaryExpr *M
+ = dyn_cast<MaterializeTemporaryExpr>(E))
+ E = M->GetTemporaryExpr();
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
+ InitEx = ICE->getSubExpr();
state = handleAssign(state, MR, InitEx,
C.getPredecessor()->getLocationContext());
}
diff --git a/lib/StaticAnalyzer/Core/Environment.cpp b/lib/StaticAnalyzer/Core/Environment.cpp
index 48f126bfd8..3961c7b952 100644
--- a/lib/StaticAnalyzer/Core/Environment.cpp
+++ b/lib/StaticAnalyzer/Core/Environment.cpp
@@ -83,6 +83,9 @@ SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder,
case Stmt::CXXBindTemporaryExprClass:
E = cast<CXXBindTemporaryExpr>(E)->getSubExpr();
continue;
+ case Stmt::MaterializeTemporaryExprClass:
+ E = cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr();
+ continue;
// Handle all other Stmt* using a lookup.
default:
break;
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 21efbac699..4aa5e350bc 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -700,6 +700,16 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
break;
}
+ case Expr::MaterializeTemporaryExprClass: {
+ const MaterializeTemporaryExpr *Materialize
+ = cast<MaterializeTemporaryExpr>(S);
+ if (!Materialize->getType()->isRecordType())
+ CreateCXXTemporaryObject(Materialize->GetTemporaryExpr(), Pred, Dst);
+ else
+ Visit(Materialize->GetTemporaryExpr(), Pred, Dst);
+ break;
+ }
+
case Stmt::InitListExprClass:
VisitInitListExpr(cast<InitListExpr>(S), Pred, Dst);
break;
@@ -2306,17 +2316,9 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
// time a function is called those values may not be current.
ExplodedNodeSet Tmp;
- if (InitEx) {
- if (VD->getType()->isReferenceType() && !InitEx->isLValue()) {
- // If the initializer is C++ record type, it should already has a
- // temp object.
- if (!InitEx->getType()->isRecordType())
- CreateCXXTemporaryObject(InitEx, Pred, Tmp);
- else
- Tmp.Add(Pred);
- } else
- Visit(InitEx, Pred, Tmp);
- } else
+ if (InitEx)
+ Visit(InitEx, Pred, Tmp);
+ else
Tmp.Add(Pred);
ExplodedNodeSet Tmp2;