From 03e80030515c800d1ab44125b9052dfffd1bd04c Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 21 Jun 2011 17:03:29 +0000 Subject: 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 . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133521 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/ExprEngine.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'lib/StaticAnalyzer/Core/ExprEngine.cpp') 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(S); + if (!Materialize->getType()->isRecordType()) + CreateCXXTemporaryObject(Materialize->GetTemporaryExpr(), Pred, Dst); + else + Visit(Materialize->GetTemporaryExpr(), Pred, Dst); + break; + } + case Stmt::InitListExprClass: VisitInitListExpr(cast(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; -- cgit v1.2.3-70-g09d2