ExprEngineObjC.cpp revision fe27971d54d26997149d6b84057f04ff398d1d5d
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
14294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek#include "clang/StaticAnalyzer/Core/CheckerManager.h"
15294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
16294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek#include "clang/Analysis/Support/SaveAndRestore.h"
17294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
18294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekusing namespace clang;
19294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekusing namespace ento;
20294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
21294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekvoid ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *Ex,
22294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek                                          ExplodedNode *Pred,
23294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek                                          ExplodedNodeSet &Dst) {
24294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
25294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  const ProgramState *state = Pred->getState();
26294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  SVal baseVal = state->getSVal(Ex->getBase());
27294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  SVal location = state->getLValue(Ex->getDecl(), baseVal);
28294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
29294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  ExplodedNodeSet dstIvar;
30294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  MakeNode(dstIvar, Ex, Pred, state->BindExpr(Ex, location));
31294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
32294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  // Perform the post-condition check of the ObjCIvarRefExpr and store
33294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  // the created nodes in 'Dst'.
34294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  getCheckerManager().runCheckersForPostStmt(Dst, dstIvar, Ex, *this);
35294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek}
36294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
37294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekvoid ExprEngine::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
38294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek                                             ExplodedNode *Pred,
39294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek                                             ExplodedNodeSet &Dst) {
40294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  getCheckerManager().runCheckersForPreStmt(Dst, Pred, S, *this);
41294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek}
42294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
43294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekvoid ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
44294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek                                            ExplodedNode *Pred,
45294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek                                            ExplodedNodeSet &Dst) {
46294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
47294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  // ObjCForCollectionStmts are processed in two places.  This method
48294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  // handles the case where an ObjCForCollectionStmt* occurs as one of the
49294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  // statements within a basic block.  This transfer function does two things:
50294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //
51294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //  (1) binds the next container value to 'element'.  This creates a new
52294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //      node in the ExplodedGraph.
53294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //
54294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //  (2) binds the value 0/1 to the ObjCForCollectionStmt* itself, indicating
55294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //      whether or not the container has any more elements.  This value
56294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //      will be tested in ProcessBranch.  We need to explicitly bind
57294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //      this value because a container can contain nil elements.
58294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //
59294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  // FIXME: Eventually this logic should actually do dispatches to
60294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //   'countByEnumeratingWithState:objects:count:' (NSFastEnumeration).
61294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //   This will require simulating a temporary NSFastEnumerationState, either
62294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //   through an SVal or through the use of MemRegions.  This value can
63294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //   be affixed to the ObjCForCollectionStmt* instead of 0/1; when the loop
64294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //   terminates we reclaim the temporary (it goes out of scope) and we
65294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //   we can test if the SVal is 0 or if the MemRegion is null (depending
66294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //   on what approach we take).
67294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //
68294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //  For now: simulate (1) by assigning either a symbol or nil if the
69294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //    container is empty.  Thus this transfer function will by default
70294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  //    result in state splitting.
71294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
72294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  const Stmt *elem = S->getElement();
73294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  const ProgramState *state = Pred->getState();
74294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  SVal elementV;
75294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
76294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  if (const DeclStmt *DS = dyn_cast<DeclStmt>(elem)) {
77294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    const VarDecl *elemD = cast<VarDecl>(DS->getSingleDecl());
78294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    assert(elemD->getInit() == 0);
79294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    elementV = state->getLValue(elemD, Pred->getLocationContext());
80294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  }
81294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  else {
82294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    elementV = state->getSVal(elem);
83294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  }
84294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
85294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  ExplodedNodeSet dstLocation;
86294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  evalLocation(dstLocation, elem, Pred, state, elementV, NULL, false);
87294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
88294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  if (dstLocation.empty())
89294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    return;
90294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
91294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  for (ExplodedNodeSet::iterator NI = dstLocation.begin(),
92294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek       NE = dstLocation.end(); NI!=NE; ++NI) {
93294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    Pred = *NI;
94294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    const ProgramState *state = Pred->getState();
95294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
96294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    // Handle the case where the container still has elements.
97294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    SVal TrueV = svalBuilder.makeTruthVal(1);
98294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    const ProgramState *hasElems = state->BindExpr(S, TrueV);
99294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
100294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    // Handle the case where the container has no elements.
101294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    SVal FalseV = svalBuilder.makeTruthVal(0);
102294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    const ProgramState *noElems = state->BindExpr(S, FalseV);
103294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
104294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    if (loc::MemRegionVal *MV = dyn_cast<loc::MemRegionVal>(&elementV))
105294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek      if (const TypedValueRegion *R =
106294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          dyn_cast<TypedValueRegion>(MV->getRegion())) {
107294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        // FIXME: The proper thing to do is to really iterate over the
108294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        //  container.  We will do this with dispatch logic to the store.
109294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        //  For now, just 'conjure' up a symbolic value.
110294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        QualType T = R->getValueType();
111294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        assert(Loc::isLocType(T));
112294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        unsigned Count = Builder->getCurrentBlockCount();
113294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);
114294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        SVal V = svalBuilder.makeLoc(Sym);
115294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        hasElems = hasElems->bindLoc(elementV, V);
116294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
117294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        // Bind the location to 'nil' on the false branch.
118294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        SVal nilV = svalBuilder.makeIntVal(0, T);
119294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        noElems = noElems->bindLoc(elementV, nilV);
120294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek      }
121294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
122294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    // Create the new nodes.
123294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    MakeNode(Dst, S, Pred, hasElems);
124294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    MakeNode(Dst, S, Pred, noElems);
125294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  }
126294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek}
127294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
128294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenekvoid ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
129294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek                                  ExplodedNode *Pred,
130294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek                                  ExplodedNodeSet &Dst) {
131294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
132294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  // Handle the previsits checks.
133294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  ExplodedNodeSet dstPrevisit;
134294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  getCheckerManager().runCheckersForPreObjCMessage(dstPrevisit, Pred,
135294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek                                                   msg, *this);
136294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
137294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  // Proceed with evaluate the message expression.
138294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  ExplodedNodeSet dstEval;
139294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
140294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  for (ExplodedNodeSet::iterator DI = dstPrevisit.begin(),
141294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek       DE = dstPrevisit.end(); DI != DE; ++DI) {
142294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
143294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    ExplodedNode *Pred = *DI;
144294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    bool RaisesException = false;
145294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    SaveAndRestore<bool> OldSink(Builder->BuildSinks);
146294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    SaveOr OldHasGen(Builder->hasGeneratedNode);
147294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
148294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    if (const Expr *Receiver = msg.getInstanceReceiver()) {
149294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek      const ProgramState *state = Pred->getState();
150294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek      SVal recVal = state->getSVal(Receiver);
151294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek      if (!recVal.isUndef()) {
152294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        // Bifurcate the state into nil and non-nil ones.
153294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
154294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
155294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        const ProgramState *notNilState, *nilState;
156294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        llvm::tie(notNilState, nilState) = state->assume(receiverVal);
157294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
158294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        // There are three cases: can be nil or non-nil, must be nil, must be
159294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        // non-nil. We ignore must be nil, and merge the rest two into non-nil.
160294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        if (nilState && !notNilState) {
161294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          dstEval.insert(Pred);
162294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          continue;
163294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        }
164294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
165294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        // Check if the "raise" message was sent.
166294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        assert(notNilState);
167294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        if (msg.getSelector() == RaiseSel)
168294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          RaisesException = true;
169294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
170294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        // Check if we raise an exception.  For now treat these as sinks.
171294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        // Eventually we will want to handle exceptions properly.
172294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        if (RaisesException)
173294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          Builder->BuildSinks = true;
174294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
175294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        // Dispatch to plug-in transfer function.
176294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        evalObjCMessage(dstEval, msg, Pred, notNilState);
177294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek      }
178294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    }
179294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    else if (const ObjCInterfaceDecl *Iface = msg.getReceiverInterface()) {
180294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek      IdentifierInfo* ClsName = Iface->getIdentifier();
181294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek      Selector S = msg.getSelector();
182294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
183294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek      // Check for special instance methods.
184294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek      if (!NSExceptionII) {
185294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        ASTContext &Ctx = getContext();
186294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        NSExceptionII = &Ctx.Idents.get("NSException");
187294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek      }
188294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
189294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek      if (ClsName == NSExceptionII) {
190294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        enum { NUM_RAISE_SELECTORS = 2 };
191294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
192294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        // Lazily create a cache of the selectors.
193294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        if (!NSExceptionInstanceRaiseSelectors) {
194294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          ASTContext &Ctx = getContext();
195294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          NSExceptionInstanceRaiseSelectors =
196294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          new Selector[NUM_RAISE_SELECTORS];
197294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          SmallVector<IdentifierInfo*, NUM_RAISE_SELECTORS> II;
198294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          unsigned idx = 0;
199294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
200294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          // raise:format:
201294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          II.push_back(&Ctx.Idents.get("raise"));
202294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          II.push_back(&Ctx.Idents.get("format"));
203294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          NSExceptionInstanceRaiseSelectors[idx++] =
204294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          Ctx.Selectors.getSelector(II.size(), &II[0]);
205294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
206294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          // raise:format::arguments:
207294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          II.push_back(&Ctx.Idents.get("arguments"));
208294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          NSExceptionInstanceRaiseSelectors[idx++] =
209294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          Ctx.Selectors.getSelector(II.size(), &II[0]);
210294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        }
211294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
212294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i)
213294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          if (S == NSExceptionInstanceRaiseSelectors[i]) {
214294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek            RaisesException = true;
215294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek            break;
216294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek          }
217294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek      }
218294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
219294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek      // Check if we raise an exception.  For now treat these as sinks.
220294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek      // Eventually we will want to handle exceptions properly.
221294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek      if (RaisesException)
222294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek        Builder->BuildSinks = true;
223294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
224294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek      // Dispatch to plug-in transfer function.
225294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek      evalObjCMessage(dstEval, msg, Pred, Pred->getState());
226294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek    }
227fe27971d54d26997149d6b84057f04ff398d1d5dJordy Rose
228fe27971d54d26997149d6b84057f04ff398d1d5dJordy Rose    assert(Builder->BuildSinks || Builder->hasGeneratedNode);
229294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  }
230294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek
231294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  // Finally, perform the post-condition check of the ObjCMessageExpr and store
232294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  // the created nodes in 'Dst'.
233294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek  getCheckerManager().runCheckersForPostObjCMessage(Dst, dstEval, msg, *this);
234294fd0a62b95f512637910bf85c7efa6c2354b50Ted Kremenek}
235500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose
236500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rosevoid ExprEngine::evalObjCMessage(ExplodedNodeSet &Dst, const ObjCMessage &msg,
237500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose                                 ExplodedNode *Pred,
238500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose                                 const ProgramState *state) {
239500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose  assert (Builder && "StmtNodeBuilder must be defined.");
240500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose
241500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose  // First handle the return value.
242500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose  SVal ReturnValue = UnknownVal();
243500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose
244500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose  // Some method families have known return values.
245500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose  switch (msg.getMethodFamily()) {
246500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose  default:
247500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose    break;
248500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose  case OMF_autorelease:
249500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose  case OMF_retain:
250500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose  case OMF_self: {
251500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose    // These methods return their receivers.
252500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose    const Expr *ReceiverE = msg.getInstanceReceiver();
253500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose    if (ReceiverE)
254500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose      ReturnValue = state->getSVal(ReceiverE);
255500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose    break;
256500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose  }
257500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose  }
258500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose
259500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose  // If we failed to figure out the return value, use a conjured value instead.
260500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose  if (ReturnValue.isUnknown()) {
261500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose    SValBuilder &SVB = getSValBuilder();
262500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose    QualType ResultTy = msg.getResultType(getContext());
263500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose    unsigned Count = Builder->getCurrentBlockCount();
264500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose    const Expr *CurrentE = cast<Expr>(currentStmt);
265500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose    ReturnValue = SVB.getConjuredSymbolVal(NULL, CurrentE, ResultTy, Count);
266500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose  }
267500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose
268500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose  // Bind the return value.
269500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose  state = state->BindExpr(currentStmt, ReturnValue);
270500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose
271e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose  // Invalidate the arguments (and the receiver)
272e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose  const LocationContext *LC = Pred->getLocationContext();
273e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose  state = invalidateArguments(state, CallOrObjCMessage(msg, state), LC);
274e38dd95dddb8f1b38469c8d0e28aa1c660489324Jordy Rose
275fe27971d54d26997149d6b84057f04ff398d1d5dJordy Rose  // And create the new node.
276fe27971d54d26997149d6b84057f04ff398d1d5dJordy Rose  MakeNode(Dst, msg.getOriginExpr(), Pred, state);
277500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose}
278500abad7edfcc2409b18dd616cdbc28a094926f5Jordy Rose
279