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; 31e606e3d224d3fa8f6d4358ec66858d46754457a0Jordan Rose StmtNodeBuilder Bldr(Pred, dstIvar, *currBldrCtx); 32e606e3d224d3fa8f6d4358ec66858d46754457a0Jordan Rose 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()); 806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines assert(elemD->getInit() == nullptr); 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; 886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines evalLocation(dstLocation, S, elem, Pred, state, elementV, nullptr, 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); 1065251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie 107dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie if (Optional<loc::MemRegionVal> MV = elementV.getAs<loc::MemRegionVal>()) 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 135d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rosevoid ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME, 136294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNode *Pred, 137294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet &Dst) { 138d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose CallEventManager &CEMgr = getStateManager().getCallEventManager(); 139d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose CallEventRef<ObjCMethodCall> Msg = 140d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose CEMgr.getObjCMethodCall(ME, Pred->getState(), Pred->getLocationContext()); 141d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose 142294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Handle the previsits checks. 143294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet dstPrevisit; 14496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose getCheckerManager().runCheckersForPreObjCMessage(dstPrevisit, Pred, 145d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose *Msg, *this); 14696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose ExplodedNodeSet dstGenericPrevisit; 14796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose getCheckerManager().runCheckersForPreCall(dstGenericPrevisit, dstPrevisit, 148d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose *Msg, *this); 14996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose 150294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Proceed with evaluate the message expression. 151294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNodeSet dstEval; 15266c486f275531df6362b3511fc3af6563561801bTed Kremenek StmtNodeBuilder Bldr(dstGenericPrevisit, dstEval, *currBldrCtx); 153ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks 15496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose for (ExplodedNodeSet::iterator DI = dstGenericPrevisit.begin(), 15596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose DE = dstGenericPrevisit.end(); DI != DE; ++DI) { 156294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek ExplodedNode *Pred = *DI; 157d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose ProgramStateRef State = Pred->getState(); 158d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose CallEventRef<ObjCMethodCall> UpdatedMsg = Msg.cloneWithState(State); 159294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 160d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose if (UpdatedMsg->isInstanceMessage()) { 161d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose SVal recVal = UpdatedMsg->getReceiverSVal(); 162294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (!recVal.isUndef()) { 163294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Bifurcate the state into nil and non-nil ones. 1645251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie DefinedOrUnknownSVal receiverVal = 1655251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie recVal.castAs<DefinedOrUnknownSVal>(); 1665251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie 1678bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef notNilState, nilState; 168651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::tie(notNilState, nilState) = State->assume(receiverVal); 169294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 170294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // There are three cases: can be nil or non-nil, must be nil, must be 171294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // non-nil. We ignore must be nil, and merge the rest two into non-nil. 172cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose // FIXME: This ignores many potential bugs (<rdar://problem/11733396>). 173cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose // Revisit once we have lazier constraints. 174294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek if (nilState && !notNilState) { 175294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek continue; 176294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 177294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 178294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Check if the "raise" message was sent. 179294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek assert(notNilState); 1804ef19205b6912316296db74a9073ad6fa60e4ccaTed Kremenek if (ObjCNoRet.isImplicitNoReturn(ME)) { 181e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks // If we raise an exception, for now treat it as a sink. 182e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks // Eventually we will want to handle exceptions properly. 1839428723d6730f4fd257e15b78d24991ae95bbd84Jordan Rose Bldr.generateSink(ME, Pred, State); 184e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks continue; 185e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks } 186294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 187e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks // Generate a transition to non-Nil state. 18882f2ad456a82da1b9cb7ddfc994c8f5fa44b59e6Jordan Rose if (notNilState != State) { 1899428723d6730f4fd257e15b78d24991ae95bbd84Jordan Rose Pred = Bldr.generateNode(ME, Pred, notNilState); 19082f2ad456a82da1b9cb7ddfc994c8f5fa44b59e6Jordan Rose assert(Pred && "Should have cached out already!"); 19182f2ad456a82da1b9cb7ddfc994c8f5fa44b59e6Jordan Rose } 192294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 193cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose } else { 1944ef19205b6912316296db74a9073ad6fa60e4ccaTed Kremenek // Check for special class methods that are known to not return 1954ef19205b6912316296db74a9073ad6fa60e4ccaTed Kremenek // and that we should treat as a sink. 1964ef19205b6912316296db74a9073ad6fa60e4ccaTed Kremenek if (ObjCNoRet.isImplicitNoReturn(ME)) { 1974ef19205b6912316296db74a9073ad6fa60e4ccaTed Kremenek // If we raise an exception, for now treat it as a sink. 1984ef19205b6912316296db74a9073ad6fa60e4ccaTed Kremenek // Eventually we will want to handle exceptions properly. 1999428723d6730f4fd257e15b78d24991ae95bbd84Jordan Rose Bldr.generateSink(ME, Pred, Pred->getState()); 2004ef19205b6912316296db74a9073ad6fa60e4ccaTed Kremenek continue; 201294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 202294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 2039dc5167e4017ef4c8b327abb6f72225eec2e0f19Anna Zaks 20482f2ad456a82da1b9cb7ddfc994c8f5fa44b59e6Jordan Rose defaultEvalCall(Bldr, Pred, *UpdatedMsg); 205294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek } 206294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek 20796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose ExplodedNodeSet dstPostvisit; 208d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose getCheckerManager().runCheckersForPostCall(dstPostvisit, dstEval, 209d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose *Msg, *this); 21096479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose 211294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // Finally, perform the post-condition check of the ObjCMessageExpr and store 212294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek // the created nodes in 'Dst'. 21396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose getCheckerManager().runCheckersForPostObjCMessage(Dst, dstPostvisit, 214d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose *Msg, *this); 215294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek} 216