blob: 5641baac5fc990539712bcc9450fd360f96541bd [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) {
433 return generateNodeImpl(GetPostLoc(S, K, tag), State, Pred);
Ted Kremenek513f0b12009-02-19 23:45:28 +0000434}
435
436ExplodedNodeImpl*
437GRStmtNodeBuilderImpl::generateNodeImpl(PostStmt Loc, const void* State,
Ted Kremenekdf240002009-04-11 00:11:10 +0000438 ExplodedNodeImpl* Pred) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000439 bool IsNew;
Ted Kremenekfa5a3d02008-04-29 21:04:26 +0000440 ExplodedNodeImpl* N = Eng.G->getNodeImpl(Loc, State, &IsNew);
Ted Kremenek3e743662008-01-14 23:24:37 +0000441 N->addPredecessor(Pred);
442 Deferred.erase(Pred);
443
Ted Kremenek3e743662008-01-14 23:24:37 +0000444 if (IsNew) {
445 Deferred.insert(N);
446 LastNode = N;
447 return N;
448 }
449
450 LastNode = NULL;
451 return NULL;
452}
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000453
Ted Kremeneka7b8ffb2008-07-10 22:03:41 +0000454ExplodedNodeImpl* GRBranchNodeBuilderImpl::generateNodeImpl(const void* State,
Ted Kremenekaf9f3622009-07-20 18:44:36 +0000455 bool branch) {
456
457 // If the branch has been marked infeasible we should not generate a node.
458 if (!isFeasible(branch))
459 return NULL;
460
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000461 bool IsNew;
462
463 ExplodedNodeImpl* Succ =
Ted Kremenek0ecb53a2008-09-16 18:44:52 +0000464 Eng.G->getNodeImpl(BlockEdge(Src, branch ? DstT : DstF), State, &IsNew);
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000465
466 Succ->addPredecessor(Pred);
467
Ted Kremenekaf9f3622009-07-20 18:44:36 +0000468 if (branch)
469 GeneratedTrue = true;
470 else
471 GeneratedFalse = true;
Ted Kremenek7ff18932008-01-29 23:32:35 +0000472
Ted Kremeneka50d9852008-01-30 23:03:39 +0000473 if (IsNew) {
Ted Kremenek2531fce2008-01-30 23:24:39 +0000474 Deferred.push_back(Succ);
Ted Kremeneka50d9852008-01-30 23:03:39 +0000475 return Succ;
476 }
477
478 return NULL;
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000479}
Ted Kremenek7ff18932008-01-29 23:32:35 +0000480
481GRBranchNodeBuilderImpl::~GRBranchNodeBuilderImpl() {
482 if (!GeneratedTrue) generateNodeImpl(Pred->State, true);
483 if (!GeneratedFalse) generateNodeImpl(Pred->State, false);
Ted Kremenek2531fce2008-01-30 23:24:39 +0000484
485 for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000486 if (!(*I)->isSink()) Eng.WList->Enqueue(*I);
Ted Kremenek7ff18932008-01-29 23:32:35 +0000487}
Ted Kremenek7022efb2008-02-13 00:24:44 +0000488
Ted Kremenek7022efb2008-02-13 00:24:44 +0000489
490ExplodedNodeImpl*
Ted Kremenek2bba9012008-02-13 17:27:37 +0000491GRIndirectGotoNodeBuilderImpl::generateNodeImpl(const Iterator& I,
Ted Kremeneka7b8ffb2008-07-10 22:03:41 +0000492 const void* St,
Ted Kremenek7022efb2008-02-13 00:24:44 +0000493 bool isSink) {
494 bool IsNew;
495
496 ExplodedNodeImpl* Succ =
Ted Kremenek0ecb53a2008-09-16 18:44:52 +0000497 Eng.G->getNodeImpl(BlockEdge(Src, I.getBlock()), St, &IsNew);
Ted Kremenek7022efb2008-02-13 00:24:44 +0000498
499 Succ->addPredecessor(Pred);
500
501 if (IsNew) {
502
503 if (isSink)
504 Succ->markAsSink();
505 else
506 Eng.WList->Enqueue(Succ);
507
508 return Succ;
509 }
510
511 return NULL;
512}
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000513
514
515ExplodedNodeImpl*
Ted Kremeneka7b8ffb2008-07-10 22:03:41 +0000516GRSwitchNodeBuilderImpl::generateCaseStmtNodeImpl(const Iterator& I,
517 const void* St) {
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000518
519 bool IsNew;
520
Ted Kremenek0ecb53a2008-09-16 18:44:52 +0000521 ExplodedNodeImpl* Succ = Eng.G->getNodeImpl(BlockEdge(Src, I.getBlock()),
522 St, &IsNew);
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000523 Succ->addPredecessor(Pred);
524
525 if (IsNew) {
526 Eng.WList->Enqueue(Succ);
527 return Succ;
528 }
529
530 return NULL;
531}
532
533
534ExplodedNodeImpl*
Ted Kremeneka7b8ffb2008-07-10 22:03:41 +0000535GRSwitchNodeBuilderImpl::generateDefaultCaseNodeImpl(const void* St,
536 bool isSink) {
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000537
538 // Get the block for the default case.
539 assert (Src->succ_rbegin() != Src->succ_rend());
540 CFGBlock* DefaultBlock = *Src->succ_rbegin();
541
542 bool IsNew;
543
Ted Kremenek0ecb53a2008-09-16 18:44:52 +0000544 ExplodedNodeImpl* Succ = Eng.G->getNodeImpl(BlockEdge(Src, DefaultBlock),
545 St, &IsNew);
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000546 Succ->addPredecessor(Pred);
547
548 if (IsNew) {
549 if (isSink)
550 Succ->markAsSink();
551 else
552 Eng.WList->Enqueue(Succ);
553
554 return Succ;
555 }
556
557 return NULL;
558}
Ted Kremenek811c2b42008-04-11 22:03:04 +0000559
560GREndPathNodeBuilderImpl::~GREndPathNodeBuilderImpl() {
561 // Auto-generate an EOP node if one has not been generated.
562 if (!HasGeneratedNode) generateNodeImpl(Pred->State);
563}
564
Ted Kremenekc218c842009-05-08 23:08:34 +0000565ExplodedNodeImpl*
566GREndPathNodeBuilderImpl::generateNodeImpl(const void* State,
567 const void *tag,
568 ExplodedNodeImpl* P) {
569 HasGeneratedNode = true;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000570 bool IsNew;
571
572 ExplodedNodeImpl* Node =
Ted Kremenekc218c842009-05-08 23:08:34 +0000573 Eng.G->getNodeImpl(BlockEntrance(&B, tag), State, &IsNew);
Ted Kremenek811c2b42008-04-11 22:03:04 +0000574
Ted Kremenekc218c842009-05-08 23:08:34 +0000575 Node->addPredecessor(P ? P : Pred);
Ted Kremenek811c2b42008-04-11 22:03:04 +0000576
577 if (IsNew) {
Ted Kremenek811c2b42008-04-11 22:03:04 +0000578 Eng.G->addEndOfPath(Node);
Ted Kremenekd004c412008-04-18 16:30:14 +0000579 return Node;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000580 }
581
Ted Kremenekd004c412008-04-18 16:30:14 +0000582 return NULL;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000583}