ExprEngineObjC.cpp revision cde8cdbd6a662c636164465ad309b5f17ff01064
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" 16740d490593e0de8732a697c9f77b90ddd463863bJordan Rose#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h" 17294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 18d1e5a89226da79f7e6f43d40facc46abda9e5245Jordy Rose#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" 19294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 20294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekusing namespace clang; 21294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekusing namespace ento; 22294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 23294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekvoid ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *Ex, 24294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNode *Pred, 25294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet &Dst) { 268bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = Pred->getState(); 275eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 285eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal baseVal = state->getSVal(Ex->getBase(), LCtx); 29294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek SVal location = state->getLValue(Ex->getDecl(), baseVal); 30294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 31294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet dstIvar; 32aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks StmtNodeBuilder Bldr(Pred, dstIvar, *currentBuilderContext); 335eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, location)); 34294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 35294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Perform the post-condition check of the ObjCIvarRefExpr and store 36294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // the created nodes in 'Dst'. 37294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek getCheckerManager().runCheckersForPostStmt(Dst, dstIvar, Ex, *this); 38294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek} 39294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 40294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekvoid ExprEngine::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S, 41294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNode *Pred, 42294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet &Dst) { 43294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek getCheckerManager().runCheckersForPreStmt(Dst, Pred, S, *this); 44294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek} 45294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 46294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekvoid ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S, 47294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNode *Pred, 48294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet &Dst) { 49294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 50294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // ObjCForCollectionStmts are processed in two places. This method 51294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // handles the case where an ObjCForCollectionStmt* occurs as one of the 52294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // statements within a basic block. This transfer function does two things: 53294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // 54294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // (1) binds the next container value to 'element'. This creates a new 55294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // node in the ExplodedGraph. 56294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // 57294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // (2) binds the value 0/1 to the ObjCForCollectionStmt* itself, indicating 58294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // whether or not the container has any more elements. This value 59294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // will be tested in ProcessBranch. We need to explicitly bind 60294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // this value because a container can contain nil elements. 61294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // 62294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // FIXME: Eventually this logic should actually do dispatches to 63294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // 'countByEnumeratingWithState:objects:count:' (NSFastEnumeration). 64294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // This will require simulating a temporary NSFastEnumerationState, either 65294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // through an SVal or through the use of MemRegions. This value can 66294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // be affixed to the ObjCForCollectionStmt* instead of 0/1; when the loop 67294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // terminates we reclaim the temporary (it goes out of scope) and we 68294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // we can test if the SVal is 0 or if the MemRegion is null (depending 69294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // on what approach we take). 70294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // 71294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // For now: simulate (1) by assigning either a symbol or nil if the 72294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // container is empty. Thus this transfer function will by default 73294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // result in state splitting. 74ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks 75294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const Stmt *elem = S->getElement(); 768bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = Pred->getState(); 77294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek SVal elementV; 78294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 79294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (const DeclStmt *DS = dyn_cast<DeclStmt>(elem)) { 80294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek const VarDecl *elemD = cast<VarDecl>(DS->getSingleDecl()); 81294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek assert(elemD->getInit() == 0); 82294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek elementV = state->getLValue(elemD, Pred->getLocationContext()); 83294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 84294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek else { 855eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek elementV = state->getSVal(elem, Pred->getLocationContext()); 86294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 87294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 88294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet dstLocation; 89bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek evalLocation(dstLocation, S, elem, Pred, state, elementV, NULL, false); 901895a0a6936001374f66adbdfcf8abe5edf912eaJordan Rose 911895a0a6936001374f66adbdfcf8abe5edf912eaJordan Rose ExplodedNodeSet Tmp; 921895a0a6936001374f66adbdfcf8abe5edf912eaJordan Rose StmtNodeBuilder Bldr(Pred, Tmp, *currentBuilderContext); 931895a0a6936001374f66adbdfcf8abe5edf912eaJordan Rose 94294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek for (ExplodedNodeSet::iterator NI = dstLocation.begin(), 95294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek NE = dstLocation.end(); NI!=NE; ++NI) { 96294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek Pred = *NI; 978bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = Pred->getState(); 985eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 99294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 100294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Handle the case where the container still has elements. 101294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek SVal TrueV = svalBuilder.makeTruthVal(1); 1028bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef hasElems = state->BindExpr(S, LCtx, TrueV); 103294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 104294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Handle the case where the container has no elements. 105294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek SVal FalseV = svalBuilder.makeTruthVal(0); 1068bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef noElems = state->BindExpr(S, LCtx, FalseV); 107294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 108294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (loc::MemRegionVal *MV = dyn_cast<loc::MemRegionVal>(&elementV)) 109294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (const TypedValueRegion *R = 110294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek dyn_cast<TypedValueRegion>(MV->getRegion())) { 111294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // FIXME: The proper thing to do is to really iterate over the 112294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // container. We will do this with dispatch logic to the store. 113294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // For now, just 'conjure' up a symbolic value. 114294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek QualType T = R->getValueType(); 115294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek assert(Loc::isLocType(T)); 116ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks unsigned Count = currentBuilderContext->getCurrentBlockCount(); 1173133f79cf451e6302dd05262b4bb53a3e4fd6300Ted Kremenek SymbolRef Sym = SymMgr.getConjuredSymbol(elem, LCtx, T, Count); 118294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek SVal V = svalBuilder.makeLoc(Sym); 119294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek hasElems = hasElems->bindLoc(elementV, V); 120294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 121294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Bind the location to 'nil' on the false branch. 122294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek SVal nilV = svalBuilder.makeIntVal(0, T); 123294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek noElems = noElems->bindLoc(elementV, nilV); 124294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 125294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 126294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Create the new nodes. 127ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks Bldr.generateNode(S, Pred, hasElems); 128ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks Bldr.generateNode(S, Pred, noElems); 129294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 1301895a0a6936001374f66adbdfcf8abe5edf912eaJordan Rose 1311895a0a6936001374f66adbdfcf8abe5edf912eaJordan Rose // Finally, run any custom checkers. 1321895a0a6936001374f66adbdfcf8abe5edf912eaJordan Rose // FIXME: Eventually all pre- and post-checks should live in VisitStmt. 1331895a0a6936001374f66adbdfcf8abe5edf912eaJordan Rose getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this); 134294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek} 135294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 1366c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rosestatic bool isSubclass(const ObjCInterfaceDecl *Class, IdentifierInfo *II) { 1376c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose if (!Class) 1386c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose return false; 1396c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose if (Class->getIdentifier() == II) 1406c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose return true; 1416c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose return isSubclass(Class->getSuperClass(), II); 1426c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose} 1436c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose 144cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rosevoid ExprEngine::VisitObjCMessage(const ObjCMethodCall &msg, 145294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNode *Pred, 146294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet &Dst) { 147294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 148294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Handle the previsits checks. 149294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet dstPrevisit; 150294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek getCheckerManager().runCheckersForPreObjCMessage(dstPrevisit, Pred, 151294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek msg, *this); 152294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 153294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Proceed with evaluate the message expression. 154294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet dstEval; 155aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks StmtNodeBuilder Bldr(dstPrevisit, dstEval, *currentBuilderContext); 156ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks 157294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek for (ExplodedNodeSet::iterator DI = dstPrevisit.begin(), 158294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek DE = dstPrevisit.end(); DI != DE; ++DI) { 159294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 160294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNode *Pred = *DI; 161294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek bool RaisesException = false; 162294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 163cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose if (msg.isInstanceMessage()) { 164cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose SVal recVal = msg.getReceiverSVal(); 165294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (!recVal.isUndef()) { 166294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Bifurcate the state into nil and non-nil ones. 167294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal); 168294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 169cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose ProgramStateRef state = Pred->getState(); 1708bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef notNilState, nilState; 171294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek llvm::tie(notNilState, nilState) = state->assume(receiverVal); 172294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 173294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // There are three cases: can be nil or non-nil, must be nil, must be 174294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // non-nil. We ignore must be nil, and merge the rest two into non-nil. 175cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose // FIXME: This ignores many potential bugs (<rdar://problem/11733396>). 176cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose // Revisit once we have lazier constraints. 177294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (nilState && !notNilState) { 178294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek continue; 179294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 180294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 181294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Check if the "raise" message was sent. 182294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek assert(notNilState); 183294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (msg.getSelector() == RaiseSel) 184294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek RaisesException = true; 185294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 186ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks // If we raise an exception, for now treat it as a sink. 187294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Eventually we will want to handle exceptions properly. 188294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Dispatch to plug-in transfer function. 189ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks evalObjCMessage(Bldr, msg, Pred, notNilState, RaisesException); 190294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 191cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose } else { 1926c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose // Check for special class methods. 193cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose if (const ObjCInterfaceDecl *Iface = msg.getReceiverInterface()) { 1946c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose if (!NSExceptionII) { 195294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ASTContext &Ctx = getContext(); 1966c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose NSExceptionII = &Ctx.Idents.get("NSException"); 197294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 198294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 1996c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose if (isSubclass(Iface, NSExceptionII)) { 2006c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose enum { NUM_RAISE_SELECTORS = 2 }; 2016c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose 2026c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose // Lazily create a cache of the selectors. 2036c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose if (!NSExceptionInstanceRaiseSelectors) { 2046c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose ASTContext &Ctx = getContext(); 2056c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose NSExceptionInstanceRaiseSelectors = 2066c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose new Selector[NUM_RAISE_SELECTORS]; 2076c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose SmallVector<IdentifierInfo*, NUM_RAISE_SELECTORS> II; 2086c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose unsigned idx = 0; 2096c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose 2106c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose // raise:format: 2116c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose II.push_back(&Ctx.Idents.get("raise")); 2126c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose II.push_back(&Ctx.Idents.get("format")); 2136c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose NSExceptionInstanceRaiseSelectors[idx++] = 2146c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose Ctx.Selectors.getSelector(II.size(), &II[0]); 2156c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose 2166c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose // raise:format:arguments: 2176c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose II.push_back(&Ctx.Idents.get("arguments")); 2186c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose NSExceptionInstanceRaiseSelectors[idx++] = 2196c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose Ctx.Selectors.getSelector(II.size(), &II[0]); 2206c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose } 2216c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose 2226c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose Selector S = msg.getSelector(); 2236c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i) { 2246c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose if (S == NSExceptionInstanceRaiseSelectors[i]) { 2256c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose RaisesException = true; 2266c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose break; 2276c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose } 228294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 2296c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose } 230294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 2316c234b1fd1da64a14a77433cb805cb1aa798512aJordan Rose 232ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks // If we raise an exception, for now treat it as a sink. 233294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Eventually we will want to handle exceptions properly. 234294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Dispatch to plug-in transfer function. 235ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks evalObjCMessage(Bldr, msg, Pred, Pred->getState(), RaisesException); 236294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 237294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 238294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 239294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Finally, perform the post-condition check of the ObjCMessageExpr and store 240294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // the created nodes in 'Dst'. 241294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek getCheckerManager().runCheckersForPostObjCMessage(Dst, dstEval, msg, *this); 242294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek} 243500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 244aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaksvoid ExprEngine::evalObjCMessage(StmtNodeBuilder &Bldr, 245cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose const ObjCMethodCall &msg, 246500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose ExplodedNode *Pred, 2478bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 248ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks bool GenSink) { 249500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose // First handle the return value. 250500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose SVal ReturnValue = UnknownVal(); 251500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 252500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose // Some method families have known return values. 253500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose switch (msg.getMethodFamily()) { 254500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose default: 255500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose break; 256500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose case OMF_autorelease: 257500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose case OMF_retain: 258500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose case OMF_self: { 259500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose // These methods return their receivers. 260cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose ReturnValue = msg.getReceiverSVal(); 261500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose break; 262500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose } 263500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose } 264500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 265cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose const LocationContext *LCtx = Pred->getLocationContext(); 266cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose unsigned BlockCount = currentBuilderContext->getCurrentBlockCount(); 267cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose 268500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose // If we failed to figure out the return value, use a conjured value instead. 269500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose if (ReturnValue.isUnknown()) { 270500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose SValBuilder &SVB = getSValBuilder(); 271cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose QualType ResultTy = msg.getResultType(); 272500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose const Expr *CurrentE = cast<Expr>(currentStmt); 273740d490593e0de8732a697c9f77b90ddd463863bJordan Rose ReturnValue = SVB.getConjuredSymbolVal(NULL, CurrentE, LCtx, ResultTy, 274740d490593e0de8732a697c9f77b90ddd463863bJordan Rose BlockCount); 275500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose } 276500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 277500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose // Bind the return value. 2785eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state = state->BindExpr(currentStmt, LCtx, ReturnValue); 279500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 280e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose // Invalidate the arguments (and the receiver) 281cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose state = msg.invalidateRegions(BlockCount, state); 282e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose 283fe27971d54d26997149d6b84057f04ff398d1d5dJordy Rose // And create the new node. 284cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose Bldr.generateNode(msg.getOriginExpr(), Pred, state, GenSink); 285ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks assert(Bldr.hasGeneratedNodes()); 286500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose} 287500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose 288