blob: a676e6ca26f625242e7bb40786d3c5d618ac9dbe [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
Zhongxing Xuadf644d2010-07-22 13:52:13 +000015#include "clang/Checker/PathSensitive/AnalysisManager.h"
Ted Kremenekd6b87082010-01-25 04:41:41 +000016#include "clang/Checker/PathSensitive/GRCoreEngine.h"
17#include "clang/Checker/PathSensitive/GRExprEngine.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;
28
Zhongxing Xuadf644d2010-07-22 13:52:13 +000029// This should be removed in the future.
30namespace clang {
31GRTransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
32 const LangOptions& lopts);
33}
34
Ted Kremenekd9de9f12008-12-16 22:13:33 +000035//===----------------------------------------------------------------------===//
36// Worklist classes for exploration of reachable states.
37//===----------------------------------------------------------------------===//
38
Ted Kremenekb02788d2010-11-13 05:04:49 +000039GRWorkList::Visitor::~Visitor() {}
40
Ted Kremenek3e743662008-01-14 23:24:37 +000041namespace {
Kovarththanan Rajaratnam65c65662009-11-28 06:07:30 +000042class DFS : public GRWorkList {
Ted Kremenek3e743662008-01-14 23:24:37 +000043 llvm::SmallVector<GRWorkListUnit,20> Stack;
44public:
45 virtual bool hasWork() const {
46 return !Stack.empty();
47 }
48
49 virtual void Enqueue(const GRWorkListUnit& U) {
50 Stack.push_back(U);
51 }
52
53 virtual GRWorkListUnit Dequeue() {
54 assert (!Stack.empty());
55 const GRWorkListUnit& U = Stack.back();
56 Stack.pop_back(); // This technically "invalidates" U, but we are fine.
57 return U;
58 }
Ted Kremenekb02788d2010-11-13 05:04:49 +000059
60 virtual bool VisitItemsInWorkList(Visitor &V) {
61 for (llvm::SmallVectorImpl<GRWorkListUnit>::iterator
62 I = Stack.begin(), E = Stack.end(); I != E; ++I) {
63 if (V.Visit(*I))
64 return true;
65 }
66 return false;
67 }
Ted Kremenek3e743662008-01-14 23:24:37 +000068};
Mike Stump11289f42009-09-09 15:08:12 +000069
Kovarththanan Rajaratnam65c65662009-11-28 06:07:30 +000070class BFS : public GRWorkList {
Ted Kremenekb02788d2010-11-13 05:04:49 +000071 std::deque<GRWorkListUnit> Queue;
Ted Kremenek2c327732009-05-01 22:18:46 +000072public:
73 virtual bool hasWork() const {
74 return !Queue.empty();
75 }
Mike Stump11289f42009-09-09 15:08:12 +000076
Ted Kremenek2c327732009-05-01 22:18:46 +000077 virtual void Enqueue(const GRWorkListUnit& U) {
Ted Kremenekb02788d2010-11-13 05:04:49 +000078 Queue.push_front(U);
Ted Kremenek2c327732009-05-01 22:18:46 +000079 }
Mike Stump11289f42009-09-09 15:08:12 +000080
Ted Kremenek2c327732009-05-01 22:18:46 +000081 virtual GRWorkListUnit Dequeue() {
Mike Stump11289f42009-09-09 15:08:12 +000082 GRWorkListUnit U = Queue.front();
Ted Kremenekb02788d2010-11-13 05:04:49 +000083 Queue.pop_front();
Ted Kremenek2c327732009-05-01 22:18:46 +000084 return U;
85 }
Ted Kremenekb02788d2010-11-13 05:04:49 +000086
87 virtual bool VisitItemsInWorkList(Visitor &V) {
88 for (std::deque<GRWorkListUnit>::iterator
89 I = Queue.begin(), E = Queue.end(); I != E; ++I) {
90 if (V.Visit(*I))
91 return true;
92 }
93 return false;
94 }
Ted Kremenek2c327732009-05-01 22:18:46 +000095};
Mike Stump11289f42009-09-09 15:08:12 +000096
Ted Kremenek3e743662008-01-14 23:24:37 +000097} // end anonymous namespace
98
Ted Kremenek2e12c2e2008-01-16 18:18:48 +000099// Place the dstor for GRWorkList here because it contains virtual member
100// functions, and we the code for the dstor generated in one compilation unit.
101GRWorkList::~GRWorkList() {}
102
Ted Kremenek2c327732009-05-01 22:18:46 +0000103GRWorkList *GRWorkList::MakeDFS() { return new DFS(); }
104GRWorkList *GRWorkList::MakeBFS() { return new BFS(); }
Ted Kremenek3e743662008-01-14 23:24:37 +0000105
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000106namespace {
Kovarththanan Rajaratnam65c65662009-11-28 06:07:30 +0000107 class BFSBlockDFSContents : public GRWorkList {
Ted Kremenekb02788d2010-11-13 05:04:49 +0000108 std::deque<GRWorkListUnit> Queue;
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000109 llvm::SmallVector<GRWorkListUnit,20> Stack;
110 public:
111 virtual bool hasWork() const {
112 return !Queue.empty() || !Stack.empty();
113 }
Mike Stump11289f42009-09-09 15:08:12 +0000114
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000115 virtual void Enqueue(const GRWorkListUnit& U) {
116 if (isa<BlockEntrance>(U.getNode()->getLocation()))
Ted Kremenekb02788d2010-11-13 05:04:49 +0000117 Queue.push_front(U);
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000118 else
119 Stack.push_back(U);
120 }
Mike Stump11289f42009-09-09 15:08:12 +0000121
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000122 virtual GRWorkListUnit Dequeue() {
123 // Process all basic blocks to completion.
124 if (!Stack.empty()) {
125 const GRWorkListUnit& U = Stack.back();
126 Stack.pop_back(); // This technically "invalidates" U, but we are fine.
127 return U;
128 }
Mike Stump11289f42009-09-09 15:08:12 +0000129
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000130 assert(!Queue.empty());
131 // Don't use const reference. The subsequent pop_back() might make it
132 // unsafe.
Mike Stump11289f42009-09-09 15:08:12 +0000133 GRWorkListUnit U = Queue.front();
Ted Kremenekb02788d2010-11-13 05:04:49 +0000134 Queue.pop_front();
Mike Stump11289f42009-09-09 15:08:12 +0000135 return U;
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000136 }
Ted Kremenekb02788d2010-11-13 05:04:49 +0000137 virtual bool VisitItemsInWorkList(Visitor &V) {
138 for (llvm::SmallVectorImpl<GRWorkListUnit>::iterator
139 I = Stack.begin(), E = Stack.end(); I != E; ++I) {
140 if (V.Visit(*I))
141 return true;
142 }
143 for (std::deque<GRWorkListUnit>::iterator
144 I = Queue.begin(), E = Queue.end(); I != E; ++I) {
145 if (V.Visit(*I))
146 return true;
147 }
148 return false;
149 }
150
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000151 };
152} // end anonymous namespace
153
154GRWorkList* GRWorkList::MakeBFSBlockDFSContents() {
155 return new BFSBlockDFSContents();
156}
157
158//===----------------------------------------------------------------------===//
159// Core analysis engine.
160//===----------------------------------------------------------------------===//
Douglas Gregora2fbc942010-02-25 19:01:53 +0000161
Ted Kremenek3e743662008-01-14 23:24:37 +0000162/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000163bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
164 const GRState *InitState) {
Mike Stump11289f42009-09-09 15:08:12 +0000165
Ted Kremenek3e743662008-01-14 23:24:37 +0000166 if (G->num_roots() == 0) { // Initialize the analysis by constructing
167 // the root if none exists.
Mike Stump11289f42009-09-09 15:08:12 +0000168
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000169 const CFGBlock* Entry = &(L->getCFG()->getEntry());
Mike Stump11289f42009-09-09 15:08:12 +0000170
171 assert (Entry->empty() &&
Ted Kremenek3e743662008-01-14 23:24:37 +0000172 "Entry block must be empty.");
Mike Stump11289f42009-09-09 15:08:12 +0000173
Ted Kremenek3e743662008-01-14 23:24:37 +0000174 assert (Entry->succ_size() == 1 &&
175 "Entry block must have 1 successor.");
Mike Stump11289f42009-09-09 15:08:12 +0000176
Ted Kremenek3e743662008-01-14 23:24:37 +0000177 // Get the solitary successor.
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000178 const CFGBlock* Succ = *(Entry->succ_begin());
Mike Stump11289f42009-09-09 15:08:12 +0000179
Ted Kremenek3e743662008-01-14 23:24:37 +0000180 // Construct an edge representing the
181 // starting location in the function.
Zhongxing Xue1190f72009-08-15 03:17:38 +0000182 BlockEdge StartLoc(Entry, Succ, L);
Mike Stump11289f42009-09-09 15:08:12 +0000183
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000184 // Set the current block counter to being empty.
185 WList->setBlockCounter(BCounterFactory.GetEmptyCounter());
Mike Stump11289f42009-09-09 15:08:12 +0000186
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000187 if (!InitState)
188 // Generate the root.
189 GenerateNode(StartLoc, getInitialState(L), 0);
190 else
191 GenerateNode(StartLoc, InitState, 0);
Ted Kremenek3e743662008-01-14 23:24:37 +0000192 }
Mike Stump11289f42009-09-09 15:08:12 +0000193
Tom Care472205b2010-09-29 23:48:13 +0000194 // Check if we have a steps limit
195 bool UnlimitedSteps = Steps == 0;
196
197 while (WList->hasWork()) {
198 if (!UnlimitedSteps) {
199 if (Steps == 0)
200 break;
201 --Steps;
202 }
203
Ted Kremenek3e743662008-01-14 23:24:37 +0000204 const GRWorkListUnit& WU = WList->Dequeue();
Mike Stump11289f42009-09-09 15:08:12 +0000205
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000206 // Set the current block counter.
207 WList->setBlockCounter(WU.getBlockCounter());
208
209 // Retrieve the node.
Zhongxing Xu20227f72009-08-06 01:32:16 +0000210 ExplodedNode* Node = WU.getNode();
Mike Stump11289f42009-09-09 15:08:12 +0000211
Ted Kremenek3e743662008-01-14 23:24:37 +0000212 // Dispatch on the location type.
213 switch (Node->getLocation().getKind()) {
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000214 case ProgramPoint::BlockEdgeKind:
Ted Kremenek3e743662008-01-14 23:24:37 +0000215 HandleBlockEdge(cast<BlockEdge>(Node->getLocation()), Node);
216 break;
Mike Stump11289f42009-09-09 15:08:12 +0000217
Ted Kremenek3e743662008-01-14 23:24:37 +0000218 case ProgramPoint::BlockEntranceKind:
219 HandleBlockEntrance(cast<BlockEntrance>(Node->getLocation()), Node);
220 break;
Mike Stump11289f42009-09-09 15:08:12 +0000221
Ted Kremenek3e743662008-01-14 23:24:37 +0000222 case ProgramPoint::BlockExitKind:
Ted Kremeneke5843592008-01-15 00:24:08 +0000223 assert (false && "BlockExit location never occur in forward analysis.");
Ted Kremenek3e743662008-01-14 23:24:37 +0000224 break;
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000225
Douglas Gregora2fbc942010-02-25 19:01:53 +0000226 case ProgramPoint::CallEnterKind:
227 HandleCallEnter(cast<CallEnter>(Node->getLocation()), WU.getBlock(),
228 WU.getIndex(), Node);
229 break;
230
231 case ProgramPoint::CallExitKind:
232 HandleCallExit(cast<CallExit>(Node->getLocation()), Node);
233 break;
234
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000235 default:
Zhongxing Xu1ade3262010-11-16 07:52:17 +0000236 assert(isa<PostStmt>(Node->getLocation()) ||
237 isa<PostInitializer>(Node->getLocation()));
238 HandlePostStmt(WU.getBlock(), WU.getIndex(), Node);
Mike Stump11289f42009-09-09 15:08:12 +0000239 break;
Ted Kremenek3e743662008-01-14 23:24:37 +0000240 }
241 }
Mike Stump11289f42009-09-09 15:08:12 +0000242
Ted Kremenek2b4adff2010-08-11 00:03:02 +0000243 SubEngine.ProcessEndWorklist(hasWorkRemaining());
Ted Kremenek3e743662008-01-14 23:24:37 +0000244 return WList->hasWork();
245}
246
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000247void GRCoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L,
248 unsigned Steps,
249 const GRState *InitState,
250 ExplodedNodeSet &Dst) {
251 ExecuteWorkList(L, Steps, InitState);
252 for (llvm::SmallVectorImpl<ExplodedNode*>::iterator I = G->EndNodes.begin(),
253 E = G->EndNodes.end(); I != E; ++I) {
254 Dst.Add(*I);
255 }
256}
257
Douglas Gregora2fbc942010-02-25 19:01:53 +0000258void GRCoreEngine::HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
259 unsigned Index, ExplodedNode *Pred) {
Zhongxing Xu84f65e02010-07-19 01:31:21 +0000260 GRCallEnterNodeBuilder Builder(*this, Pred, L.getCallExpr(),
261 L.getCalleeContext(), Block, Index);
Douglas Gregora2fbc942010-02-25 19:01:53 +0000262 ProcessCallEnter(Builder);
263}
264
265void GRCoreEngine::HandleCallExit(const CallExit &L, ExplodedNode *Pred) {
266 GRCallExitNodeBuilder Builder(*this, Pred);
267 ProcessCallExit(Builder);
268}
Zhongxing Xu82003da2009-08-06 10:00:15 +0000269
270void GRCoreEngine::HandleBlockEdge(const BlockEdge& L, ExplodedNode* Pred) {
Mike Stump11289f42009-09-09 15:08:12 +0000271
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000272 const CFGBlock* Blk = L.getDst();
Mike Stump11289f42009-09-09 15:08:12 +0000273
274 // Check if we are entering the EXIT block.
Zhongxing Xud2ab38e2009-12-23 08:54:57 +0000275 if (Blk == &(L.getLocationContext()->getCFG()->getExit())) {
Mike Stump11289f42009-09-09 15:08:12 +0000276
Zhongxing Xud2ab38e2009-12-23 08:54:57 +0000277 assert (L.getLocationContext()->getCFG()->getExit().size() == 0
Ted Kremenek997d8722008-01-29 00:33:40 +0000278 && "EXIT block cannot contain Stmts.");
Ted Kremenek3e743662008-01-14 23:24:37 +0000279
Ted Kremenek811c2b42008-04-11 22:03:04 +0000280 // Process the final state transition.
Zhongxing Xu107f7592009-08-06 12:48:26 +0000281 GREndPathNodeBuilder Builder(Blk, Pred, this);
Ted Kremenek811c2b42008-04-11 22:03:04 +0000282 ProcessEndPath(Builder);
Ted Kremenek3e743662008-01-14 23:24:37 +0000283
Ted Kremenek3e743662008-01-14 23:24:37 +0000284 // This path is done. Don't enqueue any more nodes.
285 return;
286 }
Ted Kremenek17f4dbd2008-02-29 20:27:50 +0000287
288 // FIXME: Should we allow ProcessBlockEntrance to also manipulate state?
Mike Stump11289f42009-09-09 15:08:12 +0000289
Zhongxing Xu3c0c81a2010-03-23 05:05:02 +0000290 if (ProcessBlockEntrance(Blk, Pred, WList->getBlockCounter()))
Ted Kremenek090d62e2010-06-29 21:58:54 +0000291 GenerateNode(BlockEntrance(Blk, Pred->getLocationContext()),
292 Pred->State, Pred);
Ted Kremenek2b4adff2010-08-11 00:03:02 +0000293 else {
294 blocksAborted.push_back(std::make_pair(L, Pred));
295 }
Ted Kremenek3e743662008-01-14 23:24:37 +0000296}
297
Zhongxing Xu82003da2009-08-06 10:00:15 +0000298void GRCoreEngine::HandleBlockEntrance(const BlockEntrance& L,
Zhongxing Xu107f7592009-08-06 12:48:26 +0000299 ExplodedNode* Pred) {
Mike Stump11289f42009-09-09 15:08:12 +0000300
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000301 // Increment the block counter.
302 GRBlockCounter Counter = WList->getBlockCounter();
Zhongxing Xu3c0c81a2010-03-23 05:05:02 +0000303 Counter = BCounterFactory.IncrementCount(Counter,
304 Pred->getLocationContext()->getCurrentStackFrame(),
305 L.getBlock()->getBlockID());
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000306 WList->setBlockCounter(Counter);
Mike Stump11289f42009-09-09 15:08:12 +0000307
308 // Process the entrance of the block.
Ted Kremenek4cad5fc2009-12-16 03:18:58 +0000309 if (CFGElement E = L.getFirstElement()) {
Mike Stump11289f42009-09-09 15:08:12 +0000310 GRStmtNodeBuilder Builder(L.getBlock(), 0, Pred, this,
Zhongxing Xu107f7592009-08-06 12:48:26 +0000311 SubEngine.getStateManager());
Zhongxing Xu5d30c692010-11-15 08:48:43 +0000312 ProcessElement(E, Builder);
Ted Kremenek3e743662008-01-14 23:24:37 +0000313 }
Mike Stump11289f42009-09-09 15:08:12 +0000314 else
Ted Kremeneke5843592008-01-15 00:24:08 +0000315 HandleBlockExit(L.getBlock(), Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000316}
317
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000318void GRCoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode* Pred) {
Mike Stump11289f42009-09-09 15:08:12 +0000319
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000320 if (const Stmt* Term = B->getTerminator()) {
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000321 switch (Term->getStmtClass()) {
322 default:
323 assert(false && "Analysis for this terminator not implemented.");
324 break;
Mike Stump11289f42009-09-09 15:08:12 +0000325
Ted Kremenek822f7372008-02-12 21:51:20 +0000326 case Stmt::BinaryOperatorClass: // '&&' and '||'
327 HandleBranch(cast<BinaryOperator>(Term)->getLHS(), Term, B, Pred);
328 return;
Mike Stump11289f42009-09-09 15:08:12 +0000329
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000330 case Stmt::ConditionalOperatorClass:
331 HandleBranch(cast<ConditionalOperator>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000332 return;
Mike Stump11289f42009-09-09 15:08:12 +0000333
Ted Kremenek822f7372008-02-12 21:51:20 +0000334 // FIXME: Use constant-folding in CFG construction to simplify this
335 // case.
Mike Stump11289f42009-09-09 15:08:12 +0000336
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000337 case Stmt::ChooseExprClass:
338 HandleBranch(cast<ChooseExpr>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000339 return;
Mike Stump11289f42009-09-09 15:08:12 +0000340
Ted Kremenek822f7372008-02-12 21:51:20 +0000341 case Stmt::DoStmtClass:
342 HandleBranch(cast<DoStmt>(Term)->getCond(), Term, B, Pred);
343 return;
Mike Stump11289f42009-09-09 15:08:12 +0000344
Ted Kremenek822f7372008-02-12 21:51:20 +0000345 case Stmt::ForStmtClass:
346 HandleBranch(cast<ForStmt>(Term)->getCond(), Term, B, Pred);
347 return;
Mike Stump11289f42009-09-09 15:08:12 +0000348
Ted Kremenek632bcb82008-02-13 16:56:51 +0000349 case Stmt::ContinueStmtClass:
350 case Stmt::BreakStmtClass:
Mike Stump11289f42009-09-09 15:08:12 +0000351 case Stmt::GotoStmtClass:
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000352 break;
Mike Stump11289f42009-09-09 15:08:12 +0000353
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000354 case Stmt::IfStmtClass:
355 HandleBranch(cast<IfStmt>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000356 return;
Mike Stump11289f42009-09-09 15:08:12 +0000357
Ted Kremenek7022efb2008-02-13 00:24:44 +0000358 case Stmt::IndirectGotoStmtClass: {
359 // Only 1 successor: the indirect goto dispatch block.
360 assert (B->succ_size() == 1);
Mike Stump11289f42009-09-09 15:08:12 +0000361
Zhongxing Xu107f7592009-08-06 12:48:26 +0000362 GRIndirectGotoNodeBuilder
Ted Kremenek7022efb2008-02-13 00:24:44 +0000363 builder(Pred, B, cast<IndirectGotoStmt>(Term)->getTarget(),
364 *(B->succ_begin()), this);
Mike Stump11289f42009-09-09 15:08:12 +0000365
Ted Kremenek7022efb2008-02-13 00:24:44 +0000366 ProcessIndirectGoto(builder);
367 return;
368 }
Mike Stump11289f42009-09-09 15:08:12 +0000369
Ted Kremenek17810802008-11-12 19:24:17 +0000370 case Stmt::ObjCForCollectionStmtClass: {
371 // In the case of ObjCForCollectionStmt, it appears twice in a CFG:
372 //
373 // (1) inside a basic block, which represents the binding of the
374 // 'element' variable to a value.
375 // (2) in a terminator, which represents the branch.
376 //
377 // For (1), subengines will bind a value (i.e., 0 or 1) indicating
378 // whether or not collection contains any more elements. We cannot
379 // just test to see if the element is nil because a container can
380 // contain nil elements.
381 HandleBranch(Term, Term, B, Pred);
382 return;
383 }
Mike Stump11289f42009-09-09 15:08:12 +0000384
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000385 case Stmt::SwitchStmtClass: {
Zhongxing Xu107f7592009-08-06 12:48:26 +0000386 GRSwitchNodeBuilder builder(Pred, B, cast<SwitchStmt>(Term)->getCond(),
387 this);
Mike Stump11289f42009-09-09 15:08:12 +0000388
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000389 ProcessSwitch(builder);
390 return;
391 }
Mike Stump11289f42009-09-09 15:08:12 +0000392
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000393 case Stmt::WhileStmtClass:
394 HandleBranch(cast<WhileStmt>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000395 return;
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000396 }
397 }
Ted Kremenek822f7372008-02-12 21:51:20 +0000398
399 assert (B->succ_size() == 1 &&
400 "Blocks with no terminator should have at most 1 successor.");
Mike Stump11289f42009-09-09 15:08:12 +0000401
402 GenerateNode(BlockEdge(B, *(B->succ_begin()), Pred->getLocationContext()),
Zhongxing Xue1190f72009-08-15 03:17:38 +0000403 Pred->State, Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000404}
405
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000406void GRCoreEngine::HandleBranch(const Stmt* Cond, const Stmt* Term,
407 const CFGBlock * B, ExplodedNode* Pred) {
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000408 assert (B->succ_size() == 2);
409
Zhongxing Xu107f7592009-08-06 12:48:26 +0000410 GRBranchNodeBuilder Builder(B, *(B->succ_begin()), *(B->succ_begin()+1),
411 Pred, this);
Mike Stump11289f42009-09-09 15:08:12 +0000412
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000413 ProcessBranch(Cond, Term, Builder);
414}
415
Zhongxing Xu1ade3262010-11-16 07:52:17 +0000416void GRCoreEngine::HandlePostStmt(const CFGBlock* B, unsigned StmtIdx,
417 ExplodedNode* Pred) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000418 assert (!B->empty());
419
Ted Kremeneke5843592008-01-15 00:24:08 +0000420 if (StmtIdx == B->size())
421 HandleBlockExit(B, Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000422 else {
Mike Stump11289f42009-09-09 15:08:12 +0000423 GRStmtNodeBuilder Builder(B, StmtIdx, Pred, this,
Zhongxing Xu107f7592009-08-06 12:48:26 +0000424 SubEngine.getStateManager());
Zhongxing Xu5d30c692010-11-15 08:48:43 +0000425 ProcessElement((*B)[StmtIdx], Builder);
Ted Kremenek3e743662008-01-14 23:24:37 +0000426 }
427}
428
Ted Kremenek3e743662008-01-14 23:24:37 +0000429/// GenerateNode - Utility method to generate nodes, hook up successors,
430/// and add nodes to the worklist.
Mike Stump11289f42009-09-09 15:08:12 +0000431void GRCoreEngine::GenerateNode(const ProgramPoint& Loc,
Zhongxing Xu82003da2009-08-06 10:00:15 +0000432 const GRState* State, ExplodedNode* Pred) {
Mike Stump11289f42009-09-09 15:08:12 +0000433
Ted Kremenek3e743662008-01-14 23:24:37 +0000434 bool IsNew;
Zhongxing Xuc90a0c22009-08-06 06:28:40 +0000435 ExplodedNode* Node = G->getNode(Loc, State, &IsNew);
Mike Stump11289f42009-09-09 15:08:12 +0000436
437 if (Pred)
Ted Kremenekc3661de2009-10-07 00:42:52 +0000438 Node->addPredecessor(Pred, *G); // Link 'Node' with its predecessor.
Ted Kremenek3e743662008-01-14 23:24:37 +0000439 else {
440 assert (IsNew);
441 G->addRoot(Node); // 'Node' has no predecessor. Make it a root.
442 }
Mike Stump11289f42009-09-09 15:08:12 +0000443
Ted Kremenek3e743662008-01-14 23:24:37 +0000444 // Only add 'Node' to the worklist if it was freshly generated.
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000445 if (IsNew) WList->Enqueue(Node);
Ted Kremenek3e743662008-01-14 23:24:37 +0000446}
447
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000448GRStmtNodeBuilder::GRStmtNodeBuilder(const CFGBlock* b, unsigned idx,
Zhongxing Xu107f7592009-08-06 12:48:26 +0000449 ExplodedNode* N, GRCoreEngine* e,
450 GRStateManager &mgr)
Ted Kremenek982b32b2010-10-20 23:48:34 +0000451 : Eng(*e), B(*b), Idx(idx), Pred(N), Mgr(mgr),
Zhongxing Xu107f7592009-08-06 12:48:26 +0000452 PurgingDeadSymbols(false), BuildSinks(false), HasGeneratedNode(false),
453 PointKind(ProgramPoint::PostStmtKind), Tag(0) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000454 Deferred.insert(N);
Zhongxing Xud041bc62010-02-26 02:38:09 +0000455 CleanedState = Pred->getState();
Ted Kremenek3e743662008-01-14 23:24:37 +0000456}
457
Zhongxing Xu107f7592009-08-06 12:48:26 +0000458GRStmtNodeBuilder::~GRStmtNodeBuilder() {
Ted Kremenek3e743662008-01-14 23:24:37 +0000459 for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
Ted Kremeneka50d9852008-01-30 23:03:39 +0000460 if (!(*I)->isSink())
Ted Kremenek3e743662008-01-14 23:24:37 +0000461 GenerateAutoTransition(*I);
462}
463
Zhongxing Xu107f7592009-08-06 12:48:26 +0000464void GRStmtNodeBuilder::GenerateAutoTransition(ExplodedNode* N) {
Ted Kremeneka50d9852008-01-30 23:03:39 +0000465 assert (!N->isSink());
Mike Stump11289f42009-09-09 15:08:12 +0000466
Douglas Gregora2fbc942010-02-25 19:01:53 +0000467 // Check if this node entered a callee.
468 if (isa<CallEnter>(N->getLocation())) {
469 // Still use the index of the CallExpr. It's needed to create the callee
470 // StackFrameContext.
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000471 Eng.WList->Enqueue(N, &B, Idx);
Douglas Gregora2fbc942010-02-25 19:01:53 +0000472 return;
473 }
474
Zhongxing Xu1ade3262010-11-16 07:52:17 +0000475 // Do not create extra nodes. Move to the next CFG element.
476 if (isa<PostInitializer>(N->getLocation())) {
477 Eng.WList->Enqueue(N, &B, Idx+1);
478 return;
479 }
480
Zhongxing Xue1190f72009-08-15 03:17:38 +0000481 PostStmt Loc(getStmt(), N->getLocationContext());
Mike Stump11289f42009-09-09 15:08:12 +0000482
Ted Kremenek3e743662008-01-14 23:24:37 +0000483 if (Loc == N->getLocation()) {
484 // Note: 'N' should be a fresh node because otherwise it shouldn't be
485 // a member of Deferred.
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000486 Eng.WList->Enqueue(N, &B, Idx+1);
Ted Kremenek3e743662008-01-14 23:24:37 +0000487 return;
488 }
Mike Stump11289f42009-09-09 15:08:12 +0000489
Ted Kremenek3e743662008-01-14 23:24:37 +0000490 bool IsNew;
Zhongxing Xuc90a0c22009-08-06 06:28:40 +0000491 ExplodedNode* Succ = Eng.G->getNode(Loc, N->State, &IsNew);
Ted Kremenekc3661de2009-10-07 00:42:52 +0000492 Succ->addPredecessor(N, *Eng.G);
Ted Kremenek3e743662008-01-14 23:24:37 +0000493
494 if (IsNew)
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000495 Eng.WList->Enqueue(Succ, &B, Idx+1);
Ted Kremenek3e743662008-01-14 23:24:37 +0000496}
497
Zhongxing Xuc2acbe02010-07-20 02:41:28 +0000498ExplodedNode* GRStmtNodeBuilder::MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
Zhongxing Xu5eb08f72010-04-14 06:35:09 +0000499 ExplodedNode* Pred, const GRState* St,
500 ProgramPoint::Kind K) {
Ted Kremenekbd2c8002010-10-20 23:38:56 +0000501
Zhongxing Xu5eb08f72010-04-14 06:35:09 +0000502 ExplodedNode* N = generateNode(S, St, Pred, K);
503
504 if (N) {
505 if (BuildSinks)
506 N->markAsSink();
Ted Kremenek982b32b2010-10-20 23:48:34 +0000507 else
Zhongxing Xu5eb08f72010-04-14 06:35:09 +0000508 Dst.Add(N);
Zhongxing Xu5eb08f72010-04-14 06:35:09 +0000509 }
510
511 return N;
512}
513
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000514static ProgramPoint GetProgramPoint(const Stmt *S, ProgramPoint::Kind K,
515 const LocationContext *LC, const void *tag){
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000516 switch (K) {
517 default:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000518 assert(false && "Unhandled ProgramPoint kind");
519 case ProgramPoint::PreStmtKind:
520 return PreStmt(S, LC, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000521 case ProgramPoint::PostStmtKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000522 return PostStmt(S, LC, tag);
523 case ProgramPoint::PreLoadKind:
524 return PreLoad(S, LC, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000525 case ProgramPoint::PostLoadKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000526 return PostLoad(S, LC, tag);
527 case ProgramPoint::PreStoreKind:
528 return PreStore(S, LC, tag);
Ted Kremeneka1966182008-10-17 20:49:23 +0000529 case ProgramPoint::PostStoreKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000530 return PostStore(S, LC, tag);
Ted Kremeneka6e08322009-05-07 18:27:16 +0000531 case ProgramPoint::PostLValueKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000532 return PostLValue(S, LC, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000533 case ProgramPoint::PostPurgeDeadSymbolsKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000534 return PostPurgeDeadSymbols(S, LC, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000535 }
536}
537
Zhongxing Xu20227f72009-08-06 01:32:16 +0000538ExplodedNode*
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000539GRStmtNodeBuilder::generateNodeInternal(const Stmt* S, const GRState* state,
Zhongxing Xu20227f72009-08-06 01:32:16 +0000540 ExplodedNode* Pred,
Ted Kremenekdf240002009-04-11 00:11:10 +0000541 ProgramPoint::Kind K,
542 const void *tag) {
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000543
Zhongxing Xud2ab38e2009-12-23 08:54:57 +0000544 const ProgramPoint &L = GetProgramPoint(S, K, Pred->getLocationContext(),tag);
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000545 return generateNodeInternal(L, state, Pred);
Ted Kremenek513f0b12009-02-19 23:45:28 +0000546}
547
Zhongxing Xu20227f72009-08-06 01:32:16 +0000548ExplodedNode*
Zhongxing Xu107f7592009-08-06 12:48:26 +0000549GRStmtNodeBuilder::generateNodeInternal(const ProgramPoint &Loc,
Zhongxing Xuc90a0c22009-08-06 06:28:40 +0000550 const GRState* State,
Zhongxing Xu20227f72009-08-06 01:32:16 +0000551 ExplodedNode* Pred) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000552 bool IsNew;
Zhongxing Xuc90a0c22009-08-06 06:28:40 +0000553 ExplodedNode* N = Eng.G->getNode(Loc, State, &IsNew);
Ted Kremenekc3661de2009-10-07 00:42:52 +0000554 N->addPredecessor(Pred, *Eng.G);
Ted Kremenek3e743662008-01-14 23:24:37 +0000555 Deferred.erase(Pred);
Mike Stump11289f42009-09-09 15:08:12 +0000556
Ted Kremenek3e743662008-01-14 23:24:37 +0000557 if (IsNew) {
558 Deferred.insert(N);
Ted Kremenek3e743662008-01-14 23:24:37 +0000559 return N;
560 }
Mike Stump11289f42009-09-09 15:08:12 +0000561
Mike Stump11289f42009-09-09 15:08:12 +0000562 return NULL;
Ted Kremenek3e743662008-01-14 23:24:37 +0000563}
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000564
Zhongxing Xu107f7592009-08-06 12:48:26 +0000565ExplodedNode* GRBranchNodeBuilder::generateNode(const GRState* State,
566 bool branch) {
Mike Stump11289f42009-09-09 15:08:12 +0000567
Ted Kremenekaf9f3622009-07-20 18:44:36 +0000568 // If the branch has been marked infeasible we should not generate a node.
569 if (!isFeasible(branch))
570 return NULL;
Mike Stump11289f42009-09-09 15:08:12 +0000571
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000572 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000573
Zhongxing Xu20227f72009-08-06 01:32:16 +0000574 ExplodedNode* Succ =
Zhongxing Xue1190f72009-08-15 03:17:38 +0000575 Eng.G->getNode(BlockEdge(Src,branch ? DstT:DstF,Pred->getLocationContext()),
576 State, &IsNew);
Mike Stump11289f42009-09-09 15:08:12 +0000577
Ted Kremenekc3661de2009-10-07 00:42:52 +0000578 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000579
Ted Kremenekaf9f3622009-07-20 18:44:36 +0000580 if (branch)
581 GeneratedTrue = true;
582 else
Mike Stump11289f42009-09-09 15:08:12 +0000583 GeneratedFalse = true;
584
Ted Kremeneka50d9852008-01-30 23:03:39 +0000585 if (IsNew) {
Ted Kremenek2531fce2008-01-30 23:24:39 +0000586 Deferred.push_back(Succ);
Ted Kremeneka50d9852008-01-30 23:03:39 +0000587 return Succ;
588 }
Mike Stump11289f42009-09-09 15:08:12 +0000589
Ted Kremeneka50d9852008-01-30 23:03:39 +0000590 return NULL;
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000591}
Ted Kremenek7ff18932008-01-29 23:32:35 +0000592
Zhongxing Xu107f7592009-08-06 12:48:26 +0000593GRBranchNodeBuilder::~GRBranchNodeBuilder() {
594 if (!GeneratedTrue) generateNode(Pred->State, true);
595 if (!GeneratedFalse) generateNode(Pred->State, false);
Mike Stump11289f42009-09-09 15:08:12 +0000596
Ted Kremenek2531fce2008-01-30 23:24:39 +0000597 for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000598 if (!(*I)->isSink()) Eng.WList->Enqueue(*I);
Ted Kremenek7ff18932008-01-29 23:32:35 +0000599}
Ted Kremenek7022efb2008-02-13 00:24:44 +0000600
Ted Kremenek7022efb2008-02-13 00:24:44 +0000601
Zhongxing Xu20227f72009-08-06 01:32:16 +0000602ExplodedNode*
Zhongxing Xu107f7592009-08-06 12:48:26 +0000603GRIndirectGotoNodeBuilder::generateNode(const iterator& I, const GRState* St,
604 bool isSink) {
Ted Kremenek7022efb2008-02-13 00:24:44 +0000605 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000606
607 ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
Zhongxing Xue1190f72009-08-15 03:17:38 +0000608 Pred->getLocationContext()), St, &IsNew);
Mike Stump11289f42009-09-09 15:08:12 +0000609
Ted Kremenekc3661de2009-10-07 00:42:52 +0000610 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000611
Ted Kremenek7022efb2008-02-13 00:24:44 +0000612 if (IsNew) {
Mike Stump11289f42009-09-09 15:08:12 +0000613
Ted Kremenek7022efb2008-02-13 00:24:44 +0000614 if (isSink)
615 Succ->markAsSink();
616 else
617 Eng.WList->Enqueue(Succ);
Mike Stump11289f42009-09-09 15:08:12 +0000618
Ted Kremenek7022efb2008-02-13 00:24:44 +0000619 return Succ;
620 }
Mike Stump11289f42009-09-09 15:08:12 +0000621
Ted Kremenek7022efb2008-02-13 00:24:44 +0000622 return NULL;
623}
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000624
625
Zhongxing Xu20227f72009-08-06 01:32:16 +0000626ExplodedNode*
Zhongxing Xu107f7592009-08-06 12:48:26 +0000627GRSwitchNodeBuilder::generateCaseStmtNode(const iterator& I, const GRState* St){
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000628
629 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000630
Zhongxing Xue1190f72009-08-15 03:17:38 +0000631 ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
632 Pred->getLocationContext()), St, &IsNew);
Ted Kremenekc3661de2009-10-07 00:42:52 +0000633 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000634
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000635 if (IsNew) {
636 Eng.WList->Enqueue(Succ);
637 return Succ;
638 }
Mike Stump11289f42009-09-09 15:08:12 +0000639
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000640 return NULL;
641}
642
643
Zhongxing Xu20227f72009-08-06 01:32:16 +0000644ExplodedNode*
Zhongxing Xu107f7592009-08-06 12:48:26 +0000645GRSwitchNodeBuilder::generateDefaultCaseNode(const GRState* St, bool isSink) {
Mike Stump11289f42009-09-09 15:08:12 +0000646
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000647 // Get the block for the default case.
648 assert (Src->succ_rbegin() != Src->succ_rend());
649 CFGBlock* DefaultBlock = *Src->succ_rbegin();
Mike Stump11289f42009-09-09 15:08:12 +0000650
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000651 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000652
Zhongxing Xue1190f72009-08-15 03:17:38 +0000653 ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, DefaultBlock,
654 Pred->getLocationContext()), St, &IsNew);
Ted Kremenekc3661de2009-10-07 00:42:52 +0000655 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000656
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000657 if (IsNew) {
658 if (isSink)
659 Succ->markAsSink();
660 else
661 Eng.WList->Enqueue(Succ);
Mike Stump11289f42009-09-09 15:08:12 +0000662
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000663 return Succ;
664 }
Mike Stump11289f42009-09-09 15:08:12 +0000665
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000666 return NULL;
667}
Ted Kremenek811c2b42008-04-11 22:03:04 +0000668
Zhongxing Xu107f7592009-08-06 12:48:26 +0000669GREndPathNodeBuilder::~GREndPathNodeBuilder() {
Ted Kremenek811c2b42008-04-11 22:03:04 +0000670 // Auto-generate an EOP node if one has not been generated.
Douglas Gregora2fbc942010-02-25 19:01:53 +0000671 if (!HasGeneratedNode) {
672 // If we are in an inlined call, generate CallExit node.
673 if (Pred->getLocationContext()->getParent())
674 GenerateCallExitNode(Pred->State);
675 else
676 generateNode(Pred->State);
677 }
Ted Kremenek811c2b42008-04-11 22:03:04 +0000678}
679
Zhongxing Xu20227f72009-08-06 01:32:16 +0000680ExplodedNode*
Zhongxing Xu107f7592009-08-06 12:48:26 +0000681GREndPathNodeBuilder::generateNode(const GRState* State, const void *tag,
682 ExplodedNode* P) {
Mike Stump11289f42009-09-09 15:08:12 +0000683 HasGeneratedNode = true;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000684 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000685
686 ExplodedNode* Node = Eng.G->getNode(BlockEntrance(&B,
Zhongxing Xue1190f72009-08-15 03:17:38 +0000687 Pred->getLocationContext(), tag), State, &IsNew);
Mike Stump11289f42009-09-09 15:08:12 +0000688
Ted Kremenekc3661de2009-10-07 00:42:52 +0000689 Node->addPredecessor(P ? P : Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000690
Ted Kremenek811c2b42008-04-11 22:03:04 +0000691 if (IsNew) {
Ted Kremenek811c2b42008-04-11 22:03:04 +0000692 Eng.G->addEndOfPath(Node);
Ted Kremenekd004c412008-04-18 16:30:14 +0000693 return Node;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000694 }
Mike Stump11289f42009-09-09 15:08:12 +0000695
Ted Kremenekd004c412008-04-18 16:30:14 +0000696 return NULL;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000697}
Douglas Gregora2fbc942010-02-25 19:01:53 +0000698
699void GREndPathNodeBuilder::GenerateCallExitNode(const GRState *state) {
700 HasGeneratedNode = true;
701 // Create a CallExit node and enqueue it.
702 const StackFrameContext *LocCtx
703 = cast<StackFrameContext>(Pred->getLocationContext());
704 const Stmt *CE = LocCtx->getCallSite();
705
706 // Use the the callee location context.
707 CallExit Loc(CE, LocCtx);
708
709 bool isNew;
710 ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew);
711 Node->addPredecessor(Pred, *Eng.G);
712
713 if (isNew)
714 Eng.WList->Enqueue(Node);
715}
716
717
Zhongxing Xucb298022010-11-24 08:53:20 +0000718void GRCallEnterNodeBuilder::GenerateNode(const GRState *state) {
Zhongxing Xu84f65e02010-07-19 01:31:21 +0000719 // Check if the callee is in the same translation unit.
720 if (CalleeCtx->getTranslationUnit() !=
721 Pred->getLocationContext()->getTranslationUnit()) {
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000722 // Create a new engine. We must be careful that the new engine should not
723 // reference data structures owned by the old engine.
724
725 AnalysisManager &OldMgr = Eng.SubEngine.getAnalysisManager();
726
727 // Get the callee's translation unit.
728 idx::TranslationUnit *TU = CalleeCtx->getTranslationUnit();
729
730 // Create a new AnalysisManager with components of the callee's
731 // TranslationUnit.
Sebastian Redld44cd6a2010-08-18 23:57:06 +0000732 // The Diagnostic is actually shared when we create ASTUnits from AST files.
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000733 AnalysisManager AMgr(TU->getASTContext(), TU->getDiagnostic(),
734 OldMgr.getLangOptions(),
735 OldMgr.getPathDiagnosticClient(),
736 OldMgr.getStoreManagerCreator(),
737 OldMgr.getConstraintManagerCreator(),
738 OldMgr.getIndexer(),
Tom Carec88ed952010-09-14 21:35:27 +0000739 OldMgr.getMaxNodes(), OldMgr.getMaxVisit(),
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000740 OldMgr.shouldVisualizeGraphviz(),
741 OldMgr.shouldVisualizeUbigraph(),
742 OldMgr.shouldPurgeDead(),
743 OldMgr.shouldEagerlyAssume(),
744 OldMgr.shouldTrimGraph(),
Ted Kremenek4a2b2372010-08-03 00:09:51 +0000745 OldMgr.shouldInlineCall(),
Marcin Swiderski99a90402010-09-30 07:41:24 +0000746 OldMgr.getAnalysisContextManager().getUseUnoptimizedCFG(),
747 OldMgr.getAnalysisContextManager().getAddImplicitDtors(),
748 OldMgr.getAnalysisContextManager().getAddInitializers());
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000749 llvm::OwningPtr<GRTransferFuncs> TF(MakeCFRefCountTF(AMgr.getASTContext(),
750 /* GCEnabled */ false,
751 AMgr.getLangOptions()));
752 // Create the new engine.
753 GRExprEngine NewEng(AMgr, TF.take());
754
755 // Create the new LocationContext.
756 AnalysisContext *NewAnaCtx = AMgr.getAnalysisContext(CalleeCtx->getDecl(),
757 CalleeCtx->getTranslationUnit());
Zhongxing Xucb298022010-11-24 08:53:20 +0000758 const StackFrameContext *OldLocCtx = CalleeCtx;
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000759 const StackFrameContext *NewLocCtx = AMgr.getStackFrame(NewAnaCtx,
760 OldLocCtx->getParent(),
Zhongxing Xua1a9ba12010-11-24 13:08:51 +0000761 OldLocCtx->getCallSite(), false,
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000762 OldLocCtx->getCallSiteBlock(),
763 OldLocCtx->getIndex());
764
765 // Now create an initial state for the new engine.
766 const GRState *NewState = NewEng.getStateManager().MarshalState(state,
767 NewLocCtx);
768 ExplodedNodeSet ReturnNodes;
769 NewEng.ExecuteWorkListWithInitialState(NewLocCtx, AMgr.getMaxNodes(),
770 NewState, ReturnNodes);
771 return;
Zhongxing Xu84f65e02010-07-19 01:31:21 +0000772 }
773
Douglas Gregora2fbc942010-02-25 19:01:53 +0000774 // Get the callee entry block.
Zhongxing Xucb298022010-11-24 08:53:20 +0000775 const CFGBlock *Entry = &(CalleeCtx->getCFG()->getEntry());
Douglas Gregora2fbc942010-02-25 19:01:53 +0000776 assert(Entry->empty());
777 assert(Entry->succ_size() == 1);
778
779 // Get the solitary successor.
780 const CFGBlock *SuccB = *(Entry->succ_begin());
781
782 // Construct an edge representing the starting location in the callee.
Zhongxing Xucb298022010-11-24 08:53:20 +0000783 BlockEdge Loc(Entry, SuccB, CalleeCtx);
Douglas Gregora2fbc942010-02-25 19:01:53 +0000784
785 bool isNew;
786 ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew);
787 Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G);
788
789 if (isNew)
790 Eng.WList->Enqueue(Node);
791}
792
793void GRCallExitNodeBuilder::GenerateNode(const GRState *state) {
794 // Get the callee's location context.
795 const StackFrameContext *LocCtx
796 = cast<StackFrameContext>(Pred->getLocationContext());
Zhongxing Xu2cf9b132010-11-20 08:17:16 +0000797 // When exiting an implicit automatic obj dtor call, the callsite is the Stmt
798 // that triggers the dtor.
Douglas Gregora2fbc942010-02-25 19:01:53 +0000799 PostStmt Loc(LocCtx->getCallSite(), LocCtx->getParent());
800 bool isNew;
801 ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew);
802 Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G);
803 if (isNew)
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000804 Eng.WList->Enqueue(Node, LocCtx->getCallSiteBlock(),
Douglas Gregora2fbc942010-02-25 19:01:53 +0000805 LocCtx->getIndex() + 1);
806}