1294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek//=-- ExprEngineObjC.cpp - ExprEngine support for Objective-C ---*- C++ -*-===// 2294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek// 3294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek// The LLVM Compiler Infrastructure 4294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek// 5294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek// This file is distributed under the University of Illinois Open Source 6294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek// License. See LICENSE.TXT for details. 7294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek// 8294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek//===----------------------------------------------------------------------===// 9294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek// 10294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek// This file defines ExprEngine's support for Objective-C expressions. 11294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek// 12294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek//===----------------------------------------------------------------------===// 13294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 14c35fb7d67d515659ad2325b4f6ec97c9fe64fb63Benjamin Kramer#include "clang/AST/StmtObjC.h" 15294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek#include "clang/StaticAnalyzer/Core/CheckerManager.h" 16f540c54701e3eeb34cb619a3a4eb18f1ac70ef2dJordan Rose#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 17294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 18294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 19294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekusing namespace clang; 20294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekusing namespace ento; 21294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 22294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekvoid ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *Ex, 23294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNode *Pred, 24294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet &Dst) { 258bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = Pred->getState(); 265eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 275eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal baseVal = state->getSVal(Ex->getBase(), LCtx); 28294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek SVal location = state->getLValue(Ex->getDecl(), baseVal); 29294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 30294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet dstIvar; 3166c486f275531df6362b3511fc3af6563561801bTed Kremenek StmtNodeBuilder Bldr(Pred, dstIvar, *currBldrCtx); 325eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, location)); 33294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 34294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Perform the post-condition check of the ObjCIvarRefExpr and store 35294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // the created nodes in 'Dst'. 36294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek getCheckerManager().runCheckersForPostStmt(Dst, dstIvar, Ex, *this); 37294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek} 38294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 39294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekvoid ExprEngine::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S, 40294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNode *Pred, 41294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet &Dst) { 42294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek getCheckerManager().runCheckersForPreStmt(Dst, Pred, S, *this); 43294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek} 44294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 45294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekvoid ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S, 46294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNode *Pred, 47294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet &Dst) { 48294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 49294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // ObjCForCollectionStmts are processed in two places. This method 50294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // handles the case where an ObjCForCollectionStmt* occurs as one of the 51294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // statements within a basic block. This transfer function does two things: 52294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // 53294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // (1) binds the next container value to 'element'. This creates a new 54294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // node in the ExplodedGraph. 55294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // 56294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // (2) binds the value 0/1 to the ObjCForCollectionStmt* itself, indicating 57294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // whether or not the container has any more elements. This value 58294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // will be tested in ProcessBranch. We need to explicitly bind 59294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // this value because a container can contain nil elements. 60294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // 61294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // FIXME: Eventually this logic should actually do dispatches to 62294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // 'countByEnumeratingWithState:objects:count:' (NSFastEnumeration). 63294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // This will require simulating a temporary NSFastEnumerationState, either 64294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // through an SVal or through the use of MemRegions. This value can 65294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // be affixed to the ObjCForCollectionStmt* instead of 0/1; when the loop 66294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // terminates we reclaim the temporary (it goes out of scope) and we 67294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // we can test if the SVal is 0 or if the MemRegion is null (depending 68294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // on what approach we take). 69294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // 70294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // For now: simulate (1) by assigning either a symbol or nil if the 71294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // container is empty. Thus this transfer function will by default 72294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // result in state splitting. 73ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks 74294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const Stmt *elem = S->getElement(); 758bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = Pred->getState(); 76294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek SVal elementV; 77294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 78294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (const DeclStmt *DS = dyn_cast<DeclStmt>(elem)) { 79294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const VarDecl *elemD = cast<VarDecl>(DS->getSingleDecl()); 80294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek assert(elemD->getInit() == 0); 81294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek elementV = state->getLValue(elemD, Pred->getLocationContext()); 82294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 83294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek else { 845eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek elementV = state->getSVal(elem, Pred->getLocationContext()); 85294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 86294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 87294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet dstLocation; 88bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek evalLocation(dstLocation, S, elem, Pred, state, elementV, NULL, false); 891895a0a6936001374f66adbdfcf8abe5edf912eaJordan Rose 901895a0a6936001374f66adbdfcf8abe5edf912eaJordan Rose ExplodedNodeSet Tmp; 9166c486f275531df6362b3511fc3af6563561801bTed Kremenek StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx); 921895a0a6936001374f66adbdfcf8abe5edf912eaJordan Rose 93294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek for (ExplodedNodeSet::iterator NI = dstLocation.begin(), 94294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek NE = dstLocation.end(); NI!=NE; ++NI) { 95294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek Pred = *NI; 968bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = Pred->getState(); 975eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 98294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 99294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Handle the case where the container still has elements. 100294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek SVal TrueV = svalBuilder.makeTruthVal(1); 1018bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef hasElems = state->BindExpr(S, LCtx, TrueV); 102294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 103294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Handle the case where the container has no elements. 104294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek SVal FalseV = svalBuilder.makeTruthVal(0); 1058bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef noElems = state->BindExpr(S, LCtx, FalseV); 106294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 107294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (loc::MemRegionVal *MV = dyn_cast<loc::MemRegionVal>(&elementV)) 108294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (const TypedValueRegion *R = 109294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek dyn_cast<TypedValueRegion>(MV->getRegion())) { 110294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // FIXME: The proper thing to do is to really iterate over the 111294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // container. We will do this with dispatch logic to the store. 112294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // For now, just 'conjure' up a symbolic value. 113294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek QualType T = R->getValueType(); 114294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek assert(Loc::isLocType(T)); 11566c486f275531df6362b3511fc3af6563561801bTed Kremenek SymbolRef Sym = SymMgr.conjureSymbol(elem, LCtx, T, 11666c486f275531df6362b3511fc3af6563561801bTed Kremenek currBldrCtx->blockCount()); 117294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek SVal V = svalBuilder.makeLoc(Sym); 118294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek hasElems = hasElems->bindLoc(elementV, V); 119294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 120294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Bind the location to 'nil' on the false branch. 121294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek SVal nilV = svalBuilder.makeIntVal(0, T); 122294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek noElems = noElems->bindLoc(elementV, nilV); 123294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 124294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 125294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Create the new nodes. 126ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks Bldr.generateNode(S, Pred, hasElems); 127ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks Bldr.generateNode(S, Pred, noElems); 128294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 1291895a0a6936001374f66adbdfcf8abe5edf912eaJordan Rose 1301895a0a6936001374f66adbdfcf8abe5edf912eaJordan Rose // Finally, run any custom checkers. 1311895a0a6936001374f66adbdfcf8abe5edf912eaJordan Rose // FIXME: Eventually all pre- and post-checks should live in VisitStmt. 1321895a0a6936001374f66adbdfcf8abe5edf912eaJordan Rose getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this); 133294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek} 134294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 1356c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rosestatic bool isSubclass(const ObjCInterfaceDecl *Class, IdentifierInfo *II) { 1366c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose if (!Class) 1376c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose return false; 1386c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose if (Class->getIdentifier() == II) 1396c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose return true; 1406c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose return isSubclass(Class->getSuperClass(), II); 1416c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose} 1426c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose 143d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rosevoid ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME, 144294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNode *Pred, 145294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet &Dst) { 146d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose CallEventManager &CEMgr = getStateManager().getCallEventManager(); 147d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose CallEventRef<ObjCMethodCall> Msg = 148d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose CEMgr.getObjCMethodCall(ME, Pred->getState(), Pred->getLocationContext()); 149d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose 150294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Handle the previsits checks. 151294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet dstPrevisit; 15296479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose getCheckerManager().runCheckersForPreObjCMessage(dstPrevisit, Pred, 153d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose *Msg, *this); 15496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose ExplodedNodeSet dstGenericPrevisit; 15596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose getCheckerManager().runCheckersForPreCall(dstGenericPrevisit, dstPrevisit, 156d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose *Msg, *this); 15796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose 158294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Proceed with evaluate the message expression. 159294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet dstEval; 16066c486f275531df6362b3511fc3af6563561801bTed Kremenek StmtNodeBuilder Bldr(dstGenericPrevisit, dstEval, *currBldrCtx); 161ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks 16296479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose for (ExplodedNodeSet::iterator DI = dstGenericPrevisit.begin(), 16396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose DE = dstGenericPrevisit.end(); DI != DE; ++DI) { 164294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNode *Pred = *DI; 165d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose ProgramStateRef State = Pred->getState(); 166d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose CallEventRef<ObjCMethodCall> UpdatedMsg = Msg.cloneWithState(State); 167294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 168d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose if (UpdatedMsg->isInstanceMessage()) { 169d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose SVal recVal = UpdatedMsg->getReceiverSVal(); 170294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (!recVal.isUndef()) { 171294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Bifurcate the state into nil and non-nil ones. 172294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal); 173294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 1748bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef notNilState, nilState; 175d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose llvm::tie(notNilState, nilState) = State->assume(receiverVal); 176294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 177294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // There are three cases: can be nil or non-nil, must be nil, must be 178294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // non-nil. We ignore must be nil, and merge the rest two into non-nil. 179cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose // FIXME: This ignores many potential bugs (<rdar://problem/11733396>). 180cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose // Revisit once we have lazier constraints. 181294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (nilState && !notNilState) { 182294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek continue; 183294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 184294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 185294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Check if the "raise" message was sent. 186294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek assert(notNilState); 187d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose if (Msg->getSelector() == RaiseSel) { 188e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks // If we raise an exception, for now treat it as a sink. 189e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks // Eventually we will want to handle exceptions properly. 19066c486f275531df6362b3511fc3af6563561801bTed Kremenek Bldr.generateSink(currStmt, Pred, State); 191e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks continue; 192e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks } 193294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 194e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks // Generate a transition to non-Nil state. 19582f2ad456a82da1b9cb7ddfc994c8f5fa44b59e6Jordan Rose if (notNilState != State) { 19666c486f275531df6362b3511fc3af6563561801bTed Kremenek Pred = Bldr.generateNode(currStmt, Pred, notNilState); 19782f2ad456a82da1b9cb7ddfc994c8f5fa44b59e6Jordan Rose assert(Pred && "Should have cached out already!"); 19882f2ad456a82da1b9cb7ddfc994c8f5fa44b59e6Jordan Rose } 199294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 200cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose } else { 2016c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose // Check for special class methods. 202d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose if (const ObjCInterfaceDecl *Iface = Msg->getReceiverInterface()) { 2036c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose if (!NSExceptionII) { 204294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ASTContext &Ctx = getContext(); 2056c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose NSExceptionII = &Ctx.Idents.get("NSException"); 206294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 207294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 2086c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose if (isSubclass(Iface, NSExceptionII)) { 2096c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose enum { NUM_RAISE_SELECTORS = 2 }; 2106c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose 2116c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose // Lazily create a cache of the selectors. 2126c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose if (!NSExceptionInstanceRaiseSelectors) { 2136c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose ASTContext &Ctx = getContext(); 2146c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose NSExceptionInstanceRaiseSelectors = 2156c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose new Selector[NUM_RAISE_SELECTORS]; 2166c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose SmallVector<IdentifierInfo*, NUM_RAISE_SELECTORS> II; 2176c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose unsigned idx = 0; 2186c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose 2196c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose // raise:format: 2206c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose II.push_back(&Ctx.Idents.get("raise")); 2216c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose II.push_back(&Ctx.Idents.get("format")); 2226c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose NSExceptionInstanceRaiseSelectors[idx++] = 2236c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose Ctx.Selectors.getSelector(II.size(), &II[0]); 2246c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose 2256c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose // raise:format:arguments: 2266c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose II.push_back(&Ctx.Idents.get("arguments")); 2276c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose NSExceptionInstanceRaiseSelectors[idx++] = 2286c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose Ctx.Selectors.getSelector(II.size(), &II[0]); 2296c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose } 2306c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose 231d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose Selector S = Msg->getSelector(); 232e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks bool RaisesException = false; 2336c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i) { 2346c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose if (S == NSExceptionInstanceRaiseSelectors[i]) { 2356c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose RaisesException = true; 2366c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose break; 2376c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose } 238294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 239e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks if (RaisesException) { 240e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks // If we raise an exception, for now treat it as a sink. 241e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks // Eventually we will want to handle exceptions properly. 24266c486f275531df6362b3511fc3af6563561801bTed Kremenek Bldr.generateSink(currStmt, Pred, Pred->getState()); 243e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks continue; 244e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks } 245e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks 2466c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose } 247294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 248294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 2499dc5167e4017ef4c8b327abb6f72225eec2e0f19Anna Zaks 25082f2ad456a82da1b9cb7ddfc994c8f5fa44b59e6Jordan Rose defaultEvalCall(Bldr, Pred, *UpdatedMsg); 251294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 252294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 25396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose ExplodedNodeSet dstPostvisit; 254d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose getCheckerManager().runCheckersForPostCall(dstPostvisit, dstEval, 255d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose *Msg, *this); 25696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose 257294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Finally, perform the post-condition check of the ObjCMessageExpr and store 258294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // the created nodes in 'Dst'. 25996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose getCheckerManager().runCheckersForPostObjCMessage(Dst, dstPostvisit, 260d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose *Msg, *this); 261294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek} 262