blob: a23c7f9d2d4c411206d887122a9821677b3033f6 [file] [log] [blame]
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +00001//==- CoreEngine.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 Kremenekd99bd552010-12-23 19:38:26 +000015#include "clang/StaticAnalyzer/PathSensitive/AnalysisManager.h"
16#include "clang/StaticAnalyzer/PathSensitive/CoreEngine.h"
17#include "clang/StaticAnalyzer/PathSensitive/ExprEngine.h"
Zhongxing Xuadf644d2010-07-22 13:52:13 +000018#include "clang/Index/TranslationUnit.h"
Ted Kremenek3e743662008-01-14 23:24:37 +000019#include "clang/AST/Expr.h"
Ted Kremenek3e743662008-01-14 23:24:37 +000020#include "llvm/Support/Casting.h"
21#include "llvm/ADT/DenseMap.h"
22#include <vector>
Ted Kremenekd9de9f12008-12-16 22:13:33 +000023#include <queue>
Ted Kremenek3e743662008-01-14 23:24:37 +000024
25using llvm::cast;
26using llvm::isa;
27using namespace clang;
Ted Kremenek98857c92010-12-23 07:20:52 +000028using namespace ento;
Ted Kremenek3e743662008-01-14 23:24:37 +000029
Zhongxing Xuadf644d2010-07-22 13:52:13 +000030// This should be removed in the future.
31namespace clang {
Ted Kremenek98857c92010-12-23 07:20:52 +000032namespace ento {
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +000033TransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
Zhongxing Xuadf644d2010-07-22 13:52:13 +000034 const LangOptions& lopts);
35}
Argyrios Kyrtzidisca08fba2010-12-22 18:53:20 +000036}
Zhongxing Xuadf644d2010-07-22 13:52:13 +000037
Ted Kremenekd9de9f12008-12-16 22:13:33 +000038//===----------------------------------------------------------------------===//
39// Worklist classes for exploration of reachable states.
40//===----------------------------------------------------------------------===//
41
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +000042WorkList::Visitor::~Visitor() {}
Ted Kremenekb02788d2010-11-13 05:04:49 +000043
Ted Kremenek3e743662008-01-14 23:24:37 +000044namespace {
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +000045class DFS : public WorkList {
46 llvm::SmallVector<WorkListUnit,20> Stack;
Ted Kremenek3e743662008-01-14 23:24:37 +000047public:
48 virtual bool hasWork() const {
49 return !Stack.empty();
50 }
51
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +000052 virtual void Enqueue(const WorkListUnit& U) {
Ted Kremenek3e743662008-01-14 23:24:37 +000053 Stack.push_back(U);
54 }
55
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +000056 virtual WorkListUnit Dequeue() {
Ted Kremenek3e743662008-01-14 23:24:37 +000057 assert (!Stack.empty());
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +000058 const WorkListUnit& U = Stack.back();
Ted Kremenek3e743662008-01-14 23:24:37 +000059 Stack.pop_back(); // This technically "invalidates" U, but we are fine.
60 return U;
61 }
Ted Kremenekb02788d2010-11-13 05:04:49 +000062
63 virtual bool VisitItemsInWorkList(Visitor &V) {
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +000064 for (llvm::SmallVectorImpl<WorkListUnit>::iterator
Ted Kremenekb02788d2010-11-13 05:04:49 +000065 I = Stack.begin(), E = Stack.end(); I != E; ++I) {
66 if (V.Visit(*I))
67 return true;
68 }
69 return false;
70 }
Ted Kremenek3e743662008-01-14 23:24:37 +000071};
Mike Stump11289f42009-09-09 15:08:12 +000072
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +000073class BFS : public WorkList {
74 std::deque<WorkListUnit> Queue;
Ted Kremenek2c327732009-05-01 22:18:46 +000075public:
76 virtual bool hasWork() const {
77 return !Queue.empty();
78 }
Mike Stump11289f42009-09-09 15:08:12 +000079
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +000080 virtual void Enqueue(const WorkListUnit& U) {
Ted Kremenekb02788d2010-11-13 05:04:49 +000081 Queue.push_front(U);
Ted Kremenek2c327732009-05-01 22:18:46 +000082 }
Mike Stump11289f42009-09-09 15:08:12 +000083
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +000084 virtual WorkListUnit Dequeue() {
85 WorkListUnit U = Queue.front();
Ted Kremenekb02788d2010-11-13 05:04:49 +000086 Queue.pop_front();
Ted Kremenek2c327732009-05-01 22:18:46 +000087 return U;
88 }
Ted Kremenekb02788d2010-11-13 05:04:49 +000089
90 virtual bool VisitItemsInWorkList(Visitor &V) {
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +000091 for (std::deque<WorkListUnit>::iterator
Ted Kremenekb02788d2010-11-13 05:04:49 +000092 I = Queue.begin(), E = Queue.end(); I != E; ++I) {
93 if (V.Visit(*I))
94 return true;
95 }
96 return false;
97 }
Ted Kremenek2c327732009-05-01 22:18:46 +000098};
Mike Stump11289f42009-09-09 15:08:12 +000099
Ted Kremenek3e743662008-01-14 23:24:37 +0000100} // end anonymous namespace
101
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000102// Place the dstor for WorkList here because it contains virtual member
Ted Kremenek2e12c2e2008-01-16 18:18:48 +0000103// functions, and we the code for the dstor generated in one compilation unit.
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000104WorkList::~WorkList() {}
Ted Kremenek2e12c2e2008-01-16 18:18:48 +0000105
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000106WorkList *WorkList::MakeDFS() { return new DFS(); }
107WorkList *WorkList::MakeBFS() { return new BFS(); }
Ted Kremenek3e743662008-01-14 23:24:37 +0000108
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000109namespace {
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000110 class BFSBlockDFSContents : public WorkList {
111 std::deque<WorkListUnit> Queue;
112 llvm::SmallVector<WorkListUnit,20> Stack;
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000113 public:
114 virtual bool hasWork() const {
115 return !Queue.empty() || !Stack.empty();
116 }
Mike Stump11289f42009-09-09 15:08:12 +0000117
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000118 virtual void Enqueue(const WorkListUnit& U) {
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000119 if (isa<BlockEntrance>(U.getNode()->getLocation()))
Ted Kremenekb02788d2010-11-13 05:04:49 +0000120 Queue.push_front(U);
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000121 else
122 Stack.push_back(U);
123 }
Mike Stump11289f42009-09-09 15:08:12 +0000124
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000125 virtual WorkListUnit Dequeue() {
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000126 // Process all basic blocks to completion.
127 if (!Stack.empty()) {
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000128 const WorkListUnit& U = Stack.back();
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000129 Stack.pop_back(); // This technically "invalidates" U, but we are fine.
130 return U;
131 }
Mike Stump11289f42009-09-09 15:08:12 +0000132
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000133 assert(!Queue.empty());
134 // Don't use const reference. The subsequent pop_back() might make it
135 // unsafe.
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000136 WorkListUnit U = Queue.front();
Ted Kremenekb02788d2010-11-13 05:04:49 +0000137 Queue.pop_front();
Mike Stump11289f42009-09-09 15:08:12 +0000138 return U;
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000139 }
Ted Kremenekb02788d2010-11-13 05:04:49 +0000140 virtual bool VisitItemsInWorkList(Visitor &V) {
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000141 for (llvm::SmallVectorImpl<WorkListUnit>::iterator
Ted Kremenekb02788d2010-11-13 05:04:49 +0000142 I = Stack.begin(), E = Stack.end(); I != E; ++I) {
143 if (V.Visit(*I))
144 return true;
145 }
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000146 for (std::deque<WorkListUnit>::iterator
Ted Kremenekb02788d2010-11-13 05:04:49 +0000147 I = Queue.begin(), E = Queue.end(); I != E; ++I) {
148 if (V.Visit(*I))
149 return true;
150 }
151 return false;
152 }
153
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000154 };
155} // end anonymous namespace
156
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000157WorkList* WorkList::MakeBFSBlockDFSContents() {
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000158 return new BFSBlockDFSContents();
159}
160
161//===----------------------------------------------------------------------===//
162// Core analysis engine.
163//===----------------------------------------------------------------------===//
Douglas Gregora2fbc942010-02-25 19:01:53 +0000164
Ted Kremenek3e743662008-01-14 23:24:37 +0000165/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000166bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000167 const GRState *InitState) {
Mike Stump11289f42009-09-09 15:08:12 +0000168
Ted Kremenek3e743662008-01-14 23:24:37 +0000169 if (G->num_roots() == 0) { // Initialize the analysis by constructing
170 // the root if none exists.
Mike Stump11289f42009-09-09 15:08:12 +0000171
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000172 const CFGBlock* Entry = &(L->getCFG()->getEntry());
Mike Stump11289f42009-09-09 15:08:12 +0000173
174 assert (Entry->empty() &&
Ted Kremenek3e743662008-01-14 23:24:37 +0000175 "Entry block must be empty.");
Mike Stump11289f42009-09-09 15:08:12 +0000176
Ted Kremenek3e743662008-01-14 23:24:37 +0000177 assert (Entry->succ_size() == 1 &&
178 "Entry block must have 1 successor.");
Mike Stump11289f42009-09-09 15:08:12 +0000179
Ted Kremenek3e743662008-01-14 23:24:37 +0000180 // Get the solitary successor.
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000181 const CFGBlock* Succ = *(Entry->succ_begin());
Mike Stump11289f42009-09-09 15:08:12 +0000182
Ted Kremenek3e743662008-01-14 23:24:37 +0000183 // Construct an edge representing the
184 // starting location in the function.
Zhongxing Xue1190f72009-08-15 03:17:38 +0000185 BlockEdge StartLoc(Entry, Succ, L);
Mike Stump11289f42009-09-09 15:08:12 +0000186
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000187 // Set the current block counter to being empty.
188 WList->setBlockCounter(BCounterFactory.GetEmptyCounter());
Mike Stump11289f42009-09-09 15:08:12 +0000189
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000190 if (!InitState)
191 // Generate the root.
Ted Kremenek750b7ac2010-12-20 21:19:09 +0000192 generateNode(StartLoc, getInitialState(L), 0);
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000193 else
Ted Kremenek750b7ac2010-12-20 21:19:09 +0000194 generateNode(StartLoc, InitState, 0);
Ted Kremenek3e743662008-01-14 23:24:37 +0000195 }
Mike Stump11289f42009-09-09 15:08:12 +0000196
Tom Care472205b2010-09-29 23:48:13 +0000197 // Check if we have a steps limit
198 bool UnlimitedSteps = Steps == 0;
199
200 while (WList->hasWork()) {
201 if (!UnlimitedSteps) {
202 if (Steps == 0)
203 break;
204 --Steps;
205 }
206
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000207 const WorkListUnit& WU = WList->Dequeue();
Mike Stump11289f42009-09-09 15:08:12 +0000208
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000209 // Set the current block counter.
210 WList->setBlockCounter(WU.getBlockCounter());
211
212 // Retrieve the node.
Zhongxing Xu20227f72009-08-06 01:32:16 +0000213 ExplodedNode* Node = WU.getNode();
Mike Stump11289f42009-09-09 15:08:12 +0000214
Ted Kremenek3e743662008-01-14 23:24:37 +0000215 // Dispatch on the location type.
216 switch (Node->getLocation().getKind()) {
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000217 case ProgramPoint::BlockEdgeKind:
Ted Kremenek3e743662008-01-14 23:24:37 +0000218 HandleBlockEdge(cast<BlockEdge>(Node->getLocation()), Node);
219 break;
Mike Stump11289f42009-09-09 15:08:12 +0000220
Ted Kremenek3e743662008-01-14 23:24:37 +0000221 case ProgramPoint::BlockEntranceKind:
222 HandleBlockEntrance(cast<BlockEntrance>(Node->getLocation()), Node);
223 break;
Mike Stump11289f42009-09-09 15:08:12 +0000224
Ted Kremenek3e743662008-01-14 23:24:37 +0000225 case ProgramPoint::BlockExitKind:
Ted Kremeneke5843592008-01-15 00:24:08 +0000226 assert (false && "BlockExit location never occur in forward analysis.");
Ted Kremenek3e743662008-01-14 23:24:37 +0000227 break;
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000228
Douglas Gregora2fbc942010-02-25 19:01:53 +0000229 case ProgramPoint::CallEnterKind:
230 HandleCallEnter(cast<CallEnter>(Node->getLocation()), WU.getBlock(),
231 WU.getIndex(), Node);
232 break;
233
234 case ProgramPoint::CallExitKind:
235 HandleCallExit(cast<CallExit>(Node->getLocation()), Node);
236 break;
237
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000238 default:
Zhongxing Xu1ade3262010-11-16 07:52:17 +0000239 assert(isa<PostStmt>(Node->getLocation()) ||
240 isa<PostInitializer>(Node->getLocation()));
241 HandlePostStmt(WU.getBlock(), WU.getIndex(), Node);
Mike Stump11289f42009-09-09 15:08:12 +0000242 break;
Ted Kremenek3e743662008-01-14 23:24:37 +0000243 }
244 }
Mike Stump11289f42009-09-09 15:08:12 +0000245
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000246 SubEng.ProcessEndWorklist(hasWorkRemaining());
Ted Kremenek3e743662008-01-14 23:24:37 +0000247 return WList->hasWork();
248}
249
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000250void CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L,
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000251 unsigned Steps,
252 const GRState *InitState,
253 ExplodedNodeSet &Dst) {
254 ExecuteWorkList(L, Steps, InitState);
255 for (llvm::SmallVectorImpl<ExplodedNode*>::iterator I = G->EndNodes.begin(),
256 E = G->EndNodes.end(); I != E; ++I) {
257 Dst.Add(*I);
258 }
259}
260
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000261void CoreEngine::HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
Douglas Gregora2fbc942010-02-25 19:01:53 +0000262 unsigned Index, ExplodedNode *Pred) {
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000263 CallEnterNodeBuilder Builder(*this, Pred, L.getCallExpr(),
Zhongxing Xu84f65e02010-07-19 01:31:21 +0000264 L.getCalleeContext(), Block, Index);
Douglas Gregora2fbc942010-02-25 19:01:53 +0000265 ProcessCallEnter(Builder);
266}
267
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000268void CoreEngine::HandleCallExit(const CallExit &L, ExplodedNode *Pred) {
269 CallExitNodeBuilder Builder(*this, Pred);
Douglas Gregora2fbc942010-02-25 19:01:53 +0000270 ProcessCallExit(Builder);
271}
Zhongxing Xu82003da2009-08-06 10:00:15 +0000272
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000273void CoreEngine::HandleBlockEdge(const BlockEdge& L, ExplodedNode* Pred) {
Mike Stump11289f42009-09-09 15:08:12 +0000274
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000275 const CFGBlock* Blk = L.getDst();
Mike Stump11289f42009-09-09 15:08:12 +0000276
277 // Check if we are entering the EXIT block.
Zhongxing Xud2ab38e2009-12-23 08:54:57 +0000278 if (Blk == &(L.getLocationContext()->getCFG()->getExit())) {
Mike Stump11289f42009-09-09 15:08:12 +0000279
Zhongxing Xud2ab38e2009-12-23 08:54:57 +0000280 assert (L.getLocationContext()->getCFG()->getExit().size() == 0
Ted Kremenek997d8722008-01-29 00:33:40 +0000281 && "EXIT block cannot contain Stmts.");
Ted Kremenek3e743662008-01-14 23:24:37 +0000282
Ted Kremenek811c2b42008-04-11 22:03:04 +0000283 // Process the final state transition.
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000284 EndPathNodeBuilder Builder(Blk, Pred, this);
Ted Kremenek811c2b42008-04-11 22:03:04 +0000285 ProcessEndPath(Builder);
Ted Kremenek3e743662008-01-14 23:24:37 +0000286
Ted Kremenek3e743662008-01-14 23:24:37 +0000287 // This path is done. Don't enqueue any more nodes.
288 return;
289 }
Ted Kremenek17f4dbd2008-02-29 20:27:50 +0000290
291 // FIXME: Should we allow ProcessBlockEntrance to also manipulate state?
Mike Stump11289f42009-09-09 15:08:12 +0000292
Zhongxing Xu3c0c81a2010-03-23 05:05:02 +0000293 if (ProcessBlockEntrance(Blk, Pred, WList->getBlockCounter()))
Ted Kremenek750b7ac2010-12-20 21:19:09 +0000294 generateNode(BlockEntrance(Blk, Pred->getLocationContext()),
Ted Kremenek090d62e2010-06-29 21:58:54 +0000295 Pred->State, Pred);
Ted Kremenek2b4adff2010-08-11 00:03:02 +0000296 else {
297 blocksAborted.push_back(std::make_pair(L, Pred));
298 }
Ted Kremenek3e743662008-01-14 23:24:37 +0000299}
300
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000301void CoreEngine::HandleBlockEntrance(const BlockEntrance& L,
Zhongxing Xu107f7592009-08-06 12:48:26 +0000302 ExplodedNode* Pred) {
Mike Stump11289f42009-09-09 15:08:12 +0000303
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000304 // Increment the block counter.
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000305 BlockCounter Counter = WList->getBlockCounter();
Zhongxing Xu3c0c81a2010-03-23 05:05:02 +0000306 Counter = BCounterFactory.IncrementCount(Counter,
307 Pred->getLocationContext()->getCurrentStackFrame(),
308 L.getBlock()->getBlockID());
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000309 WList->setBlockCounter(Counter);
Mike Stump11289f42009-09-09 15:08:12 +0000310
311 // Process the entrance of the block.
Ted Kremenek4cad5fc2009-12-16 03:18:58 +0000312 if (CFGElement E = L.getFirstElement()) {
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000313 StmtNodeBuilder Builder(L.getBlock(), 0, Pred, this,
314 SubEng.getStateManager());
Zhongxing Xu5d30c692010-11-15 08:48:43 +0000315 ProcessElement(E, Builder);
Ted Kremenek3e743662008-01-14 23:24:37 +0000316 }
Mike Stump11289f42009-09-09 15:08:12 +0000317 else
Ted Kremeneke5843592008-01-15 00:24:08 +0000318 HandleBlockExit(L.getBlock(), Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000319}
320
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000321void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode* Pred) {
Mike Stump11289f42009-09-09 15:08:12 +0000322
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000323 if (const Stmt* Term = B->getTerminator()) {
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000324 switch (Term->getStmtClass()) {
325 default:
326 assert(false && "Analysis for this terminator not implemented.");
327 break;
Mike Stump11289f42009-09-09 15:08:12 +0000328
Ted Kremenek822f7372008-02-12 21:51:20 +0000329 case Stmt::BinaryOperatorClass: // '&&' and '||'
330 HandleBranch(cast<BinaryOperator>(Term)->getLHS(), Term, B, Pred);
331 return;
Mike Stump11289f42009-09-09 15:08:12 +0000332
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000333 case Stmt::ConditionalOperatorClass:
334 HandleBranch(cast<ConditionalOperator>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000335 return;
Mike Stump11289f42009-09-09 15:08:12 +0000336
Ted Kremenek822f7372008-02-12 21:51:20 +0000337 // FIXME: Use constant-folding in CFG construction to simplify this
338 // case.
Mike Stump11289f42009-09-09 15:08:12 +0000339
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000340 case Stmt::ChooseExprClass:
341 HandleBranch(cast<ChooseExpr>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000342 return;
Mike Stump11289f42009-09-09 15:08:12 +0000343
Ted Kremenek822f7372008-02-12 21:51:20 +0000344 case Stmt::DoStmtClass:
345 HandleBranch(cast<DoStmt>(Term)->getCond(), Term, B, Pred);
346 return;
Mike Stump11289f42009-09-09 15:08:12 +0000347
Ted Kremenek822f7372008-02-12 21:51:20 +0000348 case Stmt::ForStmtClass:
349 HandleBranch(cast<ForStmt>(Term)->getCond(), Term, B, Pred);
350 return;
Mike Stump11289f42009-09-09 15:08:12 +0000351
Ted Kremenek632bcb82008-02-13 16:56:51 +0000352 case Stmt::ContinueStmtClass:
353 case Stmt::BreakStmtClass:
Mike Stump11289f42009-09-09 15:08:12 +0000354 case Stmt::GotoStmtClass:
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000355 break;
Mike Stump11289f42009-09-09 15:08:12 +0000356
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000357 case Stmt::IfStmtClass:
358 HandleBranch(cast<IfStmt>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000359 return;
Mike Stump11289f42009-09-09 15:08:12 +0000360
Ted Kremenek7022efb2008-02-13 00:24:44 +0000361 case Stmt::IndirectGotoStmtClass: {
362 // Only 1 successor: the indirect goto dispatch block.
363 assert (B->succ_size() == 1);
Mike Stump11289f42009-09-09 15:08:12 +0000364
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000365 IndirectGotoNodeBuilder
Ted Kremenek7022efb2008-02-13 00:24:44 +0000366 builder(Pred, B, cast<IndirectGotoStmt>(Term)->getTarget(),
367 *(B->succ_begin()), this);
Mike Stump11289f42009-09-09 15:08:12 +0000368
Ted Kremenek7022efb2008-02-13 00:24:44 +0000369 ProcessIndirectGoto(builder);
370 return;
371 }
Mike Stump11289f42009-09-09 15:08:12 +0000372
Ted Kremenek17810802008-11-12 19:24:17 +0000373 case Stmt::ObjCForCollectionStmtClass: {
374 // In the case of ObjCForCollectionStmt, it appears twice in a CFG:
375 //
376 // (1) inside a basic block, which represents the binding of the
377 // 'element' variable to a value.
378 // (2) in a terminator, which represents the branch.
379 //
380 // For (1), subengines will bind a value (i.e., 0 or 1) indicating
381 // whether or not collection contains any more elements. We cannot
382 // just test to see if the element is nil because a container can
383 // contain nil elements.
384 HandleBranch(Term, Term, B, Pred);
385 return;
386 }
Mike Stump11289f42009-09-09 15:08:12 +0000387
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000388 case Stmt::SwitchStmtClass: {
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000389 SwitchNodeBuilder builder(Pred, B, cast<SwitchStmt>(Term)->getCond(),
Zhongxing Xu107f7592009-08-06 12:48:26 +0000390 this);
Mike Stump11289f42009-09-09 15:08:12 +0000391
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000392 ProcessSwitch(builder);
393 return;
394 }
Mike Stump11289f42009-09-09 15:08:12 +0000395
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000396 case Stmt::WhileStmtClass:
397 HandleBranch(cast<WhileStmt>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000398 return;
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000399 }
400 }
Ted Kremenek822f7372008-02-12 21:51:20 +0000401
402 assert (B->succ_size() == 1 &&
403 "Blocks with no terminator should have at most 1 successor.");
Mike Stump11289f42009-09-09 15:08:12 +0000404
Ted Kremenek750b7ac2010-12-20 21:19:09 +0000405 generateNode(BlockEdge(B, *(B->succ_begin()), Pred->getLocationContext()),
Zhongxing Xue1190f72009-08-15 03:17:38 +0000406 Pred->State, Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000407}
408
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000409void CoreEngine::HandleBranch(const Stmt* Cond, const Stmt* Term,
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000410 const CFGBlock * B, ExplodedNode* Pred) {
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000411 assert (B->succ_size() == 2);
412
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000413 BranchNodeBuilder Builder(B, *(B->succ_begin()), *(B->succ_begin()+1),
Zhongxing Xu107f7592009-08-06 12:48:26 +0000414 Pred, this);
Mike Stump11289f42009-09-09 15:08:12 +0000415
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000416 ProcessBranch(Cond, Term, Builder);
417}
418
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000419void CoreEngine::HandlePostStmt(const CFGBlock* B, unsigned StmtIdx,
Zhongxing Xu1ade3262010-11-16 07:52:17 +0000420 ExplodedNode* Pred) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000421 assert (!B->empty());
422
Ted Kremeneke5843592008-01-15 00:24:08 +0000423 if (StmtIdx == B->size())
424 HandleBlockExit(B, Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000425 else {
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000426 StmtNodeBuilder Builder(B, StmtIdx, Pred, this,
427 SubEng.getStateManager());
Zhongxing Xu5d30c692010-11-15 08:48:43 +0000428 ProcessElement((*B)[StmtIdx], Builder);
Ted Kremenek3e743662008-01-14 23:24:37 +0000429 }
430}
431
Ted Kremenek750b7ac2010-12-20 21:19:09 +0000432/// generateNode - Utility method to generate nodes, hook up successors,
Ted Kremenek3e743662008-01-14 23:24:37 +0000433/// and add nodes to the worklist.
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000434void CoreEngine::generateNode(const ProgramPoint& Loc,
435 const GRState* State, ExplodedNode* Pred) {
Mike Stump11289f42009-09-09 15:08:12 +0000436
Ted Kremenek3e743662008-01-14 23:24:37 +0000437 bool IsNew;
Zhongxing Xuc90a0c22009-08-06 06:28:40 +0000438 ExplodedNode* Node = G->getNode(Loc, State, &IsNew);
Mike Stump11289f42009-09-09 15:08:12 +0000439
440 if (Pred)
Ted Kremenekc3661de2009-10-07 00:42:52 +0000441 Node->addPredecessor(Pred, *G); // Link 'Node' with its predecessor.
Ted Kremenek3e743662008-01-14 23:24:37 +0000442 else {
443 assert (IsNew);
444 G->addRoot(Node); // 'Node' has no predecessor. Make it a root.
445 }
Mike Stump11289f42009-09-09 15:08:12 +0000446
Ted Kremenek3e743662008-01-14 23:24:37 +0000447 // Only add 'Node' to the worklist if it was freshly generated.
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000448 if (IsNew) WList->Enqueue(Node);
Ted Kremenek3e743662008-01-14 23:24:37 +0000449}
450
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000451StmtNodeBuilder::StmtNodeBuilder(const CFGBlock* b, unsigned idx,
452 ExplodedNode* N, CoreEngine* e,
Zhongxing Xu107f7592009-08-06 12:48:26 +0000453 GRStateManager &mgr)
Ted Kremenek982b32b2010-10-20 23:48:34 +0000454 : Eng(*e), B(*b), Idx(idx), Pred(N), Mgr(mgr),
Zhongxing Xu107f7592009-08-06 12:48:26 +0000455 PurgingDeadSymbols(false), BuildSinks(false), HasGeneratedNode(false),
456 PointKind(ProgramPoint::PostStmtKind), Tag(0) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000457 Deferred.insert(N);
Zhongxing Xud041bc62010-02-26 02:38:09 +0000458 CleanedState = Pred->getState();
Ted Kremenek3e743662008-01-14 23:24:37 +0000459}
460
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000461StmtNodeBuilder::~StmtNodeBuilder() {
Ted Kremenek3e743662008-01-14 23:24:37 +0000462 for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
Ted Kremeneka50d9852008-01-30 23:03:39 +0000463 if (!(*I)->isSink())
Ted Kremenek3e743662008-01-14 23:24:37 +0000464 GenerateAutoTransition(*I);
465}
466
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000467void StmtNodeBuilder::GenerateAutoTransition(ExplodedNode* N) {
Ted Kremeneka50d9852008-01-30 23:03:39 +0000468 assert (!N->isSink());
Mike Stump11289f42009-09-09 15:08:12 +0000469
Douglas Gregora2fbc942010-02-25 19:01:53 +0000470 // Check if this node entered a callee.
471 if (isa<CallEnter>(N->getLocation())) {
472 // Still use the index of the CallExpr. It's needed to create the callee
473 // StackFrameContext.
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000474 Eng.WList->Enqueue(N, &B, Idx);
Douglas Gregora2fbc942010-02-25 19:01:53 +0000475 return;
476 }
477
Zhongxing Xu1ade3262010-11-16 07:52:17 +0000478 // Do not create extra nodes. Move to the next CFG element.
479 if (isa<PostInitializer>(N->getLocation())) {
480 Eng.WList->Enqueue(N, &B, Idx+1);
481 return;
482 }
483
Zhongxing Xue1190f72009-08-15 03:17:38 +0000484 PostStmt Loc(getStmt(), N->getLocationContext());
Mike Stump11289f42009-09-09 15:08:12 +0000485
Ted Kremenek3e743662008-01-14 23:24:37 +0000486 if (Loc == N->getLocation()) {
487 // Note: 'N' should be a fresh node because otherwise it shouldn't be
488 // a member of Deferred.
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000489 Eng.WList->Enqueue(N, &B, Idx+1);
Ted Kremenek3e743662008-01-14 23:24:37 +0000490 return;
491 }
Mike Stump11289f42009-09-09 15:08:12 +0000492
Ted Kremenek3e743662008-01-14 23:24:37 +0000493 bool IsNew;
Zhongxing Xuc90a0c22009-08-06 06:28:40 +0000494 ExplodedNode* Succ = Eng.G->getNode(Loc, N->State, &IsNew);
Ted Kremenekc3661de2009-10-07 00:42:52 +0000495 Succ->addPredecessor(N, *Eng.G);
Ted Kremenek3e743662008-01-14 23:24:37 +0000496
497 if (IsNew)
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000498 Eng.WList->Enqueue(Succ, &B, Idx+1);
Ted Kremenek3e743662008-01-14 23:24:37 +0000499}
500
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000501ExplodedNode* StmtNodeBuilder::MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
Zhongxing Xu5eb08f72010-04-14 06:35:09 +0000502 ExplodedNode* Pred, const GRState* St,
503 ProgramPoint::Kind K) {
Ted Kremenekbd2c8002010-10-20 23:38:56 +0000504
Zhongxing Xu5eb08f72010-04-14 06:35:09 +0000505 ExplodedNode* N = generateNode(S, St, Pred, K);
506
507 if (N) {
508 if (BuildSinks)
509 N->markAsSink();
Ted Kremenek982b32b2010-10-20 23:48:34 +0000510 else
Zhongxing Xu5eb08f72010-04-14 06:35:09 +0000511 Dst.Add(N);
Zhongxing Xu5eb08f72010-04-14 06:35:09 +0000512 }
513
514 return N;
515}
516
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000517static ProgramPoint GetProgramPoint(const Stmt *S, ProgramPoint::Kind K,
518 const LocationContext *LC, const void *tag){
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000519 switch (K) {
520 default:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000521 assert(false && "Unhandled ProgramPoint kind");
522 case ProgramPoint::PreStmtKind:
523 return PreStmt(S, LC, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000524 case ProgramPoint::PostStmtKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000525 return PostStmt(S, LC, tag);
526 case ProgramPoint::PreLoadKind:
527 return PreLoad(S, LC, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000528 case ProgramPoint::PostLoadKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000529 return PostLoad(S, LC, tag);
530 case ProgramPoint::PreStoreKind:
531 return PreStore(S, LC, tag);
Ted Kremeneka1966182008-10-17 20:49:23 +0000532 case ProgramPoint::PostStoreKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000533 return PostStore(S, LC, tag);
Ted Kremeneka6e08322009-05-07 18:27:16 +0000534 case ProgramPoint::PostLValueKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000535 return PostLValue(S, LC, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000536 case ProgramPoint::PostPurgeDeadSymbolsKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000537 return PostPurgeDeadSymbols(S, LC, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000538 }
539}
540
Zhongxing Xu20227f72009-08-06 01:32:16 +0000541ExplodedNode*
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000542StmtNodeBuilder::generateNodeInternal(const Stmt* S, const GRState* state,
Zhongxing Xu20227f72009-08-06 01:32:16 +0000543 ExplodedNode* Pred,
Ted Kremenekdf240002009-04-11 00:11:10 +0000544 ProgramPoint::Kind K,
545 const void *tag) {
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000546
Zhongxing Xud2ab38e2009-12-23 08:54:57 +0000547 const ProgramPoint &L = GetProgramPoint(S, K, Pred->getLocationContext(),tag);
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000548 return generateNodeInternal(L, state, Pred);
Ted Kremenek513f0b12009-02-19 23:45:28 +0000549}
550
Zhongxing Xu20227f72009-08-06 01:32:16 +0000551ExplodedNode*
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000552StmtNodeBuilder::generateNodeInternal(const ProgramPoint &Loc,
Zhongxing Xuc90a0c22009-08-06 06:28:40 +0000553 const GRState* State,
Zhongxing Xu20227f72009-08-06 01:32:16 +0000554 ExplodedNode* Pred) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000555 bool IsNew;
Zhongxing Xuc90a0c22009-08-06 06:28:40 +0000556 ExplodedNode* N = Eng.G->getNode(Loc, State, &IsNew);
Ted Kremenekc3661de2009-10-07 00:42:52 +0000557 N->addPredecessor(Pred, *Eng.G);
Ted Kremenek3e743662008-01-14 23:24:37 +0000558 Deferred.erase(Pred);
Mike Stump11289f42009-09-09 15:08:12 +0000559
Ted Kremenek3e743662008-01-14 23:24:37 +0000560 if (IsNew) {
561 Deferred.insert(N);
Ted Kremenek3e743662008-01-14 23:24:37 +0000562 return N;
563 }
Mike Stump11289f42009-09-09 15:08:12 +0000564
Mike Stump11289f42009-09-09 15:08:12 +0000565 return NULL;
Ted Kremenek3e743662008-01-14 23:24:37 +0000566}
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000567
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000568ExplodedNode* BranchNodeBuilder::generateNode(const GRState* State,
Zhongxing Xu107f7592009-08-06 12:48:26 +0000569 bool branch) {
Mike Stump11289f42009-09-09 15:08:12 +0000570
Ted Kremenekaf9f3622009-07-20 18:44:36 +0000571 // If the branch has been marked infeasible we should not generate a node.
572 if (!isFeasible(branch))
573 return NULL;
Mike Stump11289f42009-09-09 15:08:12 +0000574
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000575 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000576
Zhongxing Xu20227f72009-08-06 01:32:16 +0000577 ExplodedNode* Succ =
Zhongxing Xue1190f72009-08-15 03:17:38 +0000578 Eng.G->getNode(BlockEdge(Src,branch ? DstT:DstF,Pred->getLocationContext()),
579 State, &IsNew);
Mike Stump11289f42009-09-09 15:08:12 +0000580
Ted Kremenekc3661de2009-10-07 00:42:52 +0000581 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000582
Ted Kremenekaf9f3622009-07-20 18:44:36 +0000583 if (branch)
584 GeneratedTrue = true;
585 else
Mike Stump11289f42009-09-09 15:08:12 +0000586 GeneratedFalse = true;
587
Ted Kremeneka50d9852008-01-30 23:03:39 +0000588 if (IsNew) {
Ted Kremenek2531fce2008-01-30 23:24:39 +0000589 Deferred.push_back(Succ);
Ted Kremeneka50d9852008-01-30 23:03:39 +0000590 return Succ;
591 }
Mike Stump11289f42009-09-09 15:08:12 +0000592
Ted Kremeneka50d9852008-01-30 23:03:39 +0000593 return NULL;
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000594}
Ted Kremenek7ff18932008-01-29 23:32:35 +0000595
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000596BranchNodeBuilder::~BranchNodeBuilder() {
Zhongxing Xu107f7592009-08-06 12:48:26 +0000597 if (!GeneratedTrue) generateNode(Pred->State, true);
598 if (!GeneratedFalse) generateNode(Pred->State, false);
Mike Stump11289f42009-09-09 15:08:12 +0000599
Ted Kremenek2531fce2008-01-30 23:24:39 +0000600 for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000601 if (!(*I)->isSink()) Eng.WList->Enqueue(*I);
Ted Kremenek7ff18932008-01-29 23:32:35 +0000602}
Ted Kremenek7022efb2008-02-13 00:24:44 +0000603
Ted Kremenek7022efb2008-02-13 00:24:44 +0000604
Zhongxing Xu20227f72009-08-06 01:32:16 +0000605ExplodedNode*
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000606IndirectGotoNodeBuilder::generateNode(const iterator& I, const GRState* St,
Zhongxing Xu107f7592009-08-06 12:48:26 +0000607 bool isSink) {
Ted Kremenek7022efb2008-02-13 00:24:44 +0000608 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000609
610 ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
Zhongxing Xue1190f72009-08-15 03:17:38 +0000611 Pred->getLocationContext()), St, &IsNew);
Mike Stump11289f42009-09-09 15:08:12 +0000612
Ted Kremenekc3661de2009-10-07 00:42:52 +0000613 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000614
Ted Kremenek7022efb2008-02-13 00:24:44 +0000615 if (IsNew) {
Mike Stump11289f42009-09-09 15:08:12 +0000616
Ted Kremenek7022efb2008-02-13 00:24:44 +0000617 if (isSink)
618 Succ->markAsSink();
619 else
620 Eng.WList->Enqueue(Succ);
Mike Stump11289f42009-09-09 15:08:12 +0000621
Ted Kremenek7022efb2008-02-13 00:24:44 +0000622 return Succ;
623 }
Mike Stump11289f42009-09-09 15:08:12 +0000624
Ted Kremenek7022efb2008-02-13 00:24:44 +0000625 return NULL;
626}
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000627
628
Zhongxing Xu20227f72009-08-06 01:32:16 +0000629ExplodedNode*
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000630SwitchNodeBuilder::generateCaseStmtNode(const iterator& I, const GRState* St){
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000631
632 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000633
Zhongxing Xue1190f72009-08-15 03:17:38 +0000634 ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
635 Pred->getLocationContext()), St, &IsNew);
Ted Kremenekc3661de2009-10-07 00:42:52 +0000636 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000637
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000638 if (IsNew) {
639 Eng.WList->Enqueue(Succ);
640 return Succ;
641 }
Mike Stump11289f42009-09-09 15:08:12 +0000642
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000643 return NULL;
644}
645
646
Zhongxing Xu20227f72009-08-06 01:32:16 +0000647ExplodedNode*
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000648SwitchNodeBuilder::generateDefaultCaseNode(const GRState* St, bool isSink) {
Mike Stump11289f42009-09-09 15:08:12 +0000649
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000650 // Get the block for the default case.
651 assert (Src->succ_rbegin() != Src->succ_rend());
652 CFGBlock* DefaultBlock = *Src->succ_rbegin();
Mike Stump11289f42009-09-09 15:08:12 +0000653
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000654 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000655
Zhongxing Xue1190f72009-08-15 03:17:38 +0000656 ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, DefaultBlock,
657 Pred->getLocationContext()), St, &IsNew);
Ted Kremenekc3661de2009-10-07 00:42:52 +0000658 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000659
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000660 if (IsNew) {
661 if (isSink)
662 Succ->markAsSink();
663 else
664 Eng.WList->Enqueue(Succ);
Mike Stump11289f42009-09-09 15:08:12 +0000665
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000666 return Succ;
667 }
Mike Stump11289f42009-09-09 15:08:12 +0000668
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000669 return NULL;
670}
Ted Kremenek811c2b42008-04-11 22:03:04 +0000671
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000672EndPathNodeBuilder::~EndPathNodeBuilder() {
Ted Kremenek811c2b42008-04-11 22:03:04 +0000673 // Auto-generate an EOP node if one has not been generated.
Douglas Gregora2fbc942010-02-25 19:01:53 +0000674 if (!HasGeneratedNode) {
675 // If we are in an inlined call, generate CallExit node.
676 if (Pred->getLocationContext()->getParent())
677 GenerateCallExitNode(Pred->State);
678 else
679 generateNode(Pred->State);
680 }
Ted Kremenek811c2b42008-04-11 22:03:04 +0000681}
682
Zhongxing Xu20227f72009-08-06 01:32:16 +0000683ExplodedNode*
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000684EndPathNodeBuilder::generateNode(const GRState* State, const void *tag,
Zhongxing Xu107f7592009-08-06 12:48:26 +0000685 ExplodedNode* P) {
Mike Stump11289f42009-09-09 15:08:12 +0000686 HasGeneratedNode = true;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000687 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000688
689 ExplodedNode* Node = Eng.G->getNode(BlockEntrance(&B,
Zhongxing Xue1190f72009-08-15 03:17:38 +0000690 Pred->getLocationContext(), tag), State, &IsNew);
Mike Stump11289f42009-09-09 15:08:12 +0000691
Ted Kremenekc3661de2009-10-07 00:42:52 +0000692 Node->addPredecessor(P ? P : Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000693
Ted Kremenek811c2b42008-04-11 22:03:04 +0000694 if (IsNew) {
Ted Kremenek811c2b42008-04-11 22:03:04 +0000695 Eng.G->addEndOfPath(Node);
Ted Kremenekd004c412008-04-18 16:30:14 +0000696 return Node;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000697 }
Mike Stump11289f42009-09-09 15:08:12 +0000698
Ted Kremenekd004c412008-04-18 16:30:14 +0000699 return NULL;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000700}
Douglas Gregora2fbc942010-02-25 19:01:53 +0000701
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000702void EndPathNodeBuilder::GenerateCallExitNode(const GRState *state) {
Douglas Gregora2fbc942010-02-25 19:01:53 +0000703 HasGeneratedNode = true;
704 // Create a CallExit node and enqueue it.
705 const StackFrameContext *LocCtx
706 = cast<StackFrameContext>(Pred->getLocationContext());
707 const Stmt *CE = LocCtx->getCallSite();
708
709 // Use the the callee location context.
710 CallExit Loc(CE, LocCtx);
711
712 bool isNew;
713 ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew);
714 Node->addPredecessor(Pred, *Eng.G);
715
716 if (isNew)
717 Eng.WList->Enqueue(Node);
718}
719
720
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000721void CallEnterNodeBuilder::generateNode(const GRState *state) {
Zhongxing Xu84f65e02010-07-19 01:31:21 +0000722 // Check if the callee is in the same translation unit.
723 if (CalleeCtx->getTranslationUnit() !=
724 Pred->getLocationContext()->getTranslationUnit()) {
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000725 // Create a new engine. We must be careful that the new engine should not
726 // reference data structures owned by the old engine.
727
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000728 AnalysisManager &OldMgr = Eng.SubEng.getAnalysisManager();
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000729
730 // Get the callee's translation unit.
731 idx::TranslationUnit *TU = CalleeCtx->getTranslationUnit();
732
733 // Create a new AnalysisManager with components of the callee's
734 // TranslationUnit.
Sebastian Redld44cd6a2010-08-18 23:57:06 +0000735 // The Diagnostic is actually shared when we create ASTUnits from AST files.
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000736 AnalysisManager AMgr(TU->getASTContext(), TU->getDiagnostic(),
737 OldMgr.getLangOptions(),
738 OldMgr.getPathDiagnosticClient(),
739 OldMgr.getStoreManagerCreator(),
740 OldMgr.getConstraintManagerCreator(),
741 OldMgr.getIndexer(),
Tom Carec88ed952010-09-14 21:35:27 +0000742 OldMgr.getMaxNodes(), OldMgr.getMaxVisit(),
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000743 OldMgr.shouldVisualizeGraphviz(),
744 OldMgr.shouldVisualizeUbigraph(),
745 OldMgr.shouldPurgeDead(),
746 OldMgr.shouldEagerlyAssume(),
747 OldMgr.shouldTrimGraph(),
Ted Kremenek4a2b2372010-08-03 00:09:51 +0000748 OldMgr.shouldInlineCall(),
Marcin Swiderski99a90402010-09-30 07:41:24 +0000749 OldMgr.getAnalysisContextManager().getUseUnoptimizedCFG(),
750 OldMgr.getAnalysisContextManager().getAddImplicitDtors(),
751 OldMgr.getAnalysisContextManager().getAddInitializers());
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000752 llvm::OwningPtr<TransferFuncs> TF(MakeCFRefCountTF(AMgr.getASTContext(),
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000753 /* GCEnabled */ false,
754 AMgr.getLangOptions()));
755 // Create the new engine.
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000756 ExprEngine NewEng(AMgr, TF.take());
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000757
758 // Create the new LocationContext.
759 AnalysisContext *NewAnaCtx = AMgr.getAnalysisContext(CalleeCtx->getDecl(),
760 CalleeCtx->getTranslationUnit());
Zhongxing Xucb298022010-11-24 08:53:20 +0000761 const StackFrameContext *OldLocCtx = CalleeCtx;
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000762 const StackFrameContext *NewLocCtx = AMgr.getStackFrame(NewAnaCtx,
763 OldLocCtx->getParent(),
Ted Kremenek8219b822010-12-16 07:46:53 +0000764 OldLocCtx->getCallSite(),
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000765 OldLocCtx->getCallSiteBlock(),
766 OldLocCtx->getIndex());
767
768 // Now create an initial state for the new engine.
769 const GRState *NewState = NewEng.getStateManager().MarshalState(state,
770 NewLocCtx);
771 ExplodedNodeSet ReturnNodes;
772 NewEng.ExecuteWorkListWithInitialState(NewLocCtx, AMgr.getMaxNodes(),
773 NewState, ReturnNodes);
774 return;
Zhongxing Xu84f65e02010-07-19 01:31:21 +0000775 }
776
Douglas Gregora2fbc942010-02-25 19:01:53 +0000777 // Get the callee entry block.
Zhongxing Xucb298022010-11-24 08:53:20 +0000778 const CFGBlock *Entry = &(CalleeCtx->getCFG()->getEntry());
Douglas Gregora2fbc942010-02-25 19:01:53 +0000779 assert(Entry->empty());
780 assert(Entry->succ_size() == 1);
781
782 // Get the solitary successor.
783 const CFGBlock *SuccB = *(Entry->succ_begin());
784
785 // Construct an edge representing the starting location in the callee.
Zhongxing Xucb298022010-11-24 08:53:20 +0000786 BlockEdge Loc(Entry, SuccB, CalleeCtx);
Douglas Gregora2fbc942010-02-25 19:01:53 +0000787
788 bool isNew;
789 ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew);
790 Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G);
791
792 if (isNew)
793 Eng.WList->Enqueue(Node);
794}
795
Argyrios Kyrtzidis1696f502010-12-22 18:53:44 +0000796void CallExitNodeBuilder::generateNode(const GRState *state) {
Douglas Gregora2fbc942010-02-25 19:01:53 +0000797 // Get the callee's location context.
798 const StackFrameContext *LocCtx
799 = cast<StackFrameContext>(Pred->getLocationContext());
Zhongxing Xu2cf9b132010-11-20 08:17:16 +0000800 // When exiting an implicit automatic obj dtor call, the callsite is the Stmt
801 // that triggers the dtor.
Douglas Gregora2fbc942010-02-25 19:01:53 +0000802 PostStmt Loc(LocCtx->getCallSite(), LocCtx->getParent());
803 bool isNew;
804 ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew);
805 Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G);
806 if (isNew)
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000807 Eng.WList->Enqueue(Node, LocCtx->getCallSiteBlock(),
Douglas Gregora2fbc942010-02-25 19:01:53 +0000808 LocCtx->getIndex() + 1);
809}