blob: d54b0777eda75f9a56542f10e21af37d445d3845 [file] [log] [blame]
Ted Kremenek17810802008-11-12 19:24:17 +00001//==- GRCoreEngine.cpp - Path-Sensitive Dataflow Engine ------------*- C++ -*-//
Mike Stump11289f42009-09-09 15:08:12 +00002//
Ted Kremenek3e743662008-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 Kremenekd6b87082010-01-25 04:41:41 +000015#include "clang/Checker/PathSensitive/GRCoreEngine.h"
16#include "clang/Checker/PathSensitive/GRExprEngine.h"
Ted Kremenek3e743662008-01-14 23:24:37 +000017#include "clang/AST/Expr.h"
Ted Kremenek3e743662008-01-14 23:24:37 +000018#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 {
Kovarththanan Rajaratnam65c65662009-11-28 06:07:30 +000032class 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};
Mike Stump11289f42009-09-09 15:08:12 +000050
Kovarththanan Rajaratnam65c65662009-11-28 06:07:30 +000051class BFS : public GRWorkList {
Ted Kremenek2c327732009-05-01 22:18:46 +000052 std::queue<GRWorkListUnit> Queue;
53public:
54 virtual bool hasWork() const {
55 return !Queue.empty();
56 }
Mike Stump11289f42009-09-09 15:08:12 +000057
Ted Kremenek2c327732009-05-01 22:18:46 +000058 virtual void Enqueue(const GRWorkListUnit& U) {
59 Queue.push(U);
60 }
Mike Stump11289f42009-09-09 15:08:12 +000061
Ted Kremenek2c327732009-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 Stump11289f42009-09-09 15:08:12 +000065 GRWorkListUnit U = Queue.front();
Ted Kremenek2c327732009-05-01 22:18:46 +000066 Queue.pop();
67 return U;
68 }
69};
Mike Stump11289f42009-09-09 15:08:12 +000070
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 {
Kovarththanan Rajaratnam65c65662009-11-28 06:07:30 +000081 class BFSBlockDFSContents : public GRWorkList {
Ted Kremenekd9de9f12008-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 Stump11289f42009-09-09 15:08:12 +000088
Ted Kremenekd9de9f12008-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 Stump11289f42009-09-09 15:08:12 +000095
Ted Kremenekd9de9f12008-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 Stump11289f42009-09-09 15:08:12 +0000103
Ted Kremenekd9de9f12008-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 Stump11289f42009-09-09 15:08:12 +0000107 GRWorkListUnit U = Queue.front();
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000108 Queue.pop();
Mike Stump11289f42009-09-09 15:08:12 +0000109 return U;
Ted Kremenekd9de9f12008-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 Xu107f7592009-08-06 12:48:26 +0000121void GRCoreEngine::ProcessEndPath(GREndPathNodeBuilder& Builder) {
Zhongxing Xu82003da2009-08-06 10:00:15 +0000122 SubEngine.ProcessEndPath(Builder);
123}
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000124
Ted Kremenek4cad5fc2009-12-16 03:18:58 +0000125void GRCoreEngine::ProcessStmt(CFGElement E, GRStmtNodeBuilder& Builder) {
126 SubEngine.ProcessStmt(E, Builder);
Zhongxing Xu82003da2009-08-06 10:00:15 +0000127}
128
129bool GRCoreEngine::ProcessBlockEntrance(CFGBlock* Blk, const GRState* State,
Mike Stump11289f42009-09-09 15:08:12 +0000130 GRBlockCounter BC) {
Zhongxing Xu82003da2009-08-06 10:00:15 +0000131 return SubEngine.ProcessBlockEntrance(Blk, State, BC);
132}
133
134void GRCoreEngine::ProcessBranch(Stmt* Condition, Stmt* Terminator,
Zhongxing Xu107f7592009-08-06 12:48:26 +0000135 GRBranchNodeBuilder& Builder) {
Mike Stump11289f42009-09-09 15:08:12 +0000136 SubEngine.ProcessBranch(Condition, Terminator, Builder);
Zhongxing Xu82003da2009-08-06 10:00:15 +0000137}
138
Zhongxing Xu107f7592009-08-06 12:48:26 +0000139void GRCoreEngine::ProcessIndirectGoto(GRIndirectGotoNodeBuilder& Builder) {
Zhongxing Xu82003da2009-08-06 10:00:15 +0000140 SubEngine.ProcessIndirectGoto(Builder);
141}
142
Zhongxing Xu107f7592009-08-06 12:48:26 +0000143void GRCoreEngine::ProcessSwitch(GRSwitchNodeBuilder& Builder) {
Zhongxing Xu82003da2009-08-06 10:00:15 +0000144 SubEngine.ProcessSwitch(Builder);
145}
Zhongxing Xu107f7592009-08-06 12:48:26 +0000146
Ted Kremenek3e743662008-01-14 23:24:37 +0000147/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
Zhongxing Xue1190f72009-08-15 03:17:38 +0000148bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps) {
Mike Stump11289f42009-09-09 15:08:12 +0000149
Ted Kremenek3e743662008-01-14 23:24:37 +0000150 if (G->num_roots() == 0) { // Initialize the analysis by constructing
151 // the root if none exists.
Mike Stump11289f42009-09-09 15:08:12 +0000152
Zhongxing Xu94ec6492009-08-25 03:33:41 +0000153 CFGBlock* Entry = &(L->getCFG()->getEntry());
Mike Stump11289f42009-09-09 15:08:12 +0000154
155 assert (Entry->empty() &&
Ted Kremenek3e743662008-01-14 23:24:37 +0000156 "Entry block must be empty.");
Mike Stump11289f42009-09-09 15:08:12 +0000157
Ted Kremenek3e743662008-01-14 23:24:37 +0000158 assert (Entry->succ_size() == 1 &&
159 "Entry block must have 1 successor.");
Mike Stump11289f42009-09-09 15:08:12 +0000160
Ted Kremenek3e743662008-01-14 23:24:37 +0000161 // Get the solitary successor.
Mike Stump11289f42009-09-09 15:08:12 +0000162 CFGBlock* Succ = *(Entry->succ_begin());
163
Ted Kremenek3e743662008-01-14 23:24:37 +0000164 // Construct an edge representing the
165 // starting location in the function.
Zhongxing Xue1190f72009-08-15 03:17:38 +0000166 BlockEdge StartLoc(Entry, Succ, L);
Mike Stump11289f42009-09-09 15:08:12 +0000167
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000168 // Set the current block counter to being empty.
169 WList->setBlockCounter(BCounterFactory.GetEmptyCounter());
Mike Stump11289f42009-09-09 15:08:12 +0000170
Ted Kremenek3e743662008-01-14 23:24:37 +0000171 // Generate the root.
Zhongxing Xu5f078cb2009-08-17 06:19:58 +0000172 GenerateNode(StartLoc, getInitialState(L), 0);
Ted Kremenek3e743662008-01-14 23:24:37 +0000173 }
Mike Stump11289f42009-09-09 15:08:12 +0000174
Ted Kremenek3e743662008-01-14 23:24:37 +0000175 while (Steps && WList->hasWork()) {
176 --Steps;
177 const GRWorkListUnit& WU = WList->Dequeue();
Mike Stump11289f42009-09-09 15:08:12 +0000178
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000179 // Set the current block counter.
180 WList->setBlockCounter(WU.getBlockCounter());
181
182 // Retrieve the node.
Zhongxing Xu20227f72009-08-06 01:32:16 +0000183 ExplodedNode* Node = WU.getNode();
Mike Stump11289f42009-09-09 15:08:12 +0000184
Ted Kremenek3e743662008-01-14 23:24:37 +0000185 // Dispatch on the location type.
186 switch (Node->getLocation().getKind()) {
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000187 case ProgramPoint::BlockEdgeKind:
Ted Kremenek3e743662008-01-14 23:24:37 +0000188 HandleBlockEdge(cast<BlockEdge>(Node->getLocation()), Node);
189 break;
Mike Stump11289f42009-09-09 15:08:12 +0000190
Ted Kremenek3e743662008-01-14 23:24:37 +0000191 case ProgramPoint::BlockEntranceKind:
192 HandleBlockEntrance(cast<BlockEntrance>(Node->getLocation()), Node);
193 break;
Mike Stump11289f42009-09-09 15:08:12 +0000194
Ted Kremenek3e743662008-01-14 23:24:37 +0000195 case ProgramPoint::BlockExitKind:
Ted Kremeneke5843592008-01-15 00:24:08 +0000196 assert (false && "BlockExit location never occur in forward analysis.");
Ted Kremenek3e743662008-01-14 23:24:37 +0000197 break;
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000198
199 default:
200 assert(isa<PostStmt>(Node->getLocation()));
Ted Kremenek3e743662008-01-14 23:24:37 +0000201 HandlePostStmt(cast<PostStmt>(Node->getLocation()), WU.getBlock(),
202 WU.getIndex(), Node);
Mike Stump11289f42009-09-09 15:08:12 +0000203 break;
Ted Kremenek3e743662008-01-14 23:24:37 +0000204 }
205 }
Mike Stump11289f42009-09-09 15:08:12 +0000206
Ted Kremenek3e743662008-01-14 23:24:37 +0000207 return WList->hasWork();
208}
209
Zhongxing Xu82003da2009-08-06 10:00:15 +0000210
211void GRCoreEngine::HandleBlockEdge(const BlockEdge& L, ExplodedNode* Pred) {
Mike Stump11289f42009-09-09 15:08:12 +0000212
Ted Kremenek3e743662008-01-14 23:24:37 +0000213 CFGBlock* Blk = L.getDst();
Mike Stump11289f42009-09-09 15:08:12 +0000214
215 // Check if we are entering the EXIT block.
Zhongxing Xud2ab38e2009-12-23 08:54:57 +0000216 if (Blk == &(L.getLocationContext()->getCFG()->getExit())) {
Mike Stump11289f42009-09-09 15:08:12 +0000217
Zhongxing Xud2ab38e2009-12-23 08:54:57 +0000218 assert (L.getLocationContext()->getCFG()->getExit().size() == 0
Ted Kremenek997d8722008-01-29 00:33:40 +0000219 && "EXIT block cannot contain Stmts.");
Ted Kremenek3e743662008-01-14 23:24:37 +0000220
Ted Kremenek811c2b42008-04-11 22:03:04 +0000221 // Process the final state transition.
Zhongxing Xu107f7592009-08-06 12:48:26 +0000222 GREndPathNodeBuilder Builder(Blk, Pred, this);
Ted Kremenek811c2b42008-04-11 22:03:04 +0000223 ProcessEndPath(Builder);
Ted Kremenek3e743662008-01-14 23:24:37 +0000224
Ted Kremenek3e743662008-01-14 23:24:37 +0000225 // This path is done. Don't enqueue any more nodes.
226 return;
227 }
Ted Kremenek17f4dbd2008-02-29 20:27:50 +0000228
229 // FIXME: Should we allow ProcessBlockEntrance to also manipulate state?
Mike Stump11289f42009-09-09 15:08:12 +0000230
Ted Kremenek17f4dbd2008-02-29 20:27:50 +0000231 if (ProcessBlockEntrance(Blk, Pred->State, WList->getBlockCounter()))
Zhongxing Xue1190f72009-08-15 03:17:38 +0000232 GenerateNode(BlockEntrance(Blk, Pred->getLocationContext()), Pred->State, Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000233}
234
Zhongxing Xu82003da2009-08-06 10:00:15 +0000235void GRCoreEngine::HandleBlockEntrance(const BlockEntrance& L,
Zhongxing Xu107f7592009-08-06 12:48:26 +0000236 ExplodedNode* Pred) {
Mike Stump11289f42009-09-09 15:08:12 +0000237
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000238 // Increment the block counter.
239 GRBlockCounter Counter = WList->getBlockCounter();
240 Counter = BCounterFactory.IncrementCount(Counter, L.getBlock()->getBlockID());
241 WList->setBlockCounter(Counter);
Mike Stump11289f42009-09-09 15:08:12 +0000242
243 // Process the entrance of the block.
Ted Kremenek4cad5fc2009-12-16 03:18:58 +0000244 if (CFGElement E = L.getFirstElement()) {
Mike Stump11289f42009-09-09 15:08:12 +0000245 GRStmtNodeBuilder Builder(L.getBlock(), 0, Pred, this,
Zhongxing Xu107f7592009-08-06 12:48:26 +0000246 SubEngine.getStateManager());
Ted Kremenek4cad5fc2009-12-16 03:18:58 +0000247 ProcessStmt(E, Builder);
Ted Kremenek3e743662008-01-14 23:24:37 +0000248 }
Mike Stump11289f42009-09-09 15:08:12 +0000249 else
Ted Kremeneke5843592008-01-15 00:24:08 +0000250 HandleBlockExit(L.getBlock(), Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000251}
252
Zhongxing Xu82003da2009-08-06 10:00:15 +0000253void GRCoreEngine::HandleBlockExit(CFGBlock * B, ExplodedNode* Pred) {
Mike Stump11289f42009-09-09 15:08:12 +0000254
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000255 if (Stmt* Term = B->getTerminator()) {
256 switch (Term->getStmtClass()) {
257 default:
258 assert(false && "Analysis for this terminator not implemented.");
259 break;
Mike Stump11289f42009-09-09 15:08:12 +0000260
Ted Kremenek822f7372008-02-12 21:51:20 +0000261 case Stmt::BinaryOperatorClass: // '&&' and '||'
262 HandleBranch(cast<BinaryOperator>(Term)->getLHS(), Term, B, Pred);
263 return;
Mike Stump11289f42009-09-09 15:08:12 +0000264
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000265 case Stmt::ConditionalOperatorClass:
266 HandleBranch(cast<ConditionalOperator>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000267 return;
Mike Stump11289f42009-09-09 15:08:12 +0000268
Ted Kremenek822f7372008-02-12 21:51:20 +0000269 // FIXME: Use constant-folding in CFG construction to simplify this
270 // case.
Mike Stump11289f42009-09-09 15:08:12 +0000271
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000272 case Stmt::ChooseExprClass:
273 HandleBranch(cast<ChooseExpr>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000274 return;
Mike Stump11289f42009-09-09 15:08:12 +0000275
Ted Kremenek822f7372008-02-12 21:51:20 +0000276 case Stmt::DoStmtClass:
277 HandleBranch(cast<DoStmt>(Term)->getCond(), Term, B, Pred);
278 return;
Mike Stump11289f42009-09-09 15:08:12 +0000279
Ted Kremenek822f7372008-02-12 21:51:20 +0000280 case Stmt::ForStmtClass:
281 HandleBranch(cast<ForStmt>(Term)->getCond(), Term, B, Pred);
282 return;
Mike Stump11289f42009-09-09 15:08:12 +0000283
Ted Kremenek632bcb82008-02-13 16:56:51 +0000284 case Stmt::ContinueStmtClass:
285 case Stmt::BreakStmtClass:
Mike Stump11289f42009-09-09 15:08:12 +0000286 case Stmt::GotoStmtClass:
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000287 break;
Mike Stump11289f42009-09-09 15:08:12 +0000288
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000289 case Stmt::IfStmtClass:
290 HandleBranch(cast<IfStmt>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000291 return;
Mike Stump11289f42009-09-09 15:08:12 +0000292
Ted Kremenek7022efb2008-02-13 00:24:44 +0000293 case Stmt::IndirectGotoStmtClass: {
294 // Only 1 successor: the indirect goto dispatch block.
295 assert (B->succ_size() == 1);
Mike Stump11289f42009-09-09 15:08:12 +0000296
Zhongxing Xu107f7592009-08-06 12:48:26 +0000297 GRIndirectGotoNodeBuilder
Ted Kremenek7022efb2008-02-13 00:24:44 +0000298 builder(Pred, B, cast<IndirectGotoStmt>(Term)->getTarget(),
299 *(B->succ_begin()), this);
Mike Stump11289f42009-09-09 15:08:12 +0000300
Ted Kremenek7022efb2008-02-13 00:24:44 +0000301 ProcessIndirectGoto(builder);
302 return;
303 }
Mike Stump11289f42009-09-09 15:08:12 +0000304
Ted Kremenek17810802008-11-12 19:24:17 +0000305 case Stmt::ObjCForCollectionStmtClass: {
306 // In the case of ObjCForCollectionStmt, it appears twice in a CFG:
307 //
308 // (1) inside a basic block, which represents the binding of the
309 // 'element' variable to a value.
310 // (2) in a terminator, which represents the branch.
311 //
312 // For (1), subengines will bind a value (i.e., 0 or 1) indicating
313 // whether or not collection contains any more elements. We cannot
314 // just test to see if the element is nil because a container can
315 // contain nil elements.
316 HandleBranch(Term, Term, B, Pred);
317 return;
318 }
Mike Stump11289f42009-09-09 15:08:12 +0000319
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000320 case Stmt::SwitchStmtClass: {
Zhongxing Xu107f7592009-08-06 12:48:26 +0000321 GRSwitchNodeBuilder builder(Pred, B, cast<SwitchStmt>(Term)->getCond(),
322 this);
Mike Stump11289f42009-09-09 15:08:12 +0000323
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000324 ProcessSwitch(builder);
325 return;
326 }
Mike Stump11289f42009-09-09 15:08:12 +0000327
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000328 case Stmt::WhileStmtClass:
329 HandleBranch(cast<WhileStmt>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000330 return;
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000331 }
332 }
Ted Kremenek822f7372008-02-12 21:51:20 +0000333
334 assert (B->succ_size() == 1 &&
335 "Blocks with no terminator should have at most 1 successor.");
Mike Stump11289f42009-09-09 15:08:12 +0000336
337 GenerateNode(BlockEdge(B, *(B->succ_begin()), Pred->getLocationContext()),
Zhongxing Xue1190f72009-08-15 03:17:38 +0000338 Pred->State, Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000339}
340
Zhongxing Xu82003da2009-08-06 10:00:15 +0000341void GRCoreEngine::HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock * B,
342 ExplodedNode* Pred) {
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000343 assert (B->succ_size() == 2);
344
Zhongxing Xu107f7592009-08-06 12:48:26 +0000345 GRBranchNodeBuilder Builder(B, *(B->succ_begin()), *(B->succ_begin()+1),
346 Pred, this);
Mike Stump11289f42009-09-09 15:08:12 +0000347
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000348 ProcessBranch(Cond, Term, Builder);
349}
350
Zhongxing Xu82003da2009-08-06 10:00:15 +0000351void GRCoreEngine::HandlePostStmt(const PostStmt& L, CFGBlock* B,
Zhongxing Xu20227f72009-08-06 01:32:16 +0000352 unsigned StmtIdx, ExplodedNode* Pred) {
Mike Stump11289f42009-09-09 15:08:12 +0000353
Ted Kremenek3e743662008-01-14 23:24:37 +0000354 assert (!B->empty());
355
Ted Kremeneke5843592008-01-15 00:24:08 +0000356 if (StmtIdx == B->size())
357 HandleBlockExit(B, Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000358 else {
Mike Stump11289f42009-09-09 15:08:12 +0000359 GRStmtNodeBuilder Builder(B, StmtIdx, Pred, this,
Zhongxing Xu107f7592009-08-06 12:48:26 +0000360 SubEngine.getStateManager());
Ted Kremeneke914bb82008-01-16 22:13:19 +0000361 ProcessStmt((*B)[StmtIdx], Builder);
Ted Kremenek3e743662008-01-14 23:24:37 +0000362 }
363}
364
Ted Kremenek3e743662008-01-14 23:24:37 +0000365/// GenerateNode - Utility method to generate nodes, hook up successors,
366/// and add nodes to the worklist.
Mike Stump11289f42009-09-09 15:08:12 +0000367void GRCoreEngine::GenerateNode(const ProgramPoint& Loc,
Zhongxing Xu82003da2009-08-06 10:00:15 +0000368 const GRState* State, ExplodedNode* Pred) {
Mike Stump11289f42009-09-09 15:08:12 +0000369
Ted Kremenek3e743662008-01-14 23:24:37 +0000370 bool IsNew;
Zhongxing Xuc90a0c22009-08-06 06:28:40 +0000371 ExplodedNode* Node = G->getNode(Loc, State, &IsNew);
Mike Stump11289f42009-09-09 15:08:12 +0000372
373 if (Pred)
Ted Kremenekc3661de2009-10-07 00:42:52 +0000374 Node->addPredecessor(Pred, *G); // Link 'Node' with its predecessor.
Ted Kremenek3e743662008-01-14 23:24:37 +0000375 else {
376 assert (IsNew);
377 G->addRoot(Node); // 'Node' has no predecessor. Make it a root.
378 }
Mike Stump11289f42009-09-09 15:08:12 +0000379
Ted Kremenek3e743662008-01-14 23:24:37 +0000380 // Only add 'Node' to the worklist if it was freshly generated.
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000381 if (IsNew) WList->Enqueue(Node);
Ted Kremenek3e743662008-01-14 23:24:37 +0000382}
383
Zhongxing Xu107f7592009-08-06 12:48:26 +0000384GRStmtNodeBuilder::GRStmtNodeBuilder(CFGBlock* b, unsigned idx,
385 ExplodedNode* N, GRCoreEngine* e,
386 GRStateManager &mgr)
Mike Stump11289f42009-09-09 15:08:12 +0000387 : Eng(*e), B(*b), Idx(idx), Pred(N), LastNode(N), Mgr(mgr), Auditor(0),
Zhongxing Xu107f7592009-08-06 12:48:26 +0000388 PurgingDeadSymbols(false), BuildSinks(false), HasGeneratedNode(false),
389 PointKind(ProgramPoint::PostStmtKind), Tag(0) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000390 Deferred.insert(N);
Zhongxing Xu107f7592009-08-06 12:48:26 +0000391 CleanedState = getLastNode()->getState();
Ted Kremenek3e743662008-01-14 23:24:37 +0000392}
393
Zhongxing Xu107f7592009-08-06 12:48:26 +0000394GRStmtNodeBuilder::~GRStmtNodeBuilder() {
Ted Kremenek3e743662008-01-14 23:24:37 +0000395 for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
Ted Kremeneka50d9852008-01-30 23:03:39 +0000396 if (!(*I)->isSink())
Ted Kremenek3e743662008-01-14 23:24:37 +0000397 GenerateAutoTransition(*I);
398}
399
Zhongxing Xu107f7592009-08-06 12:48:26 +0000400void GRStmtNodeBuilder::GenerateAutoTransition(ExplodedNode* N) {
Ted Kremeneka50d9852008-01-30 23:03:39 +0000401 assert (!N->isSink());
Mike Stump11289f42009-09-09 15:08:12 +0000402
Zhongxing Xue1190f72009-08-15 03:17:38 +0000403 PostStmt Loc(getStmt(), N->getLocationContext());
Mike Stump11289f42009-09-09 15:08:12 +0000404
Ted Kremenek3e743662008-01-14 23:24:37 +0000405 if (Loc == N->getLocation()) {
406 // Note: 'N' should be a fresh node because otherwise it shouldn't be
407 // a member of Deferred.
408 Eng.WList->Enqueue(N, B, Idx+1);
409 return;
410 }
Mike Stump11289f42009-09-09 15:08:12 +0000411
Ted Kremenek3e743662008-01-14 23:24:37 +0000412 bool IsNew;
Zhongxing Xuc90a0c22009-08-06 06:28:40 +0000413 ExplodedNode* Succ = Eng.G->getNode(Loc, N->State, &IsNew);
Ted Kremenekc3661de2009-10-07 00:42:52 +0000414 Succ->addPredecessor(N, *Eng.G);
Ted Kremenek3e743662008-01-14 23:24:37 +0000415
416 if (IsNew)
417 Eng.WList->Enqueue(Succ, B, Idx+1);
418}
419
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000420static ProgramPoint GetProgramPoint(const Stmt *S, ProgramPoint::Kind K,
421 const LocationContext *LC, const void *tag){
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000422 switch (K) {
423 default:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000424 assert(false && "Unhandled ProgramPoint kind");
425 case ProgramPoint::PreStmtKind:
426 return PreStmt(S, LC, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000427 case ProgramPoint::PostStmtKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000428 return PostStmt(S, LC, tag);
429 case ProgramPoint::PreLoadKind:
430 return PreLoad(S, LC, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000431 case ProgramPoint::PostLoadKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000432 return PostLoad(S, LC, tag);
433 case ProgramPoint::PreStoreKind:
434 return PreStore(S, LC, tag);
Ted Kremeneka1966182008-10-17 20:49:23 +0000435 case ProgramPoint::PostStoreKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000436 return PostStore(S, LC, tag);
Ted Kremeneka6e08322009-05-07 18:27:16 +0000437 case ProgramPoint::PostLValueKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000438 return PostLValue(S, LC, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000439 case ProgramPoint::PostPurgeDeadSymbolsKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000440 return PostPurgeDeadSymbols(S, LC, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000441 }
442}
443
Zhongxing Xu20227f72009-08-06 01:32:16 +0000444ExplodedNode*
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000445GRStmtNodeBuilder::generateNodeInternal(const Stmt* S, const GRState* state,
Zhongxing Xu20227f72009-08-06 01:32:16 +0000446 ExplodedNode* Pred,
Ted Kremenekdf240002009-04-11 00:11:10 +0000447 ProgramPoint::Kind K,
448 const void *tag) {
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000449
Zhongxing Xud2ab38e2009-12-23 08:54:57 +0000450 const ProgramPoint &L = GetProgramPoint(S, K, Pred->getLocationContext(),tag);
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000451 return generateNodeInternal(L, state, Pred);
Ted Kremenek513f0b12009-02-19 23:45:28 +0000452}
453
Zhongxing Xu20227f72009-08-06 01:32:16 +0000454ExplodedNode*
Zhongxing Xu107f7592009-08-06 12:48:26 +0000455GRStmtNodeBuilder::generateNodeInternal(const ProgramPoint &Loc,
Zhongxing Xuc90a0c22009-08-06 06:28:40 +0000456 const GRState* State,
Zhongxing Xu20227f72009-08-06 01:32:16 +0000457 ExplodedNode* Pred) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000458 bool IsNew;
Zhongxing Xuc90a0c22009-08-06 06:28:40 +0000459 ExplodedNode* N = Eng.G->getNode(Loc, State, &IsNew);
Ted Kremenekc3661de2009-10-07 00:42:52 +0000460 N->addPredecessor(Pred, *Eng.G);
Ted Kremenek3e743662008-01-14 23:24:37 +0000461 Deferred.erase(Pred);
Mike Stump11289f42009-09-09 15:08:12 +0000462
Ted Kremenek3e743662008-01-14 23:24:37 +0000463 if (IsNew) {
464 Deferred.insert(N);
465 LastNode = N;
466 return N;
467 }
Mike Stump11289f42009-09-09 15:08:12 +0000468
Ted Kremenek3e743662008-01-14 23:24:37 +0000469 LastNode = NULL;
Mike Stump11289f42009-09-09 15:08:12 +0000470 return NULL;
Ted Kremenek3e743662008-01-14 23:24:37 +0000471}
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000472
Zhongxing Xu107f7592009-08-06 12:48:26 +0000473ExplodedNode* GRBranchNodeBuilder::generateNode(const GRState* State,
474 bool branch) {
Mike Stump11289f42009-09-09 15:08:12 +0000475
Ted Kremenekaf9f3622009-07-20 18:44:36 +0000476 // If the branch has been marked infeasible we should not generate a node.
477 if (!isFeasible(branch))
478 return NULL;
Mike Stump11289f42009-09-09 15:08:12 +0000479
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000480 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000481
Zhongxing Xu20227f72009-08-06 01:32:16 +0000482 ExplodedNode* Succ =
Zhongxing Xue1190f72009-08-15 03:17:38 +0000483 Eng.G->getNode(BlockEdge(Src,branch ? DstT:DstF,Pred->getLocationContext()),
484 State, &IsNew);
Mike Stump11289f42009-09-09 15:08:12 +0000485
Ted Kremenekc3661de2009-10-07 00:42:52 +0000486 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000487
Ted Kremenekaf9f3622009-07-20 18:44:36 +0000488 if (branch)
489 GeneratedTrue = true;
490 else
Mike Stump11289f42009-09-09 15:08:12 +0000491 GeneratedFalse = true;
492
Ted Kremeneka50d9852008-01-30 23:03:39 +0000493 if (IsNew) {
Ted Kremenek2531fce2008-01-30 23:24:39 +0000494 Deferred.push_back(Succ);
Ted Kremeneka50d9852008-01-30 23:03:39 +0000495 return Succ;
496 }
Mike Stump11289f42009-09-09 15:08:12 +0000497
Ted Kremeneka50d9852008-01-30 23:03:39 +0000498 return NULL;
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000499}
Ted Kremenek7ff18932008-01-29 23:32:35 +0000500
Zhongxing Xu107f7592009-08-06 12:48:26 +0000501GRBranchNodeBuilder::~GRBranchNodeBuilder() {
502 if (!GeneratedTrue) generateNode(Pred->State, true);
503 if (!GeneratedFalse) generateNode(Pred->State, false);
Mike Stump11289f42009-09-09 15:08:12 +0000504
Ted Kremenek2531fce2008-01-30 23:24:39 +0000505 for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000506 if (!(*I)->isSink()) Eng.WList->Enqueue(*I);
Ted Kremenek7ff18932008-01-29 23:32:35 +0000507}
Ted Kremenek7022efb2008-02-13 00:24:44 +0000508
Ted Kremenek7022efb2008-02-13 00:24:44 +0000509
Zhongxing Xu20227f72009-08-06 01:32:16 +0000510ExplodedNode*
Zhongxing Xu107f7592009-08-06 12:48:26 +0000511GRIndirectGotoNodeBuilder::generateNode(const iterator& I, const GRState* St,
512 bool isSink) {
Ted Kremenek7022efb2008-02-13 00:24:44 +0000513 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000514
515 ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
Zhongxing Xue1190f72009-08-15 03:17:38 +0000516 Pred->getLocationContext()), St, &IsNew);
Mike Stump11289f42009-09-09 15:08:12 +0000517
Ted Kremenekc3661de2009-10-07 00:42:52 +0000518 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000519
Ted Kremenek7022efb2008-02-13 00:24:44 +0000520 if (IsNew) {
Mike Stump11289f42009-09-09 15:08:12 +0000521
Ted Kremenek7022efb2008-02-13 00:24:44 +0000522 if (isSink)
523 Succ->markAsSink();
524 else
525 Eng.WList->Enqueue(Succ);
Mike Stump11289f42009-09-09 15:08:12 +0000526
Ted Kremenek7022efb2008-02-13 00:24:44 +0000527 return Succ;
528 }
Mike Stump11289f42009-09-09 15:08:12 +0000529
Ted Kremenek7022efb2008-02-13 00:24:44 +0000530 return NULL;
531}
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000532
533
Zhongxing Xu20227f72009-08-06 01:32:16 +0000534ExplodedNode*
Zhongxing Xu107f7592009-08-06 12:48:26 +0000535GRSwitchNodeBuilder::generateCaseStmtNode(const iterator& I, const GRState* St){
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000536
537 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000538
Zhongxing Xue1190f72009-08-15 03:17:38 +0000539 ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
540 Pred->getLocationContext()), St, &IsNew);
Ted Kremenekc3661de2009-10-07 00:42:52 +0000541 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000542
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000543 if (IsNew) {
544 Eng.WList->Enqueue(Succ);
545 return Succ;
546 }
Mike Stump11289f42009-09-09 15:08:12 +0000547
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000548 return NULL;
549}
550
551
Zhongxing Xu20227f72009-08-06 01:32:16 +0000552ExplodedNode*
Zhongxing Xu107f7592009-08-06 12:48:26 +0000553GRSwitchNodeBuilder::generateDefaultCaseNode(const GRState* St, bool isSink) {
Mike Stump11289f42009-09-09 15:08:12 +0000554
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000555 // Get the block for the default case.
556 assert (Src->succ_rbegin() != Src->succ_rend());
557 CFGBlock* DefaultBlock = *Src->succ_rbegin();
Mike Stump11289f42009-09-09 15:08:12 +0000558
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000559 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000560
Zhongxing Xue1190f72009-08-15 03:17:38 +0000561 ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, DefaultBlock,
562 Pred->getLocationContext()), St, &IsNew);
Ted Kremenekc3661de2009-10-07 00:42:52 +0000563 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000564
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000565 if (IsNew) {
566 if (isSink)
567 Succ->markAsSink();
568 else
569 Eng.WList->Enqueue(Succ);
Mike Stump11289f42009-09-09 15:08:12 +0000570
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000571 return Succ;
572 }
Mike Stump11289f42009-09-09 15:08:12 +0000573
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000574 return NULL;
575}
Ted Kremenek811c2b42008-04-11 22:03:04 +0000576
Zhongxing Xu107f7592009-08-06 12:48:26 +0000577GREndPathNodeBuilder::~GREndPathNodeBuilder() {
Ted Kremenek811c2b42008-04-11 22:03:04 +0000578 // Auto-generate an EOP node if one has not been generated.
Jakob Stoklund Olesen5a8f9ac2010-02-25 15:47:53 +0000579 if (!HasGeneratedNode) generateNode(Pred->State);
Ted Kremenek811c2b42008-04-11 22:03:04 +0000580}
581
Zhongxing Xu20227f72009-08-06 01:32:16 +0000582ExplodedNode*
Zhongxing Xu107f7592009-08-06 12:48:26 +0000583GREndPathNodeBuilder::generateNode(const GRState* State, const void *tag,
584 ExplodedNode* P) {
Mike Stump11289f42009-09-09 15:08:12 +0000585 HasGeneratedNode = true;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000586 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000587
588 ExplodedNode* Node = Eng.G->getNode(BlockEntrance(&B,
Zhongxing Xue1190f72009-08-15 03:17:38 +0000589 Pred->getLocationContext(), tag), State, &IsNew);
Mike Stump11289f42009-09-09 15:08:12 +0000590
Ted Kremenekc3661de2009-10-07 00:42:52 +0000591 Node->addPredecessor(P ? P : Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000592
Ted Kremenek811c2b42008-04-11 22:03:04 +0000593 if (IsNew) {
Ted Kremenek811c2b42008-04-11 22:03:04 +0000594 Eng.G->addEndOfPath(Node);
Ted Kremenekd004c412008-04-18 16:30:14 +0000595 return Node;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000596 }
Mike Stump11289f42009-09-09 15:08:12 +0000597
Ted Kremenekd004c412008-04-18 16:30:14 +0000598 return NULL;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000599}