[cfe-commits] r160530 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h lib/StaticAnalyzer/Core/CheckerManager.cpp lib/StaticAnalyzer/Core/ExprEngineCXX.cpp lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
Anna Zaks
ganna at apple.com
Thu Jul 19 16:38:14 PDT 2012
Author: zaks
Date: Thu Jul 19 18:38:13 2012
New Revision: 160530
URL: http://llvm.org/viewvc/llvm-project?rev=160530&view=rev
Log:
[analyzer] Refactor VisitObjCMessage and VisitCallExpr to rely on the
same implementation for call evaluation.
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?rev=160530&r1=160529&r2=160530&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Thu Jul 19 18:38:13 2012
@@ -467,9 +467,17 @@
ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val,
const ProgramPointTag *tag = 0);
+ /// \brief Create a new state in which the call return value is binded to the
+ /// call origin expression.
+ ProgramStateRef bindReturnValue(const CallEvent &Call,
+ const LocationContext *LCtx,
+ ProgramStateRef State);
+
void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
const SimpleCall &Call);
- void defaultEvalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
+
+ /// \bried Default implementation of call evaluation.
+ void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred,
const CallEvent &Call);
private:
void evalLoadCommon(ExplodedNodeSet &Dst,
@@ -491,8 +499,7 @@
const ProgramPointTag *tag, bool isLoad);
bool shouldInlineDecl(const Decl *D, ExplodedNode *Pred);
- bool inlineCall(ExplodedNodeSet &Dst, const CallEvent &Call,
- ExplodedNode *Pred);
+ bool inlineCall(const CallEvent &Call, ExplodedNode *Pred);
bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC);
};
Modified: cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp?rev=160530&r1=160529&r2=160530&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp Thu Jul 19 18:38:13 2012
@@ -568,8 +568,10 @@
}
// If none of the checkers evaluated the call, ask ExprEngine to handle it.
- if (!anyEvaluated)
- Eng.defaultEvalCall(Dst, Pred, Call);
+ if (!anyEvaluated) {
+ NodeBuilder B(Pred, Dst, Eng.getBuilderContext());
+ Eng.defaultEvalCall(B, Pred, Call);
+ }
}
}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp?rev=160530&r1=160529&r2=160530&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp Thu Jul 19 18:38:13 2012
@@ -54,9 +54,10 @@
Call, *this);
ExplodedNodeSet DstInvalidated;
+ StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currentBuilderContext);
for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
I != E; ++I)
- defaultEvalCall(DstInvalidated, *I, Call);
+ defaultEvalCall(Bldr, *I, Call);
ExplodedNodeSet DstPostCall;
getCheckerManager().runCheckersForPostCall(DstPostCall, DstInvalidated,
@@ -77,9 +78,10 @@
Call, *this);
ExplodedNodeSet DstInvalidated;
+ StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currentBuilderContext);
for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
I != E; ++I)
- defaultEvalCall(DstInvalidated, *I, Call);
+ defaultEvalCall(Bldr, *I, Call);
ExplodedNodeSet DstPostCall;
getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=160530&r1=160529&r2=160530&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Thu Jul 19 18:38:13 2012
@@ -266,8 +266,7 @@
return true;
}
-bool ExprEngine::inlineCall(ExplodedNodeSet &Dst,
- const CallEvent &Call,
+bool ExprEngine::inlineCall(const CallEvent &Call,
ExplodedNode *Pred) {
if (!getAnalysisManager().shouldInlineCall())
return false;
@@ -342,16 +341,16 @@
return true;
}
-static ProgramStateRef getInlineFailedState(ExplodedNode *&N,
+static ProgramStateRef getInlineFailedState(ProgramStateRef State,
const Stmt *CallE) {
- void *ReplayState = N->getState()->get<ReplayWithoutInlining>();
+ void *ReplayState = State->get<ReplayWithoutInlining>();
if (!ReplayState)
return 0;
assert(ReplayState == (const void*)CallE && "Backtracked to the wrong call.");
(void)CallE;
- return N->getState()->remove<ReplayWithoutInlining>();
+ return State->remove<ReplayWithoutInlining>();
}
void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
@@ -419,38 +418,69 @@
Call, *this);
}
-void ExprEngine::defaultEvalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
+ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call,
+ const LocationContext *LCtx,
+ ProgramStateRef State) {
+ const Expr *E = Call.getOriginExpr();
+ if (!E)
+ return State;
+
+ // Some method families have known return values.
+ if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) {
+ switch (Msg->getMethodFamily()) {
+ default:
+ break;
+ case OMF_autorelease:
+ case OMF_retain:
+ case OMF_self: {
+ // These methods return their receivers.
+ return State->BindExpr(E, LCtx, Msg->getReceiverSVal());
+ break;
+ }
+ }
+ }
+
+ // Conjure a symbol if the return value is unknown.
+ QualType ResultTy = Call.getResultType();
+ SValBuilder &SVB = getSValBuilder();
+ unsigned Count = currentBuilderContext->getCurrentBlockCount();
+ SVal R = SVB.getConjuredSymbolVal(0, E, LCtx, ResultTy, Count);
+ return State->BindExpr(E, LCtx, R);
+}
+
+void ExprEngine::defaultEvalCall(NodeBuilder &Bldr, ExplodedNode *Pred,
const CallEvent &Call) {
+ ProgramStateRef State = 0;
+ const Expr *E = Call.getOriginExpr();
+
// Try to inline the call.
// The origin expression here is just used as a kind of checksum;
// for CallEvents that do not have origin expressions, this should still be
// safe.
- const Expr *E = Call.getOriginExpr();
- ProgramStateRef state = getInlineFailedState(Pred, E);
- if (state == 0 && inlineCall(Dst, Call, Pred))
- return;
+ if (!isa<ObjCMethodCall>(Call)) {
+ State = getInlineFailedState(Pred->getState(), E);
+ if (State == 0 && inlineCall(Call, Pred)) {
+ // If we inlined the call, the successor has been manually added onto
+ // the work list and we should not consider it for subsequent call
+ // handling steps.
+ Bldr.takeNodes(Pred);
+ return;
+ }
+ }
// If we can't inline it, handle the return value and invalidate the regions.
- NodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
+ if (State == 0)
+ State = Pred->getState();
// Invalidate any regions touched by the call.
unsigned Count = currentBuilderContext->getCurrentBlockCount();
- if (state == 0)
- state = Pred->getState();
- state = Call.invalidateRegions(Count, state);
-
- // Conjure a symbol value to use as the result.
- if (E) {
- QualType ResultTy = Call.getResultType();
- SValBuilder &SVB = getSValBuilder();
- const LocationContext *LCtx = Pred->getLocationContext();
- SVal RetVal = SVB.getConjuredSymbolVal(0, E, LCtx, ResultTy, Count);
+ State = Call.invalidateRegions(Count, State);
- state = state->BindExpr(E, LCtx, RetVal);
- }
+ // Construct and bind the return value.
+ State = bindReturnValue(Call, Pred->getLocationContext(), State);
// And make the result node.
- Bldr.generateNode(Call.getProgramPoint(), state, Pred);
+ Bldr.generateNode(Call.getProgramPoint(), State, Pred);
}
void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp?rev=160530&r1=160529&r2=160530&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp Thu Jul 19 18:38:13 2012
@@ -158,9 +158,7 @@
for (ExplodedNodeSet::iterator DI = dstGenericPrevisit.begin(),
DE = dstGenericPrevisit.end(); DI != DE; ++DI) {
-
ExplodedNode *Pred = *DI;
- bool RaisesException = false;
if (msg.isInstanceMessage()) {
SVal recVal = msg.getReceiverSVal();
@@ -182,13 +180,19 @@
// Check if the "raise" message was sent.
assert(notNilState);
- if (msg.getSelector() == RaiseSel)
- RaisesException = true;
+ if (msg.getSelector() == RaiseSel) {
+ // If we raise an exception, for now treat it as a sink.
+ // Eventually we will want to handle exceptions properly.
+ Bldr.generateNode(currentStmt, Pred, Pred->getState(), true);
+ continue;
+ }
- // If we raise an exception, for now treat it as a sink.
- // Eventually we will want to handle exceptions properly.
- // Dispatch to plug-in transfer function.
- evalObjCMessage(Bldr, msg, Pred, notNilState, RaisesException);
+ // Generate a transition to non-Nil state.
+ if (notNilState != state)
+ Pred = Bldr.generateNode(currentStmt, Pred, notNilState);
+
+ // Evaluate the call.
+ defaultEvalCall(Bldr, Pred, msg);
}
} else {
// Check for special class methods.
@@ -222,19 +226,25 @@
}
Selector S = msg.getSelector();
+ bool RaisesException = false;
for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i) {
if (S == NSExceptionInstanceRaiseSelectors[i]) {
RaisesException = true;
break;
}
}
+ if (RaisesException) {
+ // If we raise an exception, for now treat it as a sink.
+ // Eventually we will want to handle exceptions properly.
+ Bldr.generateNode(currentStmt, Pred, Pred->getState(), true);
+ continue;
+ }
+
}
}
- // If we raise an exception, for now treat it as a sink.
- // Eventually we will want to handle exceptions properly.
- // Dispatch to plug-in transfer function.
- evalObjCMessage(Bldr, msg, Pred, Pred->getState(), RaisesException);
+ // Evaluate the call.
+ defaultEvalCall(Bldr, Pred, msg);
}
}
@@ -246,48 +256,3 @@
getCheckerManager().runCheckersForPostObjCMessage(Dst, dstPostvisit,
msg, *this);
}
-
-void ExprEngine::evalObjCMessage(StmtNodeBuilder &Bldr,
- const ObjCMethodCall &msg,
- ExplodedNode *Pred,
- ProgramStateRef state,
- bool GenSink) {
- // First handle the return value.
- SVal ReturnValue = UnknownVal();
-
- // Some method families have known return values.
- switch (msg.getMethodFamily()) {
- default:
- break;
- case OMF_autorelease:
- case OMF_retain:
- case OMF_self: {
- // These methods return their receivers.
- ReturnValue = msg.getReceiverSVal();
- break;
- }
- }
-
- const LocationContext *LCtx = Pred->getLocationContext();
- unsigned BlockCount = currentBuilderContext->getCurrentBlockCount();
-
- // If we failed to figure out the return value, use a conjured value instead.
- if (ReturnValue.isUnknown()) {
- SValBuilder &SVB = getSValBuilder();
- QualType ResultTy = msg.getResultType();
- const Expr *CurrentE = cast<Expr>(currentStmt);
- ReturnValue = SVB.getConjuredSymbolVal(NULL, CurrentE, LCtx, ResultTy,
- BlockCount);
- }
-
- // Bind the return value.
- state = state->BindExpr(currentStmt, LCtx, ReturnValue);
-
- // Invalidate the arguments (and the receiver)
- state = msg.invalidateRegions(BlockCount, state);
-
- // And create the new node.
- Bldr.generateNode(currentStmt, Pred, state, GenSink);
- assert(Bldr.hasGeneratedNodes());
-}
-
More information about the cfe-commits
mailing list