blob: 5a45ad2ce4f51d25466f68b54e05f93f4b4eb009 [file] [log] [blame]
Ted Kremenek17810802008-11-12 19:24:17 +00001//==- GRCoreEngine.cpp - Path-Sensitive Dataflow Engine ------------*- C++ -*-//
Ted Kremenek3e743662008-01-14 23:24:37 +00002//
3// 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 Kremenekf6c62f32008-02-13 17:41:41 +000015#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
Ted Kremenek3e743662008-01-14 23:24:37 +000016#include "clang/AST/Expr.h"
17#include "llvm/Support/Compiler.h"
18#include "llvm/Support/Casting.h"
19#include "llvm/ADT/DenseMap.h"
20#include <vector>
Ted Kremenekd9de9f12008-12-16 22:13:33 +000021#include <queue>
Ted Kremenek3e743662008-01-14 23:24:37 +000022
23using llvm::cast;
24using llvm::isa;
25using namespace clang;
26
Ted Kremenekd9de9f12008-12-16 22:13:33 +000027//===----------------------------------------------------------------------===//
28// Worklist classes for exploration of reachable states.
29//===----------------------------------------------------------------------===//
30
Ted Kremenek3e743662008-01-14 23:24:37 +000031namespace {
Zhongxing Xu69cc15e2009-07-15 09:04:01 +000032class VISIBILITY_HIDDEN DFS : public GRWorkList {
Ted Kremenek3e743662008-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};
Ted Kremenek2c327732009-05-01 22:18:46 +000050
51class VISIBILITY_HIDDEN BFS : public GRWorkList {
52 std::queue<GRWorkListUnit> Queue;
53public:
54 virtual bool hasWork() const {
55 return !Queue.empty();
56 }
57
58 virtual void Enqueue(const GRWorkListUnit& U) {
59 Queue.push(U);
60 }
61
62 virtual GRWorkListUnit Dequeue() {
63 // Don't use const reference. The subsequent pop_back() might make it
64 // unsafe.
65 GRWorkListUnit U = Queue.front();
66 Queue.pop();
67 return U;
68 }
69};
70
Ted Kremenek3e743662008-01-14 23:24:37 +000071} // end anonymous namespace
72
Ted Kremenek2e12c2e2008-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 Kremenek2c327732009-05-01 22:18:46 +000077GRWorkList *GRWorkList::MakeDFS() { return new DFS(); }
78GRWorkList *GRWorkList::MakeBFS() { return new BFS(); }
Ted Kremenek3e743662008-01-14 23:24:37 +000079
Ted Kremenekd9de9f12008-12-16 22:13:33 +000080namespace {
81 class VISIBILITY_HIDDEN BFSBlockDFSContents : public GRWorkList {
82 std::queue<GRWorkListUnit> Queue;
83 llvm::SmallVector<GRWorkListUnit,20> Stack;
84 public:
85 virtual bool hasWork() const {
86 return !Queue.empty() || !Stack.empty();
87 }
88
89 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 }
95
96 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 }
103
104 assert(!Queue.empty());
105 // Don't use const reference. The subsequent pop_back() might make it
106 // unsafe.
107 GRWorkListUnit U = Queue.front();
108 Queue.pop();
109 return U;
110 }
111 };
112} // end anonymous namespace
113
114GRWorkList* GRWorkList::MakeBFSBlockDFSContents() {
115 return new BFSBlockDFSContents();
116}
117
118//===----------------------------------------------------------------------===//
119// Core analysis engine.
120//===----------------------------------------------------------------------===//
121
Ted Kremenek3e743662008-01-14 23:24:37 +0000122/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
Ted Kremenekf6c62f32008-02-13 17:41:41 +0000123bool GRCoreEngineImpl::ExecuteWorkList(unsigned Steps) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000124
125 if (G->num_roots() == 0) { // Initialize the analysis by constructing
126 // the root if none exists.
127
Ted Kremenek997d8722008-01-29 00:33:40 +0000128 CFGBlock* Entry = &getCFG().getEntry();
Ted Kremenek3e743662008-01-14 23:24:37 +0000129
130 assert (Entry->empty() &&
131 "Entry block must be empty.");
132
133 assert (Entry->succ_size() == 1 &&
134 "Entry block must have 1 successor.");
135
136 // Get the solitary successor.
137 CFGBlock* Succ = *(Entry->succ_begin());
138
139 // Construct an edge representing the
140 // starting location in the function.
Ted Kremenek0ecb53a2008-09-16 18:44:52 +0000141 BlockEdge StartLoc(Entry, Succ);
Ted Kremenek3e743662008-01-14 23:24:37 +0000142
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000143 // Set the current block counter to being empty.
144 WList->setBlockCounter(BCounterFactory.GetEmptyCounter());
145
Ted Kremenek3e743662008-01-14 23:24:37 +0000146 // Generate the root.
Ted Kremenekaf665822008-08-26 22:34:23 +0000147 GenerateNode(StartLoc, getInitialState(), 0);
Ted Kremenek3e743662008-01-14 23:24:37 +0000148 }
149
150 while (Steps && WList->hasWork()) {
151 --Steps;
152 const GRWorkListUnit& WU = WList->Dequeue();
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000153
154 // Set the current block counter.
155 WList->setBlockCounter(WU.getBlockCounter());
156
157 // Retrieve the node.
Ted Kremenek3e743662008-01-14 23:24:37 +0000158 ExplodedNodeImpl* Node = WU.getNode();
159
160 // Dispatch on the location type.
161 switch (Node->getLocation().getKind()) {
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000162 case ProgramPoint::BlockEdgeKind:
Ted Kremenek3e743662008-01-14 23:24:37 +0000163 HandleBlockEdge(cast<BlockEdge>(Node->getLocation()), Node);
164 break;
165
166 case ProgramPoint::BlockEntranceKind:
167 HandleBlockEntrance(cast<BlockEntrance>(Node->getLocation()), Node);
168 break;
169
170 case ProgramPoint::BlockExitKind:
Ted Kremeneke5843592008-01-15 00:24:08 +0000171 assert (false && "BlockExit location never occur in forward analysis.");
Ted Kremenek3e743662008-01-14 23:24:37 +0000172 break;
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000173
174 default:
175 assert(isa<PostStmt>(Node->getLocation()));
Ted Kremenek3e743662008-01-14 23:24:37 +0000176 HandlePostStmt(cast<PostStmt>(Node->getLocation()), WU.getBlock(),
177 WU.getIndex(), Node);
178 break;
179 }
180 }
181
182 return WList->hasWork();
183}
184
Ted Kremenekdf4a5b92008-03-05 19:08:15 +0000185void GRCoreEngineImpl::HandleBlockEdge(const BlockEdge& L,
186 ExplodedNodeImpl* Pred) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000187
188 CFGBlock* Blk = L.getDst();
189
190 // Check if we are entering the EXIT block.
Ted Kremenek997d8722008-01-29 00:33:40 +0000191 if (Blk == &getCFG().getExit()) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000192
Ted Kremenek997d8722008-01-29 00:33:40 +0000193 assert (getCFG().getExit().size() == 0
194 && "EXIT block cannot contain Stmts.");
Ted Kremenek3e743662008-01-14 23:24:37 +0000195
Ted Kremenek811c2b42008-04-11 22:03:04 +0000196 // Process the final state transition.
197 GREndPathNodeBuilderImpl Builder(Blk, Pred, this);
198 ProcessEndPath(Builder);
Ted Kremenek3e743662008-01-14 23:24:37 +0000199
Ted Kremenek3e743662008-01-14 23:24:37 +0000200 // This path is done. Don't enqueue any more nodes.
201 return;
202 }
Ted Kremenek17f4dbd2008-02-29 20:27:50 +0000203
204 // FIXME: Should we allow ProcessBlockEntrance to also manipulate state?
Ted Kremenek3e743662008-01-14 23:24:37 +0000205
Ted Kremenek17f4dbd2008-02-29 20:27:50 +0000206 if (ProcessBlockEntrance(Blk, Pred->State, WList->getBlockCounter()))
207 GenerateNode(BlockEntrance(Blk), Pred->State, Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000208}
209
Ted Kremenekf6c62f32008-02-13 17:41:41 +0000210void GRCoreEngineImpl::HandleBlockEntrance(const BlockEntrance& L,
Ted Kremenekdf4a5b92008-03-05 19:08:15 +0000211 ExplodedNodeImpl* Pred) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000212
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000213 // Increment the block counter.
214 GRBlockCounter Counter = WList->getBlockCounter();
215 Counter = BCounterFactory.IncrementCount(Counter, L.getBlock()->getBlockID());
216 WList->setBlockCounter(Counter);
217
218 // Process the entrance of the block.
Ted Kremenek3e743662008-01-14 23:24:37 +0000219 if (Stmt* S = L.getFirstStmt()) {
Ted Kremenekb2cad312008-01-29 22:11:49 +0000220 GRStmtNodeBuilderImpl Builder(L.getBlock(), 0, Pred, this);
Ted Kremenek3e743662008-01-14 23:24:37 +0000221 ProcessStmt(S, Builder);
222 }
Ted Kremeneke5843592008-01-15 00:24:08 +0000223 else
224 HandleBlockExit(L.getBlock(), Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000225}
226
Ted Kremenek3f91f032008-08-13 03:10:52 +0000227GRCoreEngineImpl::~GRCoreEngineImpl() {
228 delete WList;
229}
Ted Kremenek3e743662008-01-14 23:24:37 +0000230
Ted Kremenekf6c62f32008-02-13 17:41:41 +0000231void GRCoreEngineImpl::HandleBlockExit(CFGBlock * B, ExplodedNodeImpl* Pred) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000232
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000233 if (Stmt* Term = B->getTerminator()) {
234 switch (Term->getStmtClass()) {
235 default:
236 assert(false && "Analysis for this terminator not implemented.");
237 break;
Ted Kremenek822f7372008-02-12 21:51:20 +0000238
239 case Stmt::BinaryOperatorClass: // '&&' and '||'
240 HandleBranch(cast<BinaryOperator>(Term)->getLHS(), Term, B, Pred);
241 return;
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000242
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000243 case Stmt::ConditionalOperatorClass:
244 HandleBranch(cast<ConditionalOperator>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000245 return;
246
247 // FIXME: Use constant-folding in CFG construction to simplify this
248 // case.
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000249
250 case Stmt::ChooseExprClass:
251 HandleBranch(cast<ChooseExpr>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000252 return;
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000253
Ted Kremenek822f7372008-02-12 21:51:20 +0000254 case Stmt::DoStmtClass:
255 HandleBranch(cast<DoStmt>(Term)->getCond(), Term, B, Pred);
256 return;
257
258 case Stmt::ForStmtClass:
259 HandleBranch(cast<ForStmt>(Term)->getCond(), Term, B, Pred);
260 return;
Ted Kremenek632bcb82008-02-13 16:56:51 +0000261
262 case Stmt::ContinueStmtClass:
263 case Stmt::BreakStmtClass:
264 case Stmt::GotoStmtClass:
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000265 break;
266
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000267 case Stmt::IfStmtClass:
268 HandleBranch(cast<IfStmt>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000269 return;
Ted Kremenek7022efb2008-02-13 00:24:44 +0000270
271 case Stmt::IndirectGotoStmtClass: {
272 // Only 1 successor: the indirect goto dispatch block.
273 assert (B->succ_size() == 1);
274
275 GRIndirectGotoNodeBuilderImpl
276 builder(Pred, B, cast<IndirectGotoStmt>(Term)->getTarget(),
277 *(B->succ_begin()), this);
278
279 ProcessIndirectGoto(builder);
280 return;
281 }
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000282
Ted Kremenek17810802008-11-12 19:24:17 +0000283 case Stmt::ObjCForCollectionStmtClass: {
284 // In the case of ObjCForCollectionStmt, it appears twice in a CFG:
285 //
286 // (1) inside a basic block, which represents the binding of the
287 // 'element' variable to a value.
288 // (2) in a terminator, which represents the branch.
289 //
290 // For (1), subengines will bind a value (i.e., 0 or 1) indicating
291 // whether or not collection contains any more elements. We cannot
292 // just test to see if the element is nil because a container can
293 // contain nil elements.
294 HandleBranch(Term, Term, B, Pred);
295 return;
296 }
297
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000298 case Stmt::SwitchStmtClass: {
299 GRSwitchNodeBuilderImpl builder(Pred, B,
300 cast<SwitchStmt>(Term)->getCond(),
301 this);
302
303 ProcessSwitch(builder);
304 return;
305 }
306
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000307 case Stmt::WhileStmtClass:
308 HandleBranch(cast<WhileStmt>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000309 return;
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000310 }
311 }
Ted Kremenek822f7372008-02-12 21:51:20 +0000312
313 assert (B->succ_size() == 1 &&
314 "Blocks with no terminator should have at most 1 successor.");
Ted Kremenek3e743662008-01-14 23:24:37 +0000315
Ted Kremenek0ecb53a2008-09-16 18:44:52 +0000316 GenerateNode(BlockEdge(B, *(B->succ_begin())), Pred->State, Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000317}
318
Ted Kremenek17810802008-11-12 19:24:17 +0000319void GRCoreEngineImpl::HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock * B,
320 ExplodedNodeImpl* Pred) {
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000321 assert (B->succ_size() == 2);
322
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000323 GRBranchNodeBuilderImpl Builder(B, *(B->succ_begin()), *(B->succ_begin()+1),
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000324 Pred, this);
325
326 ProcessBranch(Cond, Term, Builder);
327}
328
Ted Kremenekf6c62f32008-02-13 17:41:41 +0000329void GRCoreEngineImpl::HandlePostStmt(const PostStmt& L, CFGBlock* B,
Ted Kremenek3e743662008-01-14 23:24:37 +0000330 unsigned StmtIdx, ExplodedNodeImpl* Pred) {
331
332 assert (!B->empty());
333
Ted Kremeneke5843592008-01-15 00:24:08 +0000334 if (StmtIdx == B->size())
335 HandleBlockExit(B, Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000336 else {
Ted Kremenekb2cad312008-01-29 22:11:49 +0000337 GRStmtNodeBuilderImpl Builder(B, StmtIdx, Pred, this);
Ted Kremeneke914bb82008-01-16 22:13:19 +0000338 ProcessStmt((*B)[StmtIdx], Builder);
Ted Kremenek3e743662008-01-14 23:24:37 +0000339 }
340}
341
Ted Kremenek3e743662008-01-14 23:24:37 +0000342/// GenerateNode - Utility method to generate nodes, hook up successors,
343/// and add nodes to the worklist.
Ted Kremeneka7b8ffb2008-07-10 22:03:41 +0000344void GRCoreEngineImpl::GenerateNode(const ProgramPoint& Loc, const void* State,
345 ExplodedNodeImpl* Pred) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000346
347 bool IsNew;
348 ExplodedNodeImpl* Node = G->getNodeImpl(Loc, State, &IsNew);
349
350 if (Pred)
351 Node->addPredecessor(Pred); // Link 'Node' with its predecessor.
352 else {
353 assert (IsNew);
354 G->addRoot(Node); // 'Node' has no predecessor. Make it a root.
355 }
356
357 // Only add 'Node' to the worklist if it was freshly generated.
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000358 if (IsNew) WList->Enqueue(Node);
Ted Kremenek3e743662008-01-14 23:24:37 +0000359}
360
Ted Kremenekb2cad312008-01-29 22:11:49 +0000361GRStmtNodeBuilderImpl::GRStmtNodeBuilderImpl(CFGBlock* b, unsigned idx,
Ted Kremenekf6c62f32008-02-13 17:41:41 +0000362 ExplodedNodeImpl* N, GRCoreEngineImpl* e)
Ted Kremenekc072b822008-04-18 20:35:30 +0000363 : Eng(*e), B(*b), Idx(idx), Pred(N), LastNode(N) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000364 Deferred.insert(N);
365}
366
Ted Kremenekb2cad312008-01-29 22:11:49 +0000367GRStmtNodeBuilderImpl::~GRStmtNodeBuilderImpl() {
Ted Kremenek3e743662008-01-14 23:24:37 +0000368 for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
Ted Kremeneka50d9852008-01-30 23:03:39 +0000369 if (!(*I)->isSink())
Ted Kremenek3e743662008-01-14 23:24:37 +0000370 GenerateAutoTransition(*I);
371}
372
Ted Kremenekb2cad312008-01-29 22:11:49 +0000373void GRStmtNodeBuilderImpl::GenerateAutoTransition(ExplodedNodeImpl* N) {
Ted Kremeneka50d9852008-01-30 23:03:39 +0000374 assert (!N->isSink());
Ted Kremenek3e743662008-01-14 23:24:37 +0000375
376 PostStmt Loc(getStmt());
377
378 if (Loc == N->getLocation()) {
379 // Note: 'N' should be a fresh node because otherwise it shouldn't be
380 // a member of Deferred.
381 Eng.WList->Enqueue(N, B, Idx+1);
382 return;
383 }
384
385 bool IsNew;
386 ExplodedNodeImpl* Succ = Eng.G->getNodeImpl(Loc, N->State, &IsNew);
387 Succ->addPredecessor(N);
388
389 if (IsNew)
390 Eng.WList->Enqueue(Succ, B, Idx+1);
391}
392
Ted Kremenekdf240002009-04-11 00:11:10 +0000393static inline PostStmt GetPostLoc(Stmt* S, ProgramPoint::Kind K,
394 const void *tag) {
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000395 switch (K) {
396 default:
397 assert(false && "Invalid PostXXXKind.");
398
399 case ProgramPoint::PostStmtKind:
Ted Kremenekdf240002009-04-11 00:11:10 +0000400 return PostStmt(S, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000401
402 case ProgramPoint::PostLoadKind:
Ted Kremenekdf240002009-04-11 00:11:10 +0000403 return PostLoad(S, tag);
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000404
405 case ProgramPoint::PostUndefLocationCheckFailedKind:
Ted Kremenekdf240002009-04-11 00:11:10 +0000406 return PostUndefLocationCheckFailed(S, tag);
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000407
408 case ProgramPoint::PostLocationChecksSucceedKind:
Ted Kremenekdf240002009-04-11 00:11:10 +0000409 return PostLocationChecksSucceed(S, tag);
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000410
411 case ProgramPoint::PostOutOfBoundsCheckFailedKind:
Ted Kremenekdf240002009-04-11 00:11:10 +0000412 return PostOutOfBoundsCheckFailed(S, tag);
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000413
414 case ProgramPoint::PostNullCheckFailedKind:
Ted Kremenekdf240002009-04-11 00:11:10 +0000415 return PostNullCheckFailed(S, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000416
Ted Kremeneka1966182008-10-17 20:49:23 +0000417 case ProgramPoint::PostStoreKind:
Ted Kremenekdf240002009-04-11 00:11:10 +0000418 return PostStore(S, tag);
Ted Kremeneka1966182008-10-17 20:49:23 +0000419
Ted Kremeneka6e08322009-05-07 18:27:16 +0000420 case ProgramPoint::PostLValueKind:
421 return PostLValue(S, tag);
422
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000423 case ProgramPoint::PostPurgeDeadSymbolsKind:
Ted Kremenekdf240002009-04-11 00:11:10 +0000424 return PostPurgeDeadSymbols(S, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000425 }
426}
427
Ted Kremenekfa5a3d02008-04-29 21:04:26 +0000428ExplodedNodeImpl*
Ted Kremeneka7b8ffb2008-07-10 22:03:41 +0000429GRStmtNodeBuilderImpl::generateNodeImpl(Stmt* S, const void* State,
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000430 ExplodedNodeImpl* Pred,
Ted Kremenekdf240002009-04-11 00:11:10 +0000431 ProgramPoint::Kind K,
432 const void *tag) {
Ted Kremenek27760792009-07-22 21:40:46 +0000433 return K == ProgramPoint::PreStmtKind
434 ? generateNodeImpl(PreStmt(S, tag), State, Pred)
435 : generateNodeImpl(GetPostLoc(S, K, tag), State, Pred);
Ted Kremenek513f0b12009-02-19 23:45:28 +0000436}
437
438ExplodedNodeImpl*
Ted Kremenek27760792009-07-22 21:40:46 +0000439GRStmtNodeBuilderImpl::generateNodeImpl(const ProgramPoint &Loc,
440 const void* State,
Ted Kremenekdf240002009-04-11 00:11:10 +0000441 ExplodedNodeImpl* Pred) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000442 bool IsNew;
Ted Kremenekfa5a3d02008-04-29 21:04:26 +0000443 ExplodedNodeImpl* N = Eng.G->getNodeImpl(Loc, State, &IsNew);
Ted Kremenek3e743662008-01-14 23:24:37 +0000444 N->addPredecessor(Pred);
445 Deferred.erase(Pred);
446
Ted Kremenek3e743662008-01-14 23:24:37 +0000447 if (IsNew) {
448 Deferred.insert(N);
449 LastNode = N;
450 return N;
451 }
452
453 LastNode = NULL;
454 return NULL;
455}
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000456
Ted Kremeneka7b8ffb2008-07-10 22:03:41 +0000457ExplodedNodeImpl* GRBranchNodeBuilderImpl::generateNodeImpl(const void* State,
Ted Kremenekaf9f3622009-07-20 18:44:36 +0000458 bool branch) {
459
460 // If the branch has been marked infeasible we should not generate a node.
461 if (!isFeasible(branch))
462 return NULL;
463
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000464 bool IsNew;
465
466 ExplodedNodeImpl* Succ =
Ted Kremenek0ecb53a2008-09-16 18:44:52 +0000467 Eng.G->getNodeImpl(BlockEdge(Src, branch ? DstT : DstF), State, &IsNew);
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000468
469 Succ->addPredecessor(Pred);
470
Ted Kremenekaf9f3622009-07-20 18:44:36 +0000471 if (branch)
472 GeneratedTrue = true;
473 else
474 GeneratedFalse = true;
Ted Kremenek7ff18932008-01-29 23:32:35 +0000475
Ted Kremeneka50d9852008-01-30 23:03:39 +0000476 if (IsNew) {
Ted Kremenek2531fce2008-01-30 23:24:39 +0000477 Deferred.push_back(Succ);
Ted Kremeneka50d9852008-01-30 23:03:39 +0000478 return Succ;
479 }
480
481 return NULL;
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000482}
Ted Kremenek7ff18932008-01-29 23:32:35 +0000483
484GRBranchNodeBuilderImpl::~GRBranchNodeBuilderImpl() {
485 if (!GeneratedTrue) generateNodeImpl(Pred->State, true);
486 if (!GeneratedFalse) generateNodeImpl(Pred->State, false);
Ted Kremenek2531fce2008-01-30 23:24:39 +0000487
488 for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000489 if (!(*I)->isSink()) Eng.WList->Enqueue(*I);
Ted Kremenek7ff18932008-01-29 23:32:35 +0000490}
Ted Kremenek7022efb2008-02-13 00:24:44 +0000491
Ted Kremenek7022efb2008-02-13 00:24:44 +0000492
493ExplodedNodeImpl*
Ted Kremenek2bba9012008-02-13 17:27:37 +0000494GRIndirectGotoNodeBuilderImpl::generateNodeImpl(const Iterator& I,
Ted Kremeneka7b8ffb2008-07-10 22:03:41 +0000495 const void* St,
Ted Kremenek7022efb2008-02-13 00:24:44 +0000496 bool isSink) {
497 bool IsNew;
498
499 ExplodedNodeImpl* Succ =
Ted Kremenek0ecb53a2008-09-16 18:44:52 +0000500 Eng.G->getNodeImpl(BlockEdge(Src, I.getBlock()), St, &IsNew);
Ted Kremenek7022efb2008-02-13 00:24:44 +0000501
502 Succ->addPredecessor(Pred);
503
504 if (IsNew) {
505
506 if (isSink)
507 Succ->markAsSink();
508 else
509 Eng.WList->Enqueue(Succ);
510
511 return Succ;
512 }
513
514 return NULL;
515}
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000516
517
518ExplodedNodeImpl*
Ted Kremeneka7b8ffb2008-07-10 22:03:41 +0000519GRSwitchNodeBuilderImpl::generateCaseStmtNodeImpl(const Iterator& I,
520 const void* St) {
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000521
522 bool IsNew;
523
Ted Kremenek0ecb53a2008-09-16 18:44:52 +0000524 ExplodedNodeImpl* Succ = Eng.G->getNodeImpl(BlockEdge(Src, I.getBlock()),
525 St, &IsNew);
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000526 Succ->addPredecessor(Pred);
527
528 if (IsNew) {
529 Eng.WList->Enqueue(Succ);
530 return Succ;
531 }
532
533 return NULL;
534}
535
536
537ExplodedNodeImpl*
Ted Kremeneka7b8ffb2008-07-10 22:03:41 +0000538GRSwitchNodeBuilderImpl::generateDefaultCaseNodeImpl(const void* St,
539 bool isSink) {
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000540
541 // Get the block for the default case.
542 assert (Src->succ_rbegin() != Src->succ_rend());
543 CFGBlock* DefaultBlock = *Src->succ_rbegin();
544
545 bool IsNew;
546
Ted Kremenek0ecb53a2008-09-16 18:44:52 +0000547 ExplodedNodeImpl* Succ = Eng.G->getNodeImpl(BlockEdge(Src, DefaultBlock),
548 St, &IsNew);
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000549 Succ->addPredecessor(Pred);
550
551 if (IsNew) {
552 if (isSink)
553 Succ->markAsSink();
554 else
555 Eng.WList->Enqueue(Succ);
556
557 return Succ;
558 }
559
560 return NULL;
561}
Ted Kremenek811c2b42008-04-11 22:03:04 +0000562
563GREndPathNodeBuilderImpl::~GREndPathNodeBuilderImpl() {
564 // Auto-generate an EOP node if one has not been generated.
565 if (!HasGeneratedNode) generateNodeImpl(Pred->State);
566}
567
Ted Kremenekc218c842009-05-08 23:08:34 +0000568ExplodedNodeImpl*
569GREndPathNodeBuilderImpl::generateNodeImpl(const void* State,
570 const void *tag,
571 ExplodedNodeImpl* P) {
572 HasGeneratedNode = true;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000573 bool IsNew;
574
575 ExplodedNodeImpl* Node =
Ted Kremenekc218c842009-05-08 23:08:34 +0000576 Eng.G->getNodeImpl(BlockEntrance(&B, tag), State, &IsNew);
Ted Kremenek811c2b42008-04-11 22:03:04 +0000577
Ted Kremenekc218c842009-05-08 23:08:34 +0000578 Node->addPredecessor(P ? P : Pred);
Ted Kremenek811c2b42008-04-11 22:03:04 +0000579
580 if (IsNew) {
Ted Kremenek811c2b42008-04-11 22:03:04 +0000581 Eng.G->addEndOfPath(Node);
Ted Kremenekd004c412008-04-18 16:30:14 +0000582 return Node;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000583 }
584
Ted Kremenekd004c412008-04-18 16:30:14 +0000585 return NULL;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000586}