aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/ExprEngine.cpp
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-07-10 22:08:01 +0000
committerJordan Rose <jordan_rose@apple.com>2012-07-10 22:08:01 +0000
commit48b6247804eacc262cc5508e0fbb74ed819fbb6e (patch)
tree16956a95560e5e0ba92ca6453f2f620f38f6cdc3 /lib/StaticAnalyzer/Core/ExprEngine.cpp
parente54cfc7b9990acffd0a8a4ba381717b4bb9f3011 (diff)
[analyzer] Construct stack variables directly in their VarDecl.
Also contains a number of tweaks to inlining that are necessary for constructors and destructors. (I have this enabled on a private branch, but it is very much unstable.) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160023 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngine.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp37
1 files changed, 33 insertions, 4 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 5e0a338084..d78234890b 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -375,6 +375,7 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init,
const FieldDecl *FD = BMI->getAnyMember();
+ // FIXME: This does not work for initializers that call constructors.
SVal FieldLoc = state->getLValue(FD, thisVal);
SVal InitVal = state->getSVal(BMI->getInit(), Pred->getLocationContext());
state = state->bindLoc(FieldLoc, InitVal);
@@ -458,7 +459,27 @@ void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {}
-void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
+static const VarDecl *findDirectConstruction(const DeclStmt *DS,
+ const Expr *Init) {
+ for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end();
+ I != E; ++I) {
+ const VarDecl *Var = dyn_cast<VarDecl>(*I);
+ if (!Var)
+ continue;
+ if (Var->getInit() != Init)
+ continue;
+ // FIXME: We need to decide how copy-elision should work here.
+ if (!Var->isDirectInit())
+ break;
+ if (Var->getType()->isReferenceType())
+ break;
+ return Var;
+ }
+
+ return 0;
+}
+
+void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
ExplodedNodeSet &DstTop) {
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
S->getLocStart(),
@@ -724,10 +745,18 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::CXXTemporaryObjectExprClass:
case Stmt::CXXConstructExprClass: {
const CXXConstructExpr *C = cast<CXXConstructExpr>(S);
- // For block-level CXXConstructExpr, we don't have a destination region.
- // Let VisitCXXConstructExpr() create one.
+ const MemRegion *Target = 0;
+
+ const LocationContext *LCtx = Pred->getLocationContext();
+ const ParentMap &PM = LCtx->getParentMap();
+ if (const DeclStmt *DS = dyn_cast_or_null<DeclStmt>(PM.getParent(C)))
+ if (const VarDecl *Var = findDirectConstruction(DS, C))
+ Target = Pred->getState()->getLValue(Var, LCtx).getAsRegion();
+ // If we don't have a destination region, VisitCXXConstructExpr() will
+ // create one.
+
Bldr.takeNodes(Pred);
- VisitCXXConstructExpr(C, 0, Pred, Dst);
+ VisitCXXConstructExpr(C, Target, Pred, Dst);
Bldr.addNodes(Dst);
break;
}