summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-07-02 19:27:56 +0000
committerJordan Rose <jordan_rose@apple.com>2012-07-02 19:27:56 +0000
commit6bad4905d73ef9634e23709ba79747e83b27881c (patch)
tree7a2fd03e588399deb2060f19255a4d926c804e11 /clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
parent7ab0182e33eee81dfc884e9cf95863bcaf30bab0 (diff)
downloadbcm5719-llvm-6bad4905d73ef9634e23709ba79747e83b27881c.tar.gz
bcm5719-llvm-6bad4905d73ef9634e23709ba79747e83b27881c.zip
[analyzer] Begin replacing ObjCMessage with ObjCMethodCall and friends.
Previously, the CallEvent subclass ObjCMessageInvocation was just a wrapper around the existing ObjCMessage abstraction (over message sends and property accesses). Now, we have abstract CallEvent ObjCMethodCall with subclasses ObjCMessageSend and ObjCPropertyAccess. In addition to removing yet another wrapper object, this should make it easy to add a ObjCSubscriptAccess call event soon. llvm-svn: 159558
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp36
1 files changed, 16 insertions, 20 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
index d35d999b5e9..86630a8c028 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
+++ b/clang/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());
}
OpenPOWER on IntegriCloud