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.cpp36
1 files changed, 16 insertions, 20 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
index d35d999b5e..86630a8c02 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
@@ -141,7 +141,7 @@ static bool isSubclass(const ObjCInterfaceDecl *Class, IdentifierInfo *II) {
return isSubclass(Class->getSuperClass(), II);
}
-void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
+void ExprEngine::VisitObjCMessage(const ObjCMethodCall &msg,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
@@ -160,18 +160,20 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
ExplodedNode *Pred = *DI;
bool RaisesException = false;
- if (const Expr *Receiver = msg.getInstanceReceiver()) {
- ProgramStateRef state = Pred->getState();
- SVal recVal = state->getSVal(Receiver, Pred->getLocationContext());
+ if (msg.isInstanceMessage()) {
+ SVal recVal = msg.getReceiverSVal();
if (!recVal.isUndef()) {
// Bifurcate the state into nil and non-nil ones.
DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
+ ProgramStateRef state = Pred->getState();
ProgramStateRef notNilState, nilState;
llvm::tie(notNilState, nilState) = state->assume(receiverVal);
// There are three cases: can be nil or non-nil, must be nil, must be
// non-nil. We ignore must be nil, and merge the rest two into non-nil.
+ // FIXME: This ignores many potential bugs (<rdar://problem/11733396>).
+ // Revisit once we have lazier constraints.
if (nilState && !notNilState) {
continue;
}
@@ -186,12 +188,9 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
// Dispatch to plug-in transfer function.
evalObjCMessage(Bldr, msg, Pred, notNilState, RaisesException);
}
- } else if (const ObjCInterfaceDecl *Iface = msg.getReceiverInterface()) {
- // Note that this branch also handles messages to super, not just
- // class methods!
-
+ } else {
// Check for special class methods.
- if (!msg.isInstanceMessage()) {
+ if (const ObjCInterfaceDecl *Iface = msg.getReceiverInterface()) {
if (!NSExceptionII) {
ASTContext &Ctx = getContext();
NSExceptionII = &Ctx.Idents.get("NSException");
@@ -243,13 +242,10 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
}
void ExprEngine::evalObjCMessage(StmtNodeBuilder &Bldr,
- const ObjCMessage &msg,
+ const ObjCMethodCall &msg,
ExplodedNode *Pred,
ProgramStateRef state,
bool GenSink) {
- const LocationContext *LCtx = Pred->getLocationContext();
- unsigned BlockCount = currentBuilderContext->getCurrentBlockCount();
-
// First handle the return value.
SVal ReturnValue = UnknownVal();
@@ -261,17 +257,18 @@ void ExprEngine::evalObjCMessage(StmtNodeBuilder &Bldr,
case OMF_retain:
case OMF_self: {
// These methods return their receivers.
- const Expr *ReceiverE = msg.getInstanceReceiver();
- if (ReceiverE)
- ReturnValue = state->getSVal(ReceiverE, LCtx);
+ 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(getContext());
+ QualType ResultTy = msg.getResultType();
const Expr *CurrentE = cast<Expr>(currentStmt);
ReturnValue = SVB.getConjuredSymbolVal(NULL, CurrentE, LCtx, ResultTy,
BlockCount);
@@ -281,11 +278,10 @@ void ExprEngine::evalObjCMessage(StmtNodeBuilder &Bldr,
state = state->BindExpr(currentStmt, LCtx, ReturnValue);
// Invalidate the arguments (and the receiver)
- ObjCMessageInvocation Invocation(msg, state, LCtx);
- state = Invocation.invalidateRegions(BlockCount);
+ state = msg.invalidateRegions(BlockCount, state);
// And create the new node.
- Bldr.generateNode(msg.getMessageExpr(), Pred, state, GenSink);
+ Bldr.generateNode(msg.getOriginExpr(), Pred, state, GenSink);
assert(Bldr.hasGeneratedNodes());
}