blob: a816186a307ddf139d9bda9f5977d204b39977de [file] [log] [blame]
Ted Kremenekaf337412008-11-12 19:24:17 +00001//==- GRCoreEngine.cpp - Path-Sensitive Dataflow Engine ------------*- C++ -*-//
Mike Stump1eb44332009-09-09 15:08:12 +00002//
Ted Kremenekf24af5b2008-01-14 23:24:37 +00003// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines a generic engine for intraprocedural, path-sensitive,
11// dataflow analysis via graph reachability engine.
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremenek1309f9a2010-01-25 04:41:41 +000015#include "clang/Checker/PathSensitive/GRCoreEngine.h"
16#include "clang/Checker/PathSensitive/GRExprEngine.h"
Ted Kremenekf24af5b2008-01-14 23:24:37 +000017#include "clang/AST/Expr.h"
Ted Kremenekf24af5b2008-01-14 23:24:37 +000018#include "llvm/Support/Casting.h"
19#include "llvm/ADT/DenseMap.h"
20#include <vector>
Ted Kremeneke1efd4d2008-12-16 22:13:33 +000021#include <queue>
Ted Kremenekf24af5b2008-01-14 23:24:37 +000022
23using llvm::cast;
24using llvm::isa;
25using namespace clang;
26
Ted Kremeneke1efd4d2008-12-16 22:13:33 +000027//===----------------------------------------------------------------------===//
28// Worklist classes for exploration of reachable states.
29//===----------------------------------------------------------------------===//
30
Ted Kremenekf24af5b2008-01-14 23:24:37 +000031namespace {
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000032class DFS : public GRWorkList {
Ted Kremenekf24af5b2008-01-14 23:24:37 +000033 llvm::SmallVector<GRWorkListUnit,20> Stack;
34public:
35 virtual bool hasWork() const {
36 return !Stack.empty();
37 }
38
39 virtual void Enqueue(const GRWorkListUnit& U) {
40 Stack.push_back(U);
41 }
42
43 virtual GRWorkListUnit Dequeue() {
44 assert (!Stack.empty());
45 const GRWorkListUnit& U = Stack.back();
46 Stack.pop_back(); // This technically "invalidates" U, but we are fine.
47 return U;
48 }
49};
Mike Stump1eb44332009-09-09 15:08:12 +000050
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000051class BFS : public GRWorkList {
Ted Kremenek8ff59e82009-05-01 22:18:46 +000052 std::queue<GRWorkListUnit> Queue;
53public:
54 virtual bool hasWork() const {
55 return !Queue.empty();
56 }
Mike Stump1eb44332009-09-09 15:08:12 +000057
Ted Kremenek8ff59e82009-05-01 22:18:46 +000058 virtual void Enqueue(const GRWorkListUnit& U) {
59 Queue.push(U);
60 }
Mike Stump1eb44332009-09-09 15:08:12 +000061
Ted Kremenek8ff59e82009-05-01 22:18:46 +000062 virtual GRWorkListUnit Dequeue() {
63 // Don't use const reference. The subsequent pop_back() might make it
64 // unsafe.
Mike Stump1eb44332009-09-09 15:08:12 +000065 GRWorkListUnit U = Queue.front();
Ted Kremenek8ff59e82009-05-01 22:18:46 +000066 Queue.pop();
67 return U;
68 }
69};
Mike Stump1eb44332009-09-09 15:08:12 +000070
Ted Kremenekf24af5b2008-01-14 23:24:37 +000071} // end anonymous namespace
72
Ted Kremenekee985462008-01-16 18:18:48 +000073// Place the dstor for GRWorkList here because it contains virtual member
74// functions, and we the code for the dstor generated in one compilation unit.
75GRWorkList::~GRWorkList() {}
76
Ted Kremenek8ff59e82009-05-01 22:18:46 +000077GRWorkList *GRWorkList::MakeDFS() { return new DFS(); }
78GRWorkList *GRWorkList::MakeBFS() { return new BFS(); }
Ted Kremenekf24af5b2008-01-14 23:24:37 +000079
Ted Kremeneke1efd4d2008-12-16 22:13:33 +000080namespace {
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000081 class BFSBlockDFSContents : public GRWorkList {
Ted Kremeneke1efd4d2008-12-16 22:13:33 +000082 std::queue<GRWorkListUnit> Queue;
83 llvm::SmallVector<GRWorkListUnit,20> Stack;
84 public:
85 virtual bool hasWork() const {
86 return !Queue.empty() || !Stack.empty();
87 }
Mike Stump1eb44332009-09-09 15:08:12 +000088
Ted Kremeneke1efd4d2008-12-16 22:13:33 +000089 virtual void Enqueue(const GRWorkListUnit& U) {
90 if (isa<BlockEntrance>(U.getNode()->getLocation()))
91 Queue.push(U);
92 else
93 Stack.push_back(U);
94 }
Mike Stump1eb44332009-09-09 15:08:12 +000095
Ted Kremeneke1efd4d2008-12-16 22:13:33 +000096 virtual GRWorkListUnit Dequeue() {
97 // Process all basic blocks to completion.
98 if (!Stack.empty()) {
99 const GRWorkListUnit& U = Stack.back();
100 Stack.pop_back(); // This technically "invalidates" U, but we are fine.
101 return U;
102 }
Mike Stump1eb44332009-09-09 15:08:12 +0000103
Ted Kremeneke1efd4d2008-12-16 22:13:33 +0000104 assert(!Queue.empty());
105 // Don't use const reference. The subsequent pop_back() might make it
106 // unsafe.
Mike Stump1eb44332009-09-09 15:08:12 +0000107 GRWorkListUnit U = Queue.front();
Ted Kremeneke1efd4d2008-12-16 22:13:33 +0000108 Queue.pop();
Mike Stump1eb44332009-09-09 15:08:12 +0000109 return U;
Ted Kremeneke1efd4d2008-12-16 22:13:33 +0000110 }
111 };
112} // end anonymous namespace
113
114GRWorkList* GRWorkList::MakeBFSBlockDFSContents() {
115 return new BFSBlockDFSContents();
116}
117
118//===----------------------------------------------------------------------===//
119// Core analysis engine.
120//===----------------------------------------------------------------------===//
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000121void GRCoreEngine::ProcessEndPath(GREndPathNodeBuilder& Builder) {
Zhongxing Xu0111f572009-08-06 10:00:15 +0000122 SubEngine.ProcessEndPath(Builder);
123}
Ted Kremeneke1efd4d2008-12-16 22:13:33 +0000124
Ted Kremenek852274d2009-12-16 03:18:58 +0000125void GRCoreEngine::ProcessStmt(CFGElement E, GRStmtNodeBuilder& Builder) {
126 SubEngine.ProcessStmt(E, Builder);
Zhongxing Xu0111f572009-08-06 10:00:15 +0000127}
128
Zhongxing Xud9e0c0f2010-03-23 05:05:02 +0000129bool GRCoreEngine::ProcessBlockEntrance(CFGBlock* Blk, const ExplodedNode *Pred,
Mike Stump1eb44332009-09-09 15:08:12 +0000130 GRBlockCounter BC) {
Zhongxing Xud9e0c0f2010-03-23 05:05:02 +0000131 return SubEngine.ProcessBlockEntrance(Blk, Pred, BC);
Zhongxing Xu0111f572009-08-06 10:00:15 +0000132}
133
134void GRCoreEngine::ProcessBranch(Stmt* Condition, Stmt* Terminator,
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000135 GRBranchNodeBuilder& Builder) {
Mike Stump1eb44332009-09-09 15:08:12 +0000136 SubEngine.ProcessBranch(Condition, Terminator, Builder);
Zhongxing Xu0111f572009-08-06 10:00:15 +0000137}
138
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000139void GRCoreEngine::ProcessIndirectGoto(GRIndirectGotoNodeBuilder& Builder) {
Zhongxing Xu0111f572009-08-06 10:00:15 +0000140 SubEngine.ProcessIndirectGoto(Builder);
141}
142
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000143void GRCoreEngine::ProcessSwitch(GRSwitchNodeBuilder& Builder) {
Zhongxing Xu0111f572009-08-06 10:00:15 +0000144 SubEngine.ProcessSwitch(Builder);
145}
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000146
Douglas Gregor102acd52010-02-25 19:01:53 +0000147void GRCoreEngine::ProcessCallEnter(GRCallEnterNodeBuilder &Builder) {
148 SubEngine.ProcessCallEnter(Builder);
149}
150
151void GRCoreEngine::ProcessCallExit(GRCallExitNodeBuilder &Builder) {
152 SubEngine.ProcessCallExit(Builder);
153}
154
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000155/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
Zhongxing Xu25e695b2009-08-15 03:17:38 +0000156bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps) {
Mike Stump1eb44332009-09-09 15:08:12 +0000157
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000158 if (G->num_roots() == 0) { // Initialize the analysis by constructing
159 // the root if none exists.
Mike Stump1eb44332009-09-09 15:08:12 +0000160
Zhongxing Xucc025532009-08-25 03:33:41 +0000161 CFGBlock* Entry = &(L->getCFG()->getEntry());
Mike Stump1eb44332009-09-09 15:08:12 +0000162
163 assert (Entry->empty() &&
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000164 "Entry block must be empty.");
Mike Stump1eb44332009-09-09 15:08:12 +0000165
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000166 assert (Entry->succ_size() == 1 &&
167 "Entry block must have 1 successor.");
Mike Stump1eb44332009-09-09 15:08:12 +0000168
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000169 // Get the solitary successor.
Mike Stump1eb44332009-09-09 15:08:12 +0000170 CFGBlock* Succ = *(Entry->succ_begin());
171
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000172 // Construct an edge representing the
173 // starting location in the function.
Zhongxing Xu25e695b2009-08-15 03:17:38 +0000174 BlockEdge StartLoc(Entry, Succ, L);
Mike Stump1eb44332009-09-09 15:08:12 +0000175
Ted Kremenek8e49dd62008-02-12 18:08:17 +0000176 // Set the current block counter to being empty.
177 WList->setBlockCounter(BCounterFactory.GetEmptyCounter());
Mike Stump1eb44332009-09-09 15:08:12 +0000178
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000179 // Generate the root.
Zhongxing Xu17fd8632009-08-17 06:19:58 +0000180 GenerateNode(StartLoc, getInitialState(L), 0);
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000181 }
Mike Stump1eb44332009-09-09 15:08:12 +0000182
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000183 while (Steps && WList->hasWork()) {
184 --Steps;
185 const GRWorkListUnit& WU = WList->Dequeue();
Mike Stump1eb44332009-09-09 15:08:12 +0000186
Ted Kremenek8e49dd62008-02-12 18:08:17 +0000187 // Set the current block counter.
188 WList->setBlockCounter(WU.getBlockCounter());
189
190 // Retrieve the node.
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000191 ExplodedNode* Node = WU.getNode();
Mike Stump1eb44332009-09-09 15:08:12 +0000192
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000193 // Dispatch on the location type.
194 switch (Node->getLocation().getKind()) {
Ted Kremeneke1efd4d2008-12-16 22:13:33 +0000195 case ProgramPoint::BlockEdgeKind:
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000196 HandleBlockEdge(cast<BlockEdge>(Node->getLocation()), Node);
197 break;
Mike Stump1eb44332009-09-09 15:08:12 +0000198
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000199 case ProgramPoint::BlockEntranceKind:
200 HandleBlockEntrance(cast<BlockEntrance>(Node->getLocation()), Node);
201 break;
Mike Stump1eb44332009-09-09 15:08:12 +0000202
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000203 case ProgramPoint::BlockExitKind:
Ted Kremenek425c08c2008-01-15 00:24:08 +0000204 assert (false && "BlockExit location never occur in forward analysis.");
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000205 break;
Ted Kremeneke1efd4d2008-12-16 22:13:33 +0000206
Douglas Gregor102acd52010-02-25 19:01:53 +0000207 case ProgramPoint::CallEnterKind:
208 HandleCallEnter(cast<CallEnter>(Node->getLocation()), WU.getBlock(),
209 WU.getIndex(), Node);
210 break;
211
212 case ProgramPoint::CallExitKind:
213 HandleCallExit(cast<CallExit>(Node->getLocation()), Node);
214 break;
215
Ted Kremeneke1efd4d2008-12-16 22:13:33 +0000216 default:
217 assert(isa<PostStmt>(Node->getLocation()));
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000218 HandlePostStmt(cast<PostStmt>(Node->getLocation()), WU.getBlock(),
219 WU.getIndex(), Node);
Mike Stump1eb44332009-09-09 15:08:12 +0000220 break;
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000221 }
222 }
Mike Stump1eb44332009-09-09 15:08:12 +0000223
Ted Kremeneke49f2ad2010-06-29 21:58:54 +0000224 SubEngine.ProcessEndWorklist(WList->hasWork() || BlockAborted);
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000225 return WList->hasWork();
226}
227
Douglas Gregor102acd52010-02-25 19:01:53 +0000228void GRCoreEngine::HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
229 unsigned Index, ExplodedNode *Pred) {
230 GRCallEnterNodeBuilder Builder(*this, Pred, L.getCallExpr(), L.getCallee(),
231 Block, Index);
232 ProcessCallEnter(Builder);
233}
234
235void GRCoreEngine::HandleCallExit(const CallExit &L, ExplodedNode *Pred) {
236 GRCallExitNodeBuilder Builder(*this, Pred);
237 ProcessCallExit(Builder);
238}
Zhongxing Xu0111f572009-08-06 10:00:15 +0000239
240void GRCoreEngine::HandleBlockEdge(const BlockEdge& L, ExplodedNode* Pred) {
Mike Stump1eb44332009-09-09 15:08:12 +0000241
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000242 CFGBlock* Blk = L.getDst();
Mike Stump1eb44332009-09-09 15:08:12 +0000243
244 // Check if we are entering the EXIT block.
Zhongxing Xucb74d722009-12-23 08:54:57 +0000245 if (Blk == &(L.getLocationContext()->getCFG()->getExit())) {
Mike Stump1eb44332009-09-09 15:08:12 +0000246
Zhongxing Xucb74d722009-12-23 08:54:57 +0000247 assert (L.getLocationContext()->getCFG()->getExit().size() == 0
Ted Kremenekcb48b9c2008-01-29 00:33:40 +0000248 && "EXIT block cannot contain Stmts.");
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000249
Ted Kremenek11062b12008-04-11 22:03:04 +0000250 // Process the final state transition.
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000251 GREndPathNodeBuilder Builder(Blk, Pred, this);
Ted Kremenek11062b12008-04-11 22:03:04 +0000252 ProcessEndPath(Builder);
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000253
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000254 // This path is done. Don't enqueue any more nodes.
255 return;
256 }
Ted Kremenek6a6719a2008-02-29 20:27:50 +0000257
258 // FIXME: Should we allow ProcessBlockEntrance to also manipulate state?
Mike Stump1eb44332009-09-09 15:08:12 +0000259
Zhongxing Xud9e0c0f2010-03-23 05:05:02 +0000260 if (ProcessBlockEntrance(Blk, Pred, WList->getBlockCounter()))
Ted Kremeneke49f2ad2010-06-29 21:58:54 +0000261 GenerateNode(BlockEntrance(Blk, Pred->getLocationContext()),
262 Pred->State, Pred);
263 else
264 BlockAborted = true;
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000265}
266
Zhongxing Xu0111f572009-08-06 10:00:15 +0000267void GRCoreEngine::HandleBlockEntrance(const BlockEntrance& L,
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000268 ExplodedNode* Pred) {
Mike Stump1eb44332009-09-09 15:08:12 +0000269
Ted Kremenek8e49dd62008-02-12 18:08:17 +0000270 // Increment the block counter.
271 GRBlockCounter Counter = WList->getBlockCounter();
Zhongxing Xud9e0c0f2010-03-23 05:05:02 +0000272 Counter = BCounterFactory.IncrementCount(Counter,
273 Pred->getLocationContext()->getCurrentStackFrame(),
274 L.getBlock()->getBlockID());
Ted Kremenek8e49dd62008-02-12 18:08:17 +0000275 WList->setBlockCounter(Counter);
Mike Stump1eb44332009-09-09 15:08:12 +0000276
277 // Process the entrance of the block.
Ted Kremenek852274d2009-12-16 03:18:58 +0000278 if (CFGElement E = L.getFirstElement()) {
Mike Stump1eb44332009-09-09 15:08:12 +0000279 GRStmtNodeBuilder Builder(L.getBlock(), 0, Pred, this,
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000280 SubEngine.getStateManager());
Ted Kremenek852274d2009-12-16 03:18:58 +0000281 ProcessStmt(E, Builder);
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000282 }
Mike Stump1eb44332009-09-09 15:08:12 +0000283 else
Ted Kremenek425c08c2008-01-15 00:24:08 +0000284 HandleBlockExit(L.getBlock(), Pred);
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000285}
286
Zhongxing Xu0111f572009-08-06 10:00:15 +0000287void GRCoreEngine::HandleBlockExit(CFGBlock * B, ExplodedNode* Pred) {
Mike Stump1eb44332009-09-09 15:08:12 +0000288
Ted Kremenek7d7fe6d2008-01-29 22:56:11 +0000289 if (Stmt* Term = B->getTerminator()) {
290 switch (Term->getStmtClass()) {
291 default:
292 assert(false && "Analysis for this terminator not implemented.");
293 break;
Mike Stump1eb44332009-09-09 15:08:12 +0000294
Ted Kremenekf8108692008-02-12 21:51:20 +0000295 case Stmt::BinaryOperatorClass: // '&&' and '||'
296 HandleBranch(cast<BinaryOperator>(Term)->getLHS(), Term, B, Pred);
297 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000298
Ted Kremenekf233d482008-02-05 00:26:40 +0000299 case Stmt::ConditionalOperatorClass:
300 HandleBranch(cast<ConditionalOperator>(Term)->getCond(), Term, B, Pred);
Ted Kremenekf8108692008-02-12 21:51:20 +0000301 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000302
Ted Kremenekf8108692008-02-12 21:51:20 +0000303 // FIXME: Use constant-folding in CFG construction to simplify this
304 // case.
Mike Stump1eb44332009-09-09 15:08:12 +0000305
Ted Kremenekf233d482008-02-05 00:26:40 +0000306 case Stmt::ChooseExprClass:
307 HandleBranch(cast<ChooseExpr>(Term)->getCond(), Term, B, Pred);
Ted Kremenekf8108692008-02-12 21:51:20 +0000308 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000309
Ted Kremenekf8108692008-02-12 21:51:20 +0000310 case Stmt::DoStmtClass:
311 HandleBranch(cast<DoStmt>(Term)->getCond(), Term, B, Pred);
312 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000313
Ted Kremenekf8108692008-02-12 21:51:20 +0000314 case Stmt::ForStmtClass:
315 HandleBranch(cast<ForStmt>(Term)->getCond(), Term, B, Pred);
316 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000317
Ted Kremeneka58e8332008-02-13 16:56:51 +0000318 case Stmt::ContinueStmtClass:
319 case Stmt::BreakStmtClass:
Mike Stump1eb44332009-09-09 15:08:12 +0000320 case Stmt::GotoStmtClass:
Ted Kremenekf233d482008-02-05 00:26:40 +0000321 break;
Mike Stump1eb44332009-09-09 15:08:12 +0000322
Ted Kremenek7d7fe6d2008-01-29 22:56:11 +0000323 case Stmt::IfStmtClass:
324 HandleBranch(cast<IfStmt>(Term)->getCond(), Term, B, Pred);
Ted Kremenekf8108692008-02-12 21:51:20 +0000325 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000326
Ted Kremenek754607e2008-02-13 00:24:44 +0000327 case Stmt::IndirectGotoStmtClass: {
328 // Only 1 successor: the indirect goto dispatch block.
329 assert (B->succ_size() == 1);
Mike Stump1eb44332009-09-09 15:08:12 +0000330
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000331 GRIndirectGotoNodeBuilder
Ted Kremenek754607e2008-02-13 00:24:44 +0000332 builder(Pred, B, cast<IndirectGotoStmt>(Term)->getTarget(),
333 *(B->succ_begin()), this);
Mike Stump1eb44332009-09-09 15:08:12 +0000334
Ted Kremenek754607e2008-02-13 00:24:44 +0000335 ProcessIndirectGoto(builder);
336 return;
337 }
Mike Stump1eb44332009-09-09 15:08:12 +0000338
Ted Kremenekaf337412008-11-12 19:24:17 +0000339 case Stmt::ObjCForCollectionStmtClass: {
340 // In the case of ObjCForCollectionStmt, it appears twice in a CFG:
341 //
342 // (1) inside a basic block, which represents the binding of the
343 // 'element' variable to a value.
344 // (2) in a terminator, which represents the branch.
345 //
346 // For (1), subengines will bind a value (i.e., 0 or 1) indicating
347 // whether or not collection contains any more elements. We cannot
348 // just test to see if the element is nil because a container can
349 // contain nil elements.
350 HandleBranch(Term, Term, B, Pred);
351 return;
352 }
Mike Stump1eb44332009-09-09 15:08:12 +0000353
Ted Kremenekdaeb9a72008-02-13 23:08:21 +0000354 case Stmt::SwitchStmtClass: {
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000355 GRSwitchNodeBuilder builder(Pred, B, cast<SwitchStmt>(Term)->getCond(),
356 this);
Mike Stump1eb44332009-09-09 15:08:12 +0000357
Ted Kremenekdaeb9a72008-02-13 23:08:21 +0000358 ProcessSwitch(builder);
359 return;
360 }
Mike Stump1eb44332009-09-09 15:08:12 +0000361
Ted Kremenek7d7fe6d2008-01-29 22:56:11 +0000362 case Stmt::WhileStmtClass:
363 HandleBranch(cast<WhileStmt>(Term)->getCond(), Term, B, Pred);
Ted Kremenekf8108692008-02-12 21:51:20 +0000364 return;
Ted Kremenek7d7fe6d2008-01-29 22:56:11 +0000365 }
366 }
Ted Kremenekf8108692008-02-12 21:51:20 +0000367
368 assert (B->succ_size() == 1 &&
369 "Blocks with no terminator should have at most 1 successor.");
Mike Stump1eb44332009-09-09 15:08:12 +0000370
371 GenerateNode(BlockEdge(B, *(B->succ_begin()), Pred->getLocationContext()),
Zhongxing Xu25e695b2009-08-15 03:17:38 +0000372 Pred->State, Pred);
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000373}
374
Zhongxing Xu0111f572009-08-06 10:00:15 +0000375void GRCoreEngine::HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock * B,
376 ExplodedNode* Pred) {
Ted Kremenek7d7fe6d2008-01-29 22:56:11 +0000377 assert (B->succ_size() == 2);
378
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000379 GRBranchNodeBuilder Builder(B, *(B->succ_begin()), *(B->succ_begin()+1),
380 Pred, this);
Mike Stump1eb44332009-09-09 15:08:12 +0000381
Ted Kremenek7d7fe6d2008-01-29 22:56:11 +0000382 ProcessBranch(Cond, Term, Builder);
383}
384
Zhongxing Xu0111f572009-08-06 10:00:15 +0000385void GRCoreEngine::HandlePostStmt(const PostStmt& L, CFGBlock* B,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000386 unsigned StmtIdx, ExplodedNode* Pred) {
Mike Stump1eb44332009-09-09 15:08:12 +0000387
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000388 assert (!B->empty());
389
Ted Kremenek425c08c2008-01-15 00:24:08 +0000390 if (StmtIdx == B->size())
391 HandleBlockExit(B, Pred);
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000392 else {
Mike Stump1eb44332009-09-09 15:08:12 +0000393 GRStmtNodeBuilder Builder(B, StmtIdx, Pred, this,
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000394 SubEngine.getStateManager());
Ted Kremenek160760e2008-01-16 22:13:19 +0000395 ProcessStmt((*B)[StmtIdx], Builder);
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000396 }
397}
398
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000399/// GenerateNode - Utility method to generate nodes, hook up successors,
400/// and add nodes to the worklist.
Mike Stump1eb44332009-09-09 15:08:12 +0000401void GRCoreEngine::GenerateNode(const ProgramPoint& Loc,
Zhongxing Xu0111f572009-08-06 10:00:15 +0000402 const GRState* State, ExplodedNode* Pred) {
Mike Stump1eb44332009-09-09 15:08:12 +0000403
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000404 bool IsNew;
Zhongxing Xu38b02b92009-08-06 06:28:40 +0000405 ExplodedNode* Node = G->getNode(Loc, State, &IsNew);
Mike Stump1eb44332009-09-09 15:08:12 +0000406
407 if (Pred)
Ted Kremenek5fe4d9d2009-10-07 00:42:52 +0000408 Node->addPredecessor(Pred, *G); // Link 'Node' with its predecessor.
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000409 else {
410 assert (IsNew);
411 G->addRoot(Node); // 'Node' has no predecessor. Make it a root.
412 }
Mike Stump1eb44332009-09-09 15:08:12 +0000413
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000414 // Only add 'Node' to the worklist if it was freshly generated.
Ted Kremenek8e49dd62008-02-12 18:08:17 +0000415 if (IsNew) WList->Enqueue(Node);
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000416}
417
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000418GRStmtNodeBuilder::GRStmtNodeBuilder(CFGBlock* b, unsigned idx,
419 ExplodedNode* N, GRCoreEngine* e,
420 GRStateManager &mgr)
Zhongxing Xu25108a52010-02-26 02:38:09 +0000421 : Eng(*e), B(*b), Idx(idx), Pred(N), Mgr(mgr), Auditor(0),
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000422 PurgingDeadSymbols(false), BuildSinks(false), HasGeneratedNode(false),
423 PointKind(ProgramPoint::PostStmtKind), Tag(0) {
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000424 Deferred.insert(N);
Zhongxing Xu25108a52010-02-26 02:38:09 +0000425 CleanedState = Pred->getState();
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000426}
427
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000428GRStmtNodeBuilder::~GRStmtNodeBuilder() {
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000429 for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
Ted Kremenekb38911f2008-01-30 23:03:39 +0000430 if (!(*I)->isSink())
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000431 GenerateAutoTransition(*I);
432}
433
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000434void GRStmtNodeBuilder::GenerateAutoTransition(ExplodedNode* N) {
Ted Kremenekb38911f2008-01-30 23:03:39 +0000435 assert (!N->isSink());
Mike Stump1eb44332009-09-09 15:08:12 +0000436
Douglas Gregor102acd52010-02-25 19:01:53 +0000437 // Check if this node entered a callee.
438 if (isa<CallEnter>(N->getLocation())) {
439 // Still use the index of the CallExpr. It's needed to create the callee
440 // StackFrameContext.
441 Eng.WList->Enqueue(N, B, Idx);
442 return;
443 }
444
Zhongxing Xu25e695b2009-08-15 03:17:38 +0000445 PostStmt Loc(getStmt(), N->getLocationContext());
Mike Stump1eb44332009-09-09 15:08:12 +0000446
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000447 if (Loc == N->getLocation()) {
448 // Note: 'N' should be a fresh node because otherwise it shouldn't be
449 // a member of Deferred.
450 Eng.WList->Enqueue(N, B, Idx+1);
451 return;
452 }
Mike Stump1eb44332009-09-09 15:08:12 +0000453
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000454 bool IsNew;
Zhongxing Xu38b02b92009-08-06 06:28:40 +0000455 ExplodedNode* Succ = Eng.G->getNode(Loc, N->State, &IsNew);
Ted Kremenek5fe4d9d2009-10-07 00:42:52 +0000456 Succ->addPredecessor(N, *Eng.G);
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000457
458 if (IsNew)
459 Eng.WList->Enqueue(Succ, B, Idx+1);
460}
461
Zhongxing Xu868e78d2010-04-14 06:35:09 +0000462ExplodedNode* GRStmtNodeBuilder::MakeNode(ExplodedNodeSet& Dst, Stmt* S,
463 ExplodedNode* Pred, const GRState* St,
464 ProgramPoint::Kind K) {
465 const GRState* PredState = GetState(Pred);
466
467 // If the state hasn't changed, don't generate a new node.
468 if (!BuildSinks && St == PredState && Auditor == 0) {
469 Dst.Add(Pred);
470 return NULL;
471 }
472
473 ExplodedNode* N = generateNode(S, St, Pred, K);
474
475 if (N) {
476 if (BuildSinks)
477 N->markAsSink();
478 else {
479 if (Auditor && Auditor->Audit(N, Mgr))
480 N->markAsSink();
481
482 Dst.Add(N);
483 }
484 }
485
486 return N;
487}
488
Ted Kremenekb4b817d2009-11-11 03:26:34 +0000489static ProgramPoint GetProgramPoint(const Stmt *S, ProgramPoint::Kind K,
490 const LocationContext *LC, const void *tag){
Ted Kremenek331b0ac2008-06-18 05:34:07 +0000491 switch (K) {
492 default:
Ted Kremenekb4b817d2009-11-11 03:26:34 +0000493 assert(false && "Unhandled ProgramPoint kind");
494 case ProgramPoint::PreStmtKind:
495 return PreStmt(S, LC, tag);
Ted Kremenek331b0ac2008-06-18 05:34:07 +0000496 case ProgramPoint::PostStmtKind:
Ted Kremenekb4b817d2009-11-11 03:26:34 +0000497 return PostStmt(S, LC, tag);
498 case ProgramPoint::PreLoadKind:
499 return PreLoad(S, LC, tag);
Ted Kremenek331b0ac2008-06-18 05:34:07 +0000500 case ProgramPoint::PostLoadKind:
Ted Kremenekb4b817d2009-11-11 03:26:34 +0000501 return PostLoad(S, LC, tag);
502 case ProgramPoint::PreStoreKind:
503 return PreStore(S, LC, tag);
Ted Kremenekbf4e4192008-10-17 20:49:23 +0000504 case ProgramPoint::PostStoreKind:
Ted Kremenekb4b817d2009-11-11 03:26:34 +0000505 return PostStore(S, LC, tag);
Ted Kremenek7090d542009-05-07 18:27:16 +0000506 case ProgramPoint::PostLValueKind:
Ted Kremenekb4b817d2009-11-11 03:26:34 +0000507 return PostLValue(S, LC, tag);
Ted Kremenek331b0ac2008-06-18 05:34:07 +0000508 case ProgramPoint::PostPurgeDeadSymbolsKind:
Ted Kremenekb4b817d2009-11-11 03:26:34 +0000509 return PostPurgeDeadSymbols(S, LC, tag);
Ted Kremenek331b0ac2008-06-18 05:34:07 +0000510 }
511}
512
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000513ExplodedNode*
Ted Kremenekb4b817d2009-11-11 03:26:34 +0000514GRStmtNodeBuilder::generateNodeInternal(const Stmt* S, const GRState* state,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000515 ExplodedNode* Pred,
Ted Kremenek1670e402009-04-11 00:11:10 +0000516 ProgramPoint::Kind K,
517 const void *tag) {
Ted Kremenekb4b817d2009-11-11 03:26:34 +0000518
Zhongxing Xucb74d722009-12-23 08:54:57 +0000519 const ProgramPoint &L = GetProgramPoint(S, K, Pred->getLocationContext(),tag);
Ted Kremenekb4b817d2009-11-11 03:26:34 +0000520 return generateNodeInternal(L, state, Pred);
Ted Kremenek58e899b2009-02-19 23:45:28 +0000521}
522
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000523ExplodedNode*
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000524GRStmtNodeBuilder::generateNodeInternal(const ProgramPoint &Loc,
Zhongxing Xu38b02b92009-08-06 06:28:40 +0000525 const GRState* State,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000526 ExplodedNode* Pred) {
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000527 bool IsNew;
Zhongxing Xu38b02b92009-08-06 06:28:40 +0000528 ExplodedNode* N = Eng.G->getNode(Loc, State, &IsNew);
Ted Kremenek5fe4d9d2009-10-07 00:42:52 +0000529 N->addPredecessor(Pred, *Eng.G);
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000530 Deferred.erase(Pred);
Mike Stump1eb44332009-09-09 15:08:12 +0000531
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000532 if (IsNew) {
533 Deferred.insert(N);
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000534 return N;
535 }
Mike Stump1eb44332009-09-09 15:08:12 +0000536
Mike Stump1eb44332009-09-09 15:08:12 +0000537 return NULL;
Ted Kremenekf24af5b2008-01-14 23:24:37 +0000538}
Ted Kremenek7d7fe6d2008-01-29 22:56:11 +0000539
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000540ExplodedNode* GRBranchNodeBuilder::generateNode(const GRState* State,
541 bool branch) {
Mike Stump1eb44332009-09-09 15:08:12 +0000542
Ted Kremenek52003542009-07-20 18:44:36 +0000543 // If the branch has been marked infeasible we should not generate a node.
544 if (!isFeasible(branch))
545 return NULL;
Mike Stump1eb44332009-09-09 15:08:12 +0000546
Ted Kremenek7d7fe6d2008-01-29 22:56:11 +0000547 bool IsNew;
Mike Stump1eb44332009-09-09 15:08:12 +0000548
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000549 ExplodedNode* Succ =
Zhongxing Xu25e695b2009-08-15 03:17:38 +0000550 Eng.G->getNode(BlockEdge(Src,branch ? DstT:DstF,Pred->getLocationContext()),
551 State, &IsNew);
Mike Stump1eb44332009-09-09 15:08:12 +0000552
Ted Kremenek5fe4d9d2009-10-07 00:42:52 +0000553 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump1eb44332009-09-09 15:08:12 +0000554
Ted Kremenek52003542009-07-20 18:44:36 +0000555 if (branch)
556 GeneratedTrue = true;
557 else
Mike Stump1eb44332009-09-09 15:08:12 +0000558 GeneratedFalse = true;
559
Ted Kremenekb38911f2008-01-30 23:03:39 +0000560 if (IsNew) {
Ted Kremenek3b4f6702008-01-30 23:24:39 +0000561 Deferred.push_back(Succ);
Ted Kremenekb38911f2008-01-30 23:03:39 +0000562 return Succ;
563 }
Mike Stump1eb44332009-09-09 15:08:12 +0000564
Ted Kremenekb38911f2008-01-30 23:03:39 +0000565 return NULL;
Ted Kremenek7d7fe6d2008-01-29 22:56:11 +0000566}
Ted Kremenek71c29bd2008-01-29 23:32:35 +0000567
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000568GRBranchNodeBuilder::~GRBranchNodeBuilder() {
569 if (!GeneratedTrue) generateNode(Pred->State, true);
570 if (!GeneratedFalse) generateNode(Pred->State, false);
Mike Stump1eb44332009-09-09 15:08:12 +0000571
Ted Kremenek3b4f6702008-01-30 23:24:39 +0000572 for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
Ted Kremenek8e49dd62008-02-12 18:08:17 +0000573 if (!(*I)->isSink()) Eng.WList->Enqueue(*I);
Ted Kremenek71c29bd2008-01-29 23:32:35 +0000574}
Ted Kremenek754607e2008-02-13 00:24:44 +0000575
Ted Kremenek754607e2008-02-13 00:24:44 +0000576
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000577ExplodedNode*
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000578GRIndirectGotoNodeBuilder::generateNode(const iterator& I, const GRState* St,
579 bool isSink) {
Ted Kremenek754607e2008-02-13 00:24:44 +0000580 bool IsNew;
Mike Stump1eb44332009-09-09 15:08:12 +0000581
582 ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
Zhongxing Xu25e695b2009-08-15 03:17:38 +0000583 Pred->getLocationContext()), St, &IsNew);
Mike Stump1eb44332009-09-09 15:08:12 +0000584
Ted Kremenek5fe4d9d2009-10-07 00:42:52 +0000585 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump1eb44332009-09-09 15:08:12 +0000586
Ted Kremenek754607e2008-02-13 00:24:44 +0000587 if (IsNew) {
Mike Stump1eb44332009-09-09 15:08:12 +0000588
Ted Kremenek754607e2008-02-13 00:24:44 +0000589 if (isSink)
590 Succ->markAsSink();
591 else
592 Eng.WList->Enqueue(Succ);
Mike Stump1eb44332009-09-09 15:08:12 +0000593
Ted Kremenek754607e2008-02-13 00:24:44 +0000594 return Succ;
595 }
Mike Stump1eb44332009-09-09 15:08:12 +0000596
Ted Kremenek754607e2008-02-13 00:24:44 +0000597 return NULL;
598}
Ted Kremenekdaeb9a72008-02-13 23:08:21 +0000599
600
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000601ExplodedNode*
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000602GRSwitchNodeBuilder::generateCaseStmtNode(const iterator& I, const GRState* St){
Ted Kremenekdaeb9a72008-02-13 23:08:21 +0000603
604 bool IsNew;
Mike Stump1eb44332009-09-09 15:08:12 +0000605
Zhongxing Xu25e695b2009-08-15 03:17:38 +0000606 ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
607 Pred->getLocationContext()), St, &IsNew);
Ted Kremenek5fe4d9d2009-10-07 00:42:52 +0000608 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump1eb44332009-09-09 15:08:12 +0000609
Ted Kremenekdaeb9a72008-02-13 23:08:21 +0000610 if (IsNew) {
611 Eng.WList->Enqueue(Succ);
612 return Succ;
613 }
Mike Stump1eb44332009-09-09 15:08:12 +0000614
Ted Kremenekdaeb9a72008-02-13 23:08:21 +0000615 return NULL;
616}
617
618
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000619ExplodedNode*
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000620GRSwitchNodeBuilder::generateDefaultCaseNode(const GRState* St, bool isSink) {
Mike Stump1eb44332009-09-09 15:08:12 +0000621
Ted Kremenekdaeb9a72008-02-13 23:08:21 +0000622 // Get the block for the default case.
623 assert (Src->succ_rbegin() != Src->succ_rend());
624 CFGBlock* DefaultBlock = *Src->succ_rbegin();
Mike Stump1eb44332009-09-09 15:08:12 +0000625
Ted Kremenekdaeb9a72008-02-13 23:08:21 +0000626 bool IsNew;
Mike Stump1eb44332009-09-09 15:08:12 +0000627
Zhongxing Xu25e695b2009-08-15 03:17:38 +0000628 ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, DefaultBlock,
629 Pred->getLocationContext()), St, &IsNew);
Ted Kremenek5fe4d9d2009-10-07 00:42:52 +0000630 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump1eb44332009-09-09 15:08:12 +0000631
Ted Kremenekdaeb9a72008-02-13 23:08:21 +0000632 if (IsNew) {
633 if (isSink)
634 Succ->markAsSink();
635 else
636 Eng.WList->Enqueue(Succ);
Mike Stump1eb44332009-09-09 15:08:12 +0000637
Ted Kremenekdaeb9a72008-02-13 23:08:21 +0000638 return Succ;
639 }
Mike Stump1eb44332009-09-09 15:08:12 +0000640
Ted Kremenekdaeb9a72008-02-13 23:08:21 +0000641 return NULL;
642}
Ted Kremenek11062b12008-04-11 22:03:04 +0000643
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000644GREndPathNodeBuilder::~GREndPathNodeBuilder() {
Ted Kremenek11062b12008-04-11 22:03:04 +0000645 // Auto-generate an EOP node if one has not been generated.
Douglas Gregor102acd52010-02-25 19:01:53 +0000646 if (!HasGeneratedNode) {
647 // If we are in an inlined call, generate CallExit node.
648 if (Pred->getLocationContext()->getParent())
649 GenerateCallExitNode(Pred->State);
650 else
651 generateNode(Pred->State);
652 }
Ted Kremenek11062b12008-04-11 22:03:04 +0000653}
654
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000655ExplodedNode*
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000656GREndPathNodeBuilder::generateNode(const GRState* State, const void *tag,
657 ExplodedNode* P) {
Mike Stump1eb44332009-09-09 15:08:12 +0000658 HasGeneratedNode = true;
Ted Kremenek11062b12008-04-11 22:03:04 +0000659 bool IsNew;
Mike Stump1eb44332009-09-09 15:08:12 +0000660
661 ExplodedNode* Node = Eng.G->getNode(BlockEntrance(&B,
Zhongxing Xu25e695b2009-08-15 03:17:38 +0000662 Pred->getLocationContext(), tag), State, &IsNew);
Mike Stump1eb44332009-09-09 15:08:12 +0000663
Ted Kremenek5fe4d9d2009-10-07 00:42:52 +0000664 Node->addPredecessor(P ? P : Pred, *Eng.G);
Mike Stump1eb44332009-09-09 15:08:12 +0000665
Ted Kremenek11062b12008-04-11 22:03:04 +0000666 if (IsNew) {
Ted Kremenek11062b12008-04-11 22:03:04 +0000667 Eng.G->addEndOfPath(Node);
Ted Kremenek4f285152008-04-18 16:30:14 +0000668 return Node;
Ted Kremenek11062b12008-04-11 22:03:04 +0000669 }
Mike Stump1eb44332009-09-09 15:08:12 +0000670
Ted Kremenek4f285152008-04-18 16:30:14 +0000671 return NULL;
Ted Kremenek11062b12008-04-11 22:03:04 +0000672}
Douglas Gregor102acd52010-02-25 19:01:53 +0000673
674void GREndPathNodeBuilder::GenerateCallExitNode(const GRState *state) {
675 HasGeneratedNode = true;
676 // Create a CallExit node and enqueue it.
677 const StackFrameContext *LocCtx
678 = cast<StackFrameContext>(Pred->getLocationContext());
679 const Stmt *CE = LocCtx->getCallSite();
680
681 // Use the the callee location context.
682 CallExit Loc(CE, LocCtx);
683
684 bool isNew;
685 ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew);
686 Node->addPredecessor(Pred, *Eng.G);
687
688 if (isNew)
689 Eng.WList->Enqueue(Node);
690}
691
692
693void GRCallEnterNodeBuilder::GenerateNode(const GRState *state,
694 const LocationContext *LocCtx) {
695 // Get the callee entry block.
696 const CFGBlock *Entry = &(LocCtx->getCFG()->getEntry());
697 assert(Entry->empty());
698 assert(Entry->succ_size() == 1);
699
700 // Get the solitary successor.
701 const CFGBlock *SuccB = *(Entry->succ_begin());
702
703 // Construct an edge representing the starting location in the callee.
704 BlockEdge Loc(Entry, SuccB, LocCtx);
705
706 bool isNew;
707 ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew);
708 Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G);
709
710 if (isNew)
711 Eng.WList->Enqueue(Node);
712}
713
714void GRCallExitNodeBuilder::GenerateNode(const GRState *state) {
715 // Get the callee's location context.
716 const StackFrameContext *LocCtx
717 = cast<StackFrameContext>(Pred->getLocationContext());
718
719 PostStmt Loc(LocCtx->getCallSite(), LocCtx->getParent());
720 bool isNew;
721 ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew);
722 Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G);
723 if (isNew)
724 Eng.WList->Enqueue(Node, *const_cast<CFGBlock*>(LocCtx->getCallSiteBlock()),
725 LocCtx->getIndex() + 1);
726}