blob: e4f27b60cf2bec9be1a221a6565a2702b87e33b5 [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 {
32 class VISIBILITY_HIDDEN DFS : public GRWorkList {
33 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};
50} // end anonymous namespace
51
Ted Kremenek2e12c2e2008-01-16 18:18:48 +000052// Place the dstor for GRWorkList here because it contains virtual member
53// functions, and we the code for the dstor generated in one compilation unit.
54GRWorkList::~GRWorkList() {}
55
Ted Kremenek3e743662008-01-14 23:24:37 +000056GRWorkList* GRWorkList::MakeDFS() { return new DFS(); }
57
Ted Kremenekd9de9f12008-12-16 22:13:33 +000058namespace {
59 class VISIBILITY_HIDDEN BFSBlockDFSContents : public GRWorkList {
60 std::queue<GRWorkListUnit> Queue;
61 llvm::SmallVector<GRWorkListUnit,20> Stack;
62 public:
63 virtual bool hasWork() const {
64 return !Queue.empty() || !Stack.empty();
65 }
66
67 virtual void Enqueue(const GRWorkListUnit& U) {
68 if (isa<BlockEntrance>(U.getNode()->getLocation()))
69 Queue.push(U);
70 else
71 Stack.push_back(U);
72 }
73
74 virtual GRWorkListUnit Dequeue() {
75 // Process all basic blocks to completion.
76 if (!Stack.empty()) {
77 const GRWorkListUnit& U = Stack.back();
78 Stack.pop_back(); // This technically "invalidates" U, but we are fine.
79 return U;
80 }
81
82 assert(!Queue.empty());
83 // Don't use const reference. The subsequent pop_back() might make it
84 // unsafe.
85 GRWorkListUnit U = Queue.front();
86 Queue.pop();
87 return U;
88 }
89 };
90} // end anonymous namespace
91
92GRWorkList* GRWorkList::MakeBFSBlockDFSContents() {
93 return new BFSBlockDFSContents();
94}
95
96//===----------------------------------------------------------------------===//
97// Core analysis engine.
98//===----------------------------------------------------------------------===//
99
Ted Kremenek3e743662008-01-14 23:24:37 +0000100/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
Ted Kremenekf6c62f32008-02-13 17:41:41 +0000101bool GRCoreEngineImpl::ExecuteWorkList(unsigned Steps) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000102
103 if (G->num_roots() == 0) { // Initialize the analysis by constructing
104 // the root if none exists.
105
Ted Kremenek997d8722008-01-29 00:33:40 +0000106 CFGBlock* Entry = &getCFG().getEntry();
Ted Kremenek3e743662008-01-14 23:24:37 +0000107
108 assert (Entry->empty() &&
109 "Entry block must be empty.");
110
111 assert (Entry->succ_size() == 1 &&
112 "Entry block must have 1 successor.");
113
114 // Get the solitary successor.
115 CFGBlock* Succ = *(Entry->succ_begin());
116
117 // Construct an edge representing the
118 // starting location in the function.
Ted Kremenek0ecb53a2008-09-16 18:44:52 +0000119 BlockEdge StartLoc(Entry, Succ);
Ted Kremenek3e743662008-01-14 23:24:37 +0000120
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000121 // Set the current block counter to being empty.
122 WList->setBlockCounter(BCounterFactory.GetEmptyCounter());
123
Ted Kremenek3e743662008-01-14 23:24:37 +0000124 // Generate the root.
Ted Kremenekaf665822008-08-26 22:34:23 +0000125 GenerateNode(StartLoc, getInitialState(), 0);
Ted Kremenek3e743662008-01-14 23:24:37 +0000126 }
127
128 while (Steps && WList->hasWork()) {
129 --Steps;
130 const GRWorkListUnit& WU = WList->Dequeue();
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000131
132 // Set the current block counter.
133 WList->setBlockCounter(WU.getBlockCounter());
134
135 // Retrieve the node.
Ted Kremenek3e743662008-01-14 23:24:37 +0000136 ExplodedNodeImpl* Node = WU.getNode();
137
138 // Dispatch on the location type.
139 switch (Node->getLocation().getKind()) {
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000140 case ProgramPoint::BlockEdgeKind:
Ted Kremenek3e743662008-01-14 23:24:37 +0000141 HandleBlockEdge(cast<BlockEdge>(Node->getLocation()), Node);
142 break;
143
144 case ProgramPoint::BlockEntranceKind:
145 HandleBlockEntrance(cast<BlockEntrance>(Node->getLocation()), Node);
146 break;
147
148 case ProgramPoint::BlockExitKind:
Ted Kremeneke5843592008-01-15 00:24:08 +0000149 assert (false && "BlockExit location never occur in forward analysis.");
Ted Kremenek3e743662008-01-14 23:24:37 +0000150 break;
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000151
152 default:
153 assert(isa<PostStmt>(Node->getLocation()));
Ted Kremenek3e743662008-01-14 23:24:37 +0000154 HandlePostStmt(cast<PostStmt>(Node->getLocation()), WU.getBlock(),
155 WU.getIndex(), Node);
156 break;
157 }
158 }
159
160 return WList->hasWork();
161}
162
Ted Kremenekdf4a5b92008-03-05 19:08:15 +0000163void GRCoreEngineImpl::HandleBlockEdge(const BlockEdge& L,
164 ExplodedNodeImpl* Pred) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000165
166 CFGBlock* Blk = L.getDst();
167
168 // Check if we are entering the EXIT block.
Ted Kremenek997d8722008-01-29 00:33:40 +0000169 if (Blk == &getCFG().getExit()) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000170
Ted Kremenek997d8722008-01-29 00:33:40 +0000171 assert (getCFG().getExit().size() == 0
172 && "EXIT block cannot contain Stmts.");
Ted Kremenek3e743662008-01-14 23:24:37 +0000173
Ted Kremenek811c2b42008-04-11 22:03:04 +0000174 // Process the final state transition.
175 GREndPathNodeBuilderImpl Builder(Blk, Pred, this);
176 ProcessEndPath(Builder);
Ted Kremenek3e743662008-01-14 23:24:37 +0000177
Ted Kremenek3e743662008-01-14 23:24:37 +0000178 // This path is done. Don't enqueue any more nodes.
179 return;
180 }
Ted Kremenek17f4dbd2008-02-29 20:27:50 +0000181
182 // FIXME: Should we allow ProcessBlockEntrance to also manipulate state?
Ted Kremenek3e743662008-01-14 23:24:37 +0000183
Ted Kremenek17f4dbd2008-02-29 20:27:50 +0000184 if (ProcessBlockEntrance(Blk, Pred->State, WList->getBlockCounter()))
185 GenerateNode(BlockEntrance(Blk), Pred->State, Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000186}
187
Ted Kremenekf6c62f32008-02-13 17:41:41 +0000188void GRCoreEngineImpl::HandleBlockEntrance(const BlockEntrance& L,
Ted Kremenekdf4a5b92008-03-05 19:08:15 +0000189 ExplodedNodeImpl* Pred) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000190
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000191 // Increment the block counter.
192 GRBlockCounter Counter = WList->getBlockCounter();
193 Counter = BCounterFactory.IncrementCount(Counter, L.getBlock()->getBlockID());
194 WList->setBlockCounter(Counter);
195
196 // Process the entrance of the block.
Ted Kremenek3e743662008-01-14 23:24:37 +0000197 if (Stmt* S = L.getFirstStmt()) {
Ted Kremenekb2cad312008-01-29 22:11:49 +0000198 GRStmtNodeBuilderImpl Builder(L.getBlock(), 0, Pred, this);
Ted Kremenek3e743662008-01-14 23:24:37 +0000199 ProcessStmt(S, Builder);
200 }
Ted Kremeneke5843592008-01-15 00:24:08 +0000201 else
202 HandleBlockExit(L.getBlock(), Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000203}
204
Ted Kremenek3f91f032008-08-13 03:10:52 +0000205GRCoreEngineImpl::~GRCoreEngineImpl() {
206 delete WList;
207}
Ted Kremenek3e743662008-01-14 23:24:37 +0000208
Ted Kremenekf6c62f32008-02-13 17:41:41 +0000209void GRCoreEngineImpl::HandleBlockExit(CFGBlock * B, ExplodedNodeImpl* Pred) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000210
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000211 if (Stmt* Term = B->getTerminator()) {
212 switch (Term->getStmtClass()) {
213 default:
214 assert(false && "Analysis for this terminator not implemented.");
215 break;
Ted Kremenek822f7372008-02-12 21:51:20 +0000216
217 case Stmt::BinaryOperatorClass: // '&&' and '||'
218 HandleBranch(cast<BinaryOperator>(Term)->getLHS(), Term, B, Pred);
219 return;
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000220
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000221 case Stmt::ConditionalOperatorClass:
222 HandleBranch(cast<ConditionalOperator>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000223 return;
224
225 // FIXME: Use constant-folding in CFG construction to simplify this
226 // case.
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000227
228 case Stmt::ChooseExprClass:
229 HandleBranch(cast<ChooseExpr>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000230 return;
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000231
Ted Kremenek822f7372008-02-12 21:51:20 +0000232 case Stmt::DoStmtClass:
233 HandleBranch(cast<DoStmt>(Term)->getCond(), Term, B, Pred);
234 return;
235
236 case Stmt::ForStmtClass:
237 HandleBranch(cast<ForStmt>(Term)->getCond(), Term, B, Pred);
238 return;
Ted Kremenek632bcb82008-02-13 16:56:51 +0000239
240 case Stmt::ContinueStmtClass:
241 case Stmt::BreakStmtClass:
242 case Stmt::GotoStmtClass:
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000243 break;
244
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000245 case Stmt::IfStmtClass:
246 HandleBranch(cast<IfStmt>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000247 return;
Ted Kremenek7022efb2008-02-13 00:24:44 +0000248
249 case Stmt::IndirectGotoStmtClass: {
250 // Only 1 successor: the indirect goto dispatch block.
251 assert (B->succ_size() == 1);
252
253 GRIndirectGotoNodeBuilderImpl
254 builder(Pred, B, cast<IndirectGotoStmt>(Term)->getTarget(),
255 *(B->succ_begin()), this);
256
257 ProcessIndirectGoto(builder);
258 return;
259 }
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000260
Ted Kremenek17810802008-11-12 19:24:17 +0000261 case Stmt::ObjCForCollectionStmtClass: {
262 // In the case of ObjCForCollectionStmt, it appears twice in a CFG:
263 //
264 // (1) inside a basic block, which represents the binding of the
265 // 'element' variable to a value.
266 // (2) in a terminator, which represents the branch.
267 //
268 // For (1), subengines will bind a value (i.e., 0 or 1) indicating
269 // whether or not collection contains any more elements. We cannot
270 // just test to see if the element is nil because a container can
271 // contain nil elements.
272 HandleBranch(Term, Term, B, Pred);
273 return;
274 }
275
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000276 case Stmt::SwitchStmtClass: {
277 GRSwitchNodeBuilderImpl builder(Pred, B,
278 cast<SwitchStmt>(Term)->getCond(),
279 this);
280
281 ProcessSwitch(builder);
282 return;
283 }
284
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000285 case Stmt::WhileStmtClass:
286 HandleBranch(cast<WhileStmt>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000287 return;
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000288 }
289 }
Ted Kremenek822f7372008-02-12 21:51:20 +0000290
291 assert (B->succ_size() == 1 &&
292 "Blocks with no terminator should have at most 1 successor.");
Ted Kremenek3e743662008-01-14 23:24:37 +0000293
Ted Kremenek0ecb53a2008-09-16 18:44:52 +0000294 GenerateNode(BlockEdge(B, *(B->succ_begin())), Pred->State, Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000295}
296
Ted Kremenek17810802008-11-12 19:24:17 +0000297void GRCoreEngineImpl::HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock * B,
298 ExplodedNodeImpl* Pred) {
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000299 assert (B->succ_size() == 2);
300
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000301 GRBranchNodeBuilderImpl Builder(B, *(B->succ_begin()), *(B->succ_begin()+1),
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000302 Pred, this);
303
304 ProcessBranch(Cond, Term, Builder);
305}
306
Ted Kremenekf6c62f32008-02-13 17:41:41 +0000307void GRCoreEngineImpl::HandlePostStmt(const PostStmt& L, CFGBlock* B,
Ted Kremenek3e743662008-01-14 23:24:37 +0000308 unsigned StmtIdx, ExplodedNodeImpl* Pred) {
309
310 assert (!B->empty());
311
Ted Kremeneke5843592008-01-15 00:24:08 +0000312 if (StmtIdx == B->size())
313 HandleBlockExit(B, Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000314 else {
Ted Kremenekb2cad312008-01-29 22:11:49 +0000315 GRStmtNodeBuilderImpl Builder(B, StmtIdx, Pred, this);
Ted Kremeneke914bb82008-01-16 22:13:19 +0000316 ProcessStmt((*B)[StmtIdx], Builder);
Ted Kremenek3e743662008-01-14 23:24:37 +0000317 }
318}
319
Ted Kremenek3e743662008-01-14 23:24:37 +0000320/// GenerateNode - Utility method to generate nodes, hook up successors,
321/// and add nodes to the worklist.
Ted Kremeneka7b8ffb2008-07-10 22:03:41 +0000322void GRCoreEngineImpl::GenerateNode(const ProgramPoint& Loc, const void* State,
323 ExplodedNodeImpl* Pred) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000324
325 bool IsNew;
326 ExplodedNodeImpl* Node = G->getNodeImpl(Loc, State, &IsNew);
327
328 if (Pred)
329 Node->addPredecessor(Pred); // Link 'Node' with its predecessor.
330 else {
331 assert (IsNew);
332 G->addRoot(Node); // 'Node' has no predecessor. Make it a root.
333 }
334
335 // Only add 'Node' to the worklist if it was freshly generated.
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000336 if (IsNew) WList->Enqueue(Node);
Ted Kremenek3e743662008-01-14 23:24:37 +0000337}
338
Ted Kremenekb2cad312008-01-29 22:11:49 +0000339GRStmtNodeBuilderImpl::GRStmtNodeBuilderImpl(CFGBlock* b, unsigned idx,
Ted Kremenekf6c62f32008-02-13 17:41:41 +0000340 ExplodedNodeImpl* N, GRCoreEngineImpl* e)
Ted Kremenekc072b822008-04-18 20:35:30 +0000341 : Eng(*e), B(*b), Idx(idx), Pred(N), LastNode(N) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000342 Deferred.insert(N);
343}
344
Ted Kremenekb2cad312008-01-29 22:11:49 +0000345GRStmtNodeBuilderImpl::~GRStmtNodeBuilderImpl() {
Ted Kremenek3e743662008-01-14 23:24:37 +0000346 for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
Ted Kremeneka50d9852008-01-30 23:03:39 +0000347 if (!(*I)->isSink())
Ted Kremenek3e743662008-01-14 23:24:37 +0000348 GenerateAutoTransition(*I);
349}
350
Ted Kremenekb2cad312008-01-29 22:11:49 +0000351void GRStmtNodeBuilderImpl::GenerateAutoTransition(ExplodedNodeImpl* N) {
Ted Kremeneka50d9852008-01-30 23:03:39 +0000352 assert (!N->isSink());
Ted Kremenek3e743662008-01-14 23:24:37 +0000353
354 PostStmt Loc(getStmt());
355
356 if (Loc == N->getLocation()) {
357 // Note: 'N' should be a fresh node because otherwise it shouldn't be
358 // a member of Deferred.
359 Eng.WList->Enqueue(N, B, Idx+1);
360 return;
361 }
362
363 bool IsNew;
364 ExplodedNodeImpl* Succ = Eng.G->getNodeImpl(Loc, N->State, &IsNew);
365 Succ->addPredecessor(N);
366
367 if (IsNew)
368 Eng.WList->Enqueue(Succ, B, Idx+1);
369}
370
Ted Kremenekdf240002009-04-11 00:11:10 +0000371static inline PostStmt GetPostLoc(Stmt* S, ProgramPoint::Kind K,
372 const void *tag) {
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000373 switch (K) {
374 default:
375 assert(false && "Invalid PostXXXKind.");
376
377 case ProgramPoint::PostStmtKind:
Ted Kremenekdf240002009-04-11 00:11:10 +0000378 return PostStmt(S, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000379
380 case ProgramPoint::PostLoadKind:
Ted Kremenekdf240002009-04-11 00:11:10 +0000381 return PostLoad(S, tag);
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000382
383 case ProgramPoint::PostUndefLocationCheckFailedKind:
Ted Kremenekdf240002009-04-11 00:11:10 +0000384 return PostUndefLocationCheckFailed(S, tag);
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000385
386 case ProgramPoint::PostLocationChecksSucceedKind:
Ted Kremenekdf240002009-04-11 00:11:10 +0000387 return PostLocationChecksSucceed(S, tag);
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000388
389 case ProgramPoint::PostOutOfBoundsCheckFailedKind:
Ted Kremenekdf240002009-04-11 00:11:10 +0000390 return PostOutOfBoundsCheckFailed(S, tag);
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000391
392 case ProgramPoint::PostNullCheckFailedKind:
Ted Kremenekdf240002009-04-11 00:11:10 +0000393 return PostNullCheckFailed(S, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000394
Ted Kremeneka1966182008-10-17 20:49:23 +0000395 case ProgramPoint::PostStoreKind:
Ted Kremenekdf240002009-04-11 00:11:10 +0000396 return PostStore(S, tag);
Ted Kremeneka1966182008-10-17 20:49:23 +0000397
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000398 case ProgramPoint::PostPurgeDeadSymbolsKind:
Ted Kremenekdf240002009-04-11 00:11:10 +0000399 return PostPurgeDeadSymbols(S, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000400 }
401}
402
Ted Kremenekfa5a3d02008-04-29 21:04:26 +0000403ExplodedNodeImpl*
Ted Kremeneka7b8ffb2008-07-10 22:03:41 +0000404GRStmtNodeBuilderImpl::generateNodeImpl(Stmt* S, const void* State,
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000405 ExplodedNodeImpl* Pred,
Ted Kremenekdf240002009-04-11 00:11:10 +0000406 ProgramPoint::Kind K,
407 const void *tag) {
408 return generateNodeImpl(GetPostLoc(S, K, tag), State, Pred);
Ted Kremenek513f0b12009-02-19 23:45:28 +0000409}
410
411ExplodedNodeImpl*
412GRStmtNodeBuilderImpl::generateNodeImpl(PostStmt Loc, const void* State,
Ted Kremenekdf240002009-04-11 00:11:10 +0000413 ExplodedNodeImpl* Pred) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000414 bool IsNew;
Ted Kremenekfa5a3d02008-04-29 21:04:26 +0000415 ExplodedNodeImpl* N = Eng.G->getNodeImpl(Loc, State, &IsNew);
Ted Kremenek3e743662008-01-14 23:24:37 +0000416 N->addPredecessor(Pred);
417 Deferred.erase(Pred);
418
Ted Kremenek3e743662008-01-14 23:24:37 +0000419 if (IsNew) {
420 Deferred.insert(N);
421 LastNode = N;
422 return N;
423 }
424
425 LastNode = NULL;
426 return NULL;
427}
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000428
Ted Kremeneka7b8ffb2008-07-10 22:03:41 +0000429ExplodedNodeImpl* GRBranchNodeBuilderImpl::generateNodeImpl(const void* State,
Ted Kremeneka50d9852008-01-30 23:03:39 +0000430 bool branch) {
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000431 bool IsNew;
432
433 ExplodedNodeImpl* Succ =
Ted Kremenek0ecb53a2008-09-16 18:44:52 +0000434 Eng.G->getNodeImpl(BlockEdge(Src, branch ? DstT : DstF), State, &IsNew);
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000435
436 Succ->addPredecessor(Pred);
437
Ted Kremenek7ff18932008-01-29 23:32:35 +0000438 if (branch) GeneratedTrue = true;
439 else GeneratedFalse = true;
440
Ted Kremeneka50d9852008-01-30 23:03:39 +0000441 if (IsNew) {
Ted Kremenek2531fce2008-01-30 23:24:39 +0000442 Deferred.push_back(Succ);
Ted Kremeneka50d9852008-01-30 23:03:39 +0000443 return Succ;
444 }
445
446 return NULL;
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000447}
Ted Kremenek7ff18932008-01-29 23:32:35 +0000448
449GRBranchNodeBuilderImpl::~GRBranchNodeBuilderImpl() {
450 if (!GeneratedTrue) generateNodeImpl(Pred->State, true);
451 if (!GeneratedFalse) generateNodeImpl(Pred->State, false);
Ted Kremenek2531fce2008-01-30 23:24:39 +0000452
453 for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000454 if (!(*I)->isSink()) Eng.WList->Enqueue(*I);
Ted Kremenek7ff18932008-01-29 23:32:35 +0000455}
Ted Kremenek7022efb2008-02-13 00:24:44 +0000456
Ted Kremenek7022efb2008-02-13 00:24:44 +0000457
458ExplodedNodeImpl*
Ted Kremenek2bba9012008-02-13 17:27:37 +0000459GRIndirectGotoNodeBuilderImpl::generateNodeImpl(const Iterator& I,
Ted Kremeneka7b8ffb2008-07-10 22:03:41 +0000460 const void* St,
Ted Kremenek7022efb2008-02-13 00:24:44 +0000461 bool isSink) {
462 bool IsNew;
463
464 ExplodedNodeImpl* Succ =
Ted Kremenek0ecb53a2008-09-16 18:44:52 +0000465 Eng.G->getNodeImpl(BlockEdge(Src, I.getBlock()), St, &IsNew);
Ted Kremenek7022efb2008-02-13 00:24:44 +0000466
467 Succ->addPredecessor(Pred);
468
469 if (IsNew) {
470
471 if (isSink)
472 Succ->markAsSink();
473 else
474 Eng.WList->Enqueue(Succ);
475
476 return Succ;
477 }
478
479 return NULL;
480}
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000481
482
483ExplodedNodeImpl*
Ted Kremeneka7b8ffb2008-07-10 22:03:41 +0000484GRSwitchNodeBuilderImpl::generateCaseStmtNodeImpl(const Iterator& I,
485 const void* St) {
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000486
487 bool IsNew;
488
Ted Kremenek0ecb53a2008-09-16 18:44:52 +0000489 ExplodedNodeImpl* Succ = Eng.G->getNodeImpl(BlockEdge(Src, I.getBlock()),
490 St, &IsNew);
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000491 Succ->addPredecessor(Pred);
492
493 if (IsNew) {
494 Eng.WList->Enqueue(Succ);
495 return Succ;
496 }
497
498 return NULL;
499}
500
501
502ExplodedNodeImpl*
Ted Kremeneka7b8ffb2008-07-10 22:03:41 +0000503GRSwitchNodeBuilderImpl::generateDefaultCaseNodeImpl(const void* St,
504 bool isSink) {
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000505
506 // Get the block for the default case.
507 assert (Src->succ_rbegin() != Src->succ_rend());
508 CFGBlock* DefaultBlock = *Src->succ_rbegin();
509
510 bool IsNew;
511
Ted Kremenek0ecb53a2008-09-16 18:44:52 +0000512 ExplodedNodeImpl* Succ = Eng.G->getNodeImpl(BlockEdge(Src, DefaultBlock),
513 St, &IsNew);
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000514 Succ->addPredecessor(Pred);
515
516 if (IsNew) {
517 if (isSink)
518 Succ->markAsSink();
519 else
520 Eng.WList->Enqueue(Succ);
521
522 return Succ;
523 }
524
525 return NULL;
526}
Ted Kremenek811c2b42008-04-11 22:03:04 +0000527
528GREndPathNodeBuilderImpl::~GREndPathNodeBuilderImpl() {
529 // Auto-generate an EOP node if one has not been generated.
530 if (!HasGeneratedNode) generateNodeImpl(Pred->State);
531}
532
Ted Kremeneka7b8ffb2008-07-10 22:03:41 +0000533ExplodedNodeImpl* GREndPathNodeBuilderImpl::generateNodeImpl(const void* State){
Ted Kremenek811c2b42008-04-11 22:03:04 +0000534 HasGeneratedNode = true;
535
536 bool IsNew;
537
538 ExplodedNodeImpl* Node =
Ted Kremenek86051692008-04-16 22:30:40 +0000539 Eng.G->getNodeImpl(BlockEntrance(&B), State, &IsNew);
Ted Kremenek811c2b42008-04-11 22:03:04 +0000540
541
542 Node->addPredecessor(Pred);
543
544 if (IsNew) {
545 Node->markAsSink();
546 Eng.G->addEndOfPath(Node);
Ted Kremenekd004c412008-04-18 16:30:14 +0000547 return Node;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000548 }
549
Ted Kremenekd004c412008-04-18 16:30:14 +0000550 return NULL;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000551}