From: Argyrios Kyrtzidis Date: Tue, 25 Jan 2011 00:03:57 +0000 (+0000) Subject: [analyzer] Introduce ExprEngine::VisitObjCMessage for handling general ObjCMessages... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5286e2ddfd8332520de4c076e49991d6fe557adb;p=clang [analyzer] Introduce ExprEngine::VisitObjCMessage for handling general ObjCMessages (both message expressions and property access) and use it in ExprEngine::VisitObjCMessageExpr. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124160 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/StaticAnalyzer/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/PathSensitive/ExprEngine.h index 5617bf1c3b..8a9a9f2cd7 100644 --- a/include/clang/StaticAnalyzer/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/PathSensitive/ExprEngine.h @@ -391,6 +391,8 @@ public: /// VisitObjCMessageExpr - Transfer function for ObjC message expressions. void VisitObjCMessageExpr(const ObjCMessageExpr* ME, ExplodedNode* Pred, ExplodedNodeSet& Dst); + void VisitObjCMessage(const ObjCMessage &msg, ExplodedNodeSet &Src, + ExplodedNodeSet& Dst); /// VisitReturnStmt - Transfer function logic for return statements. void VisitReturnStmt(const ReturnStmt* R, ExplodedNode* Pred, diff --git a/lib/StaticAnalyzer/Checkers/ExprEngine.cpp b/lib/StaticAnalyzer/Checkers/ExprEngine.cpp index 6932f4a717..9a74bd99a1 100644 --- a/lib/StaticAnalyzer/Checkers/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Checkers/ExprEngine.cpp @@ -2300,9 +2300,16 @@ void ExprEngine::VisitObjCMessageExpr(const ObjCMessageExpr* ME, WL.push_back(ObjCMsgWLItem(Item.I, *NI)); } - // Now that the arguments are processed, handle the previsits checks. + // Now that the arguments are processed, handle the ObjC message. + VisitObjCMessage(ME, ArgsEvaluated, Dst); +} + +void ExprEngine::VisitObjCMessage(const ObjCMessage &msg, + ExplodedNodeSet &Src, ExplodedNodeSet& Dst) { + + // Handle the previsits checks. ExplodedNodeSet DstPrevisit; - CheckerVisitObjCMessage(ME, DstPrevisit, ArgsEvaluated, /*isPreVisit=*/true); + CheckerVisitObjCMessage(msg, DstPrevisit, Src, /*isPreVisit=*/true); // Proceed with evaluate the message expression. ExplodedNodeSet dstEval; @@ -2310,13 +2317,13 @@ void ExprEngine::VisitObjCMessageExpr(const ObjCMessageExpr* ME, for (ExplodedNodeSet::iterator DI = DstPrevisit.begin(), DE = DstPrevisit.end(); DI != DE; ++DI) { - Pred = *DI; + ExplodedNode *Pred = *DI; bool RaisesException = false; unsigned oldSize = dstEval.size(); SaveAndRestore OldSink(Builder->BuildSinks); SaveOr OldHasGen(Builder->hasGeneratedNode); - if (const Expr *Receiver = ME->getInstanceReceiver()) { + if (const Expr *Receiver = msg.getInstanceReceiver()) { const GRState *state = GetState(Pred); // Bifurcate the state into nil and non-nil ones. @@ -2329,13 +2336,13 @@ void ExprEngine::VisitObjCMessageExpr(const ObjCMessageExpr* ME, // There are three cases: can be nil or non-nil, must be nil, must be // non-nil. We handle must be nil, and merge the rest two into non-nil. if (nilState && !notNilState) { - CheckerEvalNilReceiver(ME, dstEval, nilState, Pred); + CheckerEvalNilReceiver(msg, dstEval, nilState, Pred); continue; } // Check if the "raise" message was sent. assert(notNilState); - if (ME->getSelector() == RaiseSel) + if (msg.getSelector() == RaiseSel) RaisesException = true; // Check if we raise an exception. For now treat these as sinks. @@ -2344,11 +2351,11 @@ void ExprEngine::VisitObjCMessageExpr(const ObjCMessageExpr* ME, Builder->BuildSinks = true; // Dispatch to plug-in transfer function. - evalObjCMessage(dstEval, ME, Pred, notNilState); + evalObjCMessage(dstEval, msg, Pred, notNilState); } - else if (ObjCInterfaceDecl *Iface = ME->getReceiverInterface()) { + else if (const ObjCInterfaceDecl *Iface = msg.getReceiverInterface()) { IdentifierInfo* ClsName = Iface->getIdentifier(); - Selector S = ME->getSelector(); + Selector S = msg.getSelector(); // Check for special instance methods. if (!NSExceptionII) { @@ -2392,19 +2399,19 @@ void ExprEngine::VisitObjCMessageExpr(const ObjCMessageExpr* ME, Builder->BuildSinks = true; // Dispatch to plug-in transfer function. - evalObjCMessage(dstEval, ME, Pred, Builder->GetState(Pred)); + evalObjCMessage(dstEval, msg, Pred, Builder->GetState(Pred)); } // Handle the case where no nodes where generated. Auto-generate that // contains the updated state if we aren't generating sinks. if (!Builder->BuildSinks && dstEval.size() == oldSize && !Builder->hasGeneratedNode) - MakeNode(dstEval, ME, Pred, GetState(Pred)); + MakeNode(dstEval, msg.getOriginExpr(), Pred, GetState(Pred)); } // Finally, perform the post-condition check of the ObjCMessageExpr and store // the created nodes in 'Dst'. - CheckerVisitObjCMessage(ME, Dst, dstEval, /*isPreVisit=*/false); + CheckerVisitObjCMessage(msg, Dst, dstEval, /*isPreVisit=*/false); } //===----------------------------------------------------------------------===//