[cfe-commits] r160023 - in /cfe/trunk/lib/StaticAnalyzer/Core: ExprEngine.cpp ExprEngineC.cpp ExprEngineCallAndReturn.cpp Store.cpp
Jordan Rose
jordan_rose at apple.com
Tue Jul 10 15:08:01 PDT 2012
Author: jrose
Date: Tue Jul 10 17:08:01 2012
New Revision: 160023
URL: http://llvm.org/viewvc/llvm-project?rev=160023&view=rev
Log:
[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.)
Modified:
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=160023&r1=160022&r2=160023&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Tue Jul 10 17:08:01 2012
@@ -375,6 +375,7 @@
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 @@
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 @@
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;
}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=160023&r1=160022&r2=160023&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Tue Jul 10 17:08:01 2012
@@ -454,30 +454,37 @@
if (const Expr *InitEx = VD->getInit()) {
SVal InitVal = state->getSVal(InitEx, Pred->getLocationContext());
-
- // We bound the temp obj region to the CXXConstructExpr. Now recover
- // the lazy compound value when the variable is not a reference.
- if (AMgr.getLangOpts().CPlusPlus && VD->getType()->isRecordType() &&
- !VD->getType()->isReferenceType() && isa<loc::MemRegionVal>(InitVal)){
- InitVal = state->getSVal(cast<loc::MemRegionVal>(InitVal).getRegion());
- assert(isa<nonloc::LazyCompoundVal>(InitVal));
- }
-
- // Recover some path-sensitivity if a scalar value evaluated to
- // UnknownVal.
- if (InitVal.isUnknown()) {
- QualType Ty = InitEx->getType();
- if (InitEx->isGLValue()) {
- Ty = getContext().getPointerType(Ty);
- }
- InitVal = svalBuilder.getConjuredSymbolVal(NULL, InitEx, LC, Ty,
- currentBuilderContext->getCurrentBlockCount());
+ if (InitVal == state->getLValue(VD, LC)) {
+ // We constructed the object directly in the variable.
+ // No need to bind anything.
+ B.generateNode(DS, N, state);
+ } else {
+ // We bound the temp obj region to the CXXConstructExpr. Now recover
+ // the lazy compound value when the variable is not a reference.
+ // FIXME: This is probably not correct for most constructors!
+ if (AMgr.getLangOpts().CPlusPlus && VD->getType()->isRecordType() &&
+ !VD->getType()->isReferenceType() && isa<loc::MemRegionVal>(InitVal)){
+ InitVal = state->getSVal(cast<loc::MemRegionVal>(InitVal).getRegion());
+ assert(isa<nonloc::LazyCompoundVal>(InitVal));
+ }
+
+ // Recover some path-sensitivity if a scalar value evaluated to
+ // UnknownVal.
+ if (InitVal.isUnknown()) {
+ QualType Ty = InitEx->getType();
+ if (InitEx->isGLValue()) {
+ Ty = getContext().getPointerType(Ty);
+ }
+
+ InitVal = svalBuilder.getConjuredSymbolVal(NULL, InitEx, LC, Ty,
+ currentBuilderContext->getCurrentBlockCount());
+ }
+ B.takeNodes(N);
+ ExplodedNodeSet Dst2;
+ evalBind(Dst2, DS, N, state->getLValue(VD, LC), InitVal, true);
+ B.addNodes(Dst2);
}
- B.takeNodes(N);
- ExplodedNodeSet Dst2;
- evalBind(Dst2, DS, N, state->getLValue(VD, LC), InitVal, true);
- B.addNodes(Dst2);
}
else {
B.generateNode(DS, N,state->bindDeclWithNoInit(state->getRegion(VD, LC)));
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=160023&r1=160022&r2=160023&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Tue Jul 10 17:08:01 2012
@@ -137,7 +137,7 @@
if (const ReturnStmt *RS = dyn_cast_or_null<ReturnStmt>(LastSt)) {
const LocationContext *LCtx = CEBNode->getLocationContext();
SVal V = state->getSVal(RS, LCtx);
- state = state->BindExpr(CE, callerCtx, V);
+ state = state->BindExpr(CE, calleeCtx->getParent(), V);
}
// Bind the constructed object value to CXXConstructExpr.
@@ -147,18 +147,10 @@
SVal ThisV = state->getSVal(This);
// Always bind the region to the CXXConstructExpr.
- state = state->BindExpr(CCE, CEBNode->getLocationContext(), ThisV);
+ state = state->BindExpr(CCE, calleeCtx->getParent(), ThisV);
}
}
- static SimpleProgramPointTag retValBindTag("ExprEngine : Bind Return Value");
- PostStmt Loc(LastSt, calleeCtx, &retValBindTag);
- bool isNew;
- ExplodedNode *BindedRetNode = G.getNode(Loc, state, false, &isNew);
- BindedRetNode->addPredecessor(CEBNode, G);
- if (!isNew)
- return;
-
// Step 3: BindedRetNode -> CleanedNodes
// If we can find a statement and a block in the inlined function, run remove
// dead bindings before returning from the call. This is important to ensure
@@ -166,6 +158,14 @@
// they occurred.
ExplodedNodeSet CleanedNodes;
if (LastSt && Blk) {
+ static SimpleProgramPointTag retValBind("ExprEngine : Bind Return Value");
+ PostStmt Loc(LastSt, calleeCtx, &retValBind);
+ bool isNew;
+ ExplodedNode *BindedRetNode = G.getNode(Loc, state, false, &isNew);
+ BindedRetNode->addPredecessor(CEBNode, G);
+ if (!isNew)
+ return;
+
NodeBuilderContext Ctx(getCoreEngine(), Blk, BindedRetNode);
currentBuilderContext = &Ctx;
// Here, we call the Symbol Reaper with 0 statement and caller location
@@ -186,7 +186,8 @@
// CleanedNodes -> CEENode
CallExitEnd Loc(calleeCtx, callerCtx);
bool isNew;
- ExplodedNode *CEENode = G.getNode(Loc, (*I)->getState(), false, &isNew);
+ ProgramStateRef CEEState = (*I == CEBNode) ? state : (*I)->getState();
+ ExplodedNode *CEENode = G.getNode(Loc, CEEState, false, &isNew);
CEENode->addPredecessor(*I, G);
if (!isNew)
return;
@@ -201,8 +202,12 @@
SaveAndRestore<unsigned> CBISave(currentStmtIdx, calleeCtx->getIndex());
// FIXME: This needs to call PostCall.
+ // FIXME: If/when we inline Objective-C messages, this also needs to call
+ // PostObjCMessage.
if (CE)
getCheckerManager().runCheckersForPostStmt(Dst, CEENode, CE, *this, true);
+ else
+ Dst.Add(CEENode);
// Enqueue the next element in the block.
for (ExplodedNodeSet::iterator PSI = Dst.begin(), PSE = Dst.end();
Modified: cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp?rev=160023&r1=160022&r2=160023&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp Tue Jul 10 17:08:01 2012
@@ -47,7 +47,7 @@
// FIXME: We will eventually want to generalize this to handle other non-
// parameter arguments besides 'this' (such as 'self' for ObjC methods).
SVal ThisVal = Call.getCXXThisVal();
- if (!ThisVal.isUndef()) {
+ if (isa<DefinedSVal>(ThisVal)) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(Call.getDecl());
loc::MemRegionVal ThisRegion = svalBuilder.getCXXThis(MD, LCtx);
Store = Bind(Store.getStore(), ThisRegion, ThisVal);
More information about the cfe-commits
mailing list