aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngineObjC.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineObjC.cpp79
1 files changed, 22 insertions, 57 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
index f99fe5ff37..a8e0b3b809 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
@@ -158,9 +158,7 @@ void ExprEngine::VisitObjCMessage(const ObjCMethodCall &msg,
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 @@ void ExprEngine::VisitObjCMessage(const ObjCMethodCall &msg,
// 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 @@ void ExprEngine::VisitObjCMessage(const ObjCMethodCall &msg,
}
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 @@ void ExprEngine::VisitObjCMessage(const ObjCMethodCall &msg,
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());
-}
-