blob: 536c9b33ba48ac081100546aca1005b5968a3123 [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 Kremenek3e743662008-01-14 23:24:37 +000039namespace {
Kovarththanan Rajaratnam65c65662009-11-28 06:07:30 +000040class DFS : public GRWorkList {
Ted Kremenek3e743662008-01-14 23:24:37 +000041 llvm::SmallVector<GRWorkListUnit,20> Stack;
42public:
43 virtual bool hasWork() const {
44 return !Stack.empty();
45 }
46
47 virtual void Enqueue(const GRWorkListUnit& U) {
48 Stack.push_back(U);
49 }
50
51 virtual GRWorkListUnit Dequeue() {
52 assert (!Stack.empty());
53 const GRWorkListUnit& U = Stack.back();
54 Stack.pop_back(); // This technically "invalidates" U, but we are fine.
55 return U;
56 }
57};
Mike Stump11289f42009-09-09 15:08:12 +000058
Kovarththanan Rajaratnam65c65662009-11-28 06:07:30 +000059class BFS : public GRWorkList {
Ted Kremenek2c327732009-05-01 22:18:46 +000060 std::queue<GRWorkListUnit> Queue;
61public:
62 virtual bool hasWork() const {
63 return !Queue.empty();
64 }
Mike Stump11289f42009-09-09 15:08:12 +000065
Ted Kremenek2c327732009-05-01 22:18:46 +000066 virtual void Enqueue(const GRWorkListUnit& U) {
67 Queue.push(U);
68 }
Mike Stump11289f42009-09-09 15:08:12 +000069
Ted Kremenek2c327732009-05-01 22:18:46 +000070 virtual GRWorkListUnit Dequeue() {
71 // Don't use const reference. The subsequent pop_back() might make it
72 // unsafe.
Mike Stump11289f42009-09-09 15:08:12 +000073 GRWorkListUnit U = Queue.front();
Ted Kremenek2c327732009-05-01 22:18:46 +000074 Queue.pop();
75 return U;
76 }
77};
Mike Stump11289f42009-09-09 15:08:12 +000078
Ted Kremenek3e743662008-01-14 23:24:37 +000079} // end anonymous namespace
80
Ted Kremenek2e12c2e2008-01-16 18:18:48 +000081// Place the dstor for GRWorkList here because it contains virtual member
82// functions, and we the code for the dstor generated in one compilation unit.
83GRWorkList::~GRWorkList() {}
84
Ted Kremenek2c327732009-05-01 22:18:46 +000085GRWorkList *GRWorkList::MakeDFS() { return new DFS(); }
86GRWorkList *GRWorkList::MakeBFS() { return new BFS(); }
Ted Kremenek3e743662008-01-14 23:24:37 +000087
Ted Kremenekd9de9f12008-12-16 22:13:33 +000088namespace {
Kovarththanan Rajaratnam65c65662009-11-28 06:07:30 +000089 class BFSBlockDFSContents : public GRWorkList {
Ted Kremenekd9de9f12008-12-16 22:13:33 +000090 std::queue<GRWorkListUnit> Queue;
91 llvm::SmallVector<GRWorkListUnit,20> Stack;
92 public:
93 virtual bool hasWork() const {
94 return !Queue.empty() || !Stack.empty();
95 }
Mike Stump11289f42009-09-09 15:08:12 +000096
Ted Kremenekd9de9f12008-12-16 22:13:33 +000097 virtual void Enqueue(const GRWorkListUnit& U) {
98 if (isa<BlockEntrance>(U.getNode()->getLocation()))
99 Queue.push(U);
100 else
101 Stack.push_back(U);
102 }
Mike Stump11289f42009-09-09 15:08:12 +0000103
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000104 virtual GRWorkListUnit Dequeue() {
105 // Process all basic blocks to completion.
106 if (!Stack.empty()) {
107 const GRWorkListUnit& U = Stack.back();
108 Stack.pop_back(); // This technically "invalidates" U, but we are fine.
109 return U;
110 }
Mike Stump11289f42009-09-09 15:08:12 +0000111
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000112 assert(!Queue.empty());
113 // Don't use const reference. The subsequent pop_back() might make it
114 // unsafe.
Mike Stump11289f42009-09-09 15:08:12 +0000115 GRWorkListUnit U = Queue.front();
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000116 Queue.pop();
Mike Stump11289f42009-09-09 15:08:12 +0000117 return U;
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000118 }
119 };
120} // end anonymous namespace
121
122GRWorkList* GRWorkList::MakeBFSBlockDFSContents() {
123 return new BFSBlockDFSContents();
124}
125
126//===----------------------------------------------------------------------===//
127// Core analysis engine.
128//===----------------------------------------------------------------------===//
Douglas Gregora2fbc942010-02-25 19:01:53 +0000129
Ted Kremenek3e743662008-01-14 23:24:37 +0000130/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000131bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
132 const GRState *InitState) {
Mike Stump11289f42009-09-09 15:08:12 +0000133
Ted Kremenek3e743662008-01-14 23:24:37 +0000134 if (G->num_roots() == 0) { // Initialize the analysis by constructing
135 // the root if none exists.
Mike Stump11289f42009-09-09 15:08:12 +0000136
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000137 const CFGBlock* Entry = &(L->getCFG()->getEntry());
Mike Stump11289f42009-09-09 15:08:12 +0000138
139 assert (Entry->empty() &&
Ted Kremenek3e743662008-01-14 23:24:37 +0000140 "Entry block must be empty.");
Mike Stump11289f42009-09-09 15:08:12 +0000141
Ted Kremenek3e743662008-01-14 23:24:37 +0000142 assert (Entry->succ_size() == 1 &&
143 "Entry block must have 1 successor.");
Mike Stump11289f42009-09-09 15:08:12 +0000144
Ted Kremenek3e743662008-01-14 23:24:37 +0000145 // Get the solitary successor.
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000146 const CFGBlock* Succ = *(Entry->succ_begin());
Mike Stump11289f42009-09-09 15:08:12 +0000147
Ted Kremenek3e743662008-01-14 23:24:37 +0000148 // Construct an edge representing the
149 // starting location in the function.
Zhongxing Xue1190f72009-08-15 03:17:38 +0000150 BlockEdge StartLoc(Entry, Succ, L);
Mike Stump11289f42009-09-09 15:08:12 +0000151
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000152 // Set the current block counter to being empty.
153 WList->setBlockCounter(BCounterFactory.GetEmptyCounter());
Mike Stump11289f42009-09-09 15:08:12 +0000154
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000155 if (!InitState)
156 // Generate the root.
157 GenerateNode(StartLoc, getInitialState(L), 0);
158 else
159 GenerateNode(StartLoc, InitState, 0);
Ted Kremenek3e743662008-01-14 23:24:37 +0000160 }
Mike Stump11289f42009-09-09 15:08:12 +0000161
Tom Care472205b2010-09-29 23:48:13 +0000162 // Check if we have a steps limit
163 bool UnlimitedSteps = Steps == 0;
164
165 while (WList->hasWork()) {
166 if (!UnlimitedSteps) {
167 if (Steps == 0)
168 break;
169 --Steps;
170 }
171
Ted Kremenek3e743662008-01-14 23:24:37 +0000172 const GRWorkListUnit& WU = WList->Dequeue();
Mike Stump11289f42009-09-09 15:08:12 +0000173
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000174 // Set the current block counter.
175 WList->setBlockCounter(WU.getBlockCounter());
176
177 // Retrieve the node.
Zhongxing Xu20227f72009-08-06 01:32:16 +0000178 ExplodedNode* Node = WU.getNode();
Mike Stump11289f42009-09-09 15:08:12 +0000179
Ted Kremenek3e743662008-01-14 23:24:37 +0000180 // Dispatch on the location type.
181 switch (Node->getLocation().getKind()) {
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000182 case ProgramPoint::BlockEdgeKind:
Ted Kremenek3e743662008-01-14 23:24:37 +0000183 HandleBlockEdge(cast<BlockEdge>(Node->getLocation()), Node);
184 break;
Mike Stump11289f42009-09-09 15:08:12 +0000185
Ted Kremenek3e743662008-01-14 23:24:37 +0000186 case ProgramPoint::BlockEntranceKind:
187 HandleBlockEntrance(cast<BlockEntrance>(Node->getLocation()), Node);
188 break;
Mike Stump11289f42009-09-09 15:08:12 +0000189
Ted Kremenek3e743662008-01-14 23:24:37 +0000190 case ProgramPoint::BlockExitKind:
Ted Kremeneke5843592008-01-15 00:24:08 +0000191 assert (false && "BlockExit location never occur in forward analysis.");
Ted Kremenek3e743662008-01-14 23:24:37 +0000192 break;
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000193
Douglas Gregora2fbc942010-02-25 19:01:53 +0000194 case ProgramPoint::CallEnterKind:
195 HandleCallEnter(cast<CallEnter>(Node->getLocation()), WU.getBlock(),
196 WU.getIndex(), Node);
197 break;
198
199 case ProgramPoint::CallExitKind:
200 HandleCallExit(cast<CallExit>(Node->getLocation()), Node);
201 break;
202
Ted Kremenekd9de9f12008-12-16 22:13:33 +0000203 default:
204 assert(isa<PostStmt>(Node->getLocation()));
Ted Kremenek3e743662008-01-14 23:24:37 +0000205 HandlePostStmt(cast<PostStmt>(Node->getLocation()), WU.getBlock(),
206 WU.getIndex(), Node);
Mike Stump11289f42009-09-09 15:08:12 +0000207 break;
Ted Kremenek3e743662008-01-14 23:24:37 +0000208 }
209 }
Mike Stump11289f42009-09-09 15:08:12 +0000210
Ted Kremenek2b4adff2010-08-11 00:03:02 +0000211 SubEngine.ProcessEndWorklist(hasWorkRemaining());
Ted Kremenek3e743662008-01-14 23:24:37 +0000212 return WList->hasWork();
213}
214
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000215void GRCoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L,
216 unsigned Steps,
217 const GRState *InitState,
218 ExplodedNodeSet &Dst) {
219 ExecuteWorkList(L, Steps, InitState);
220 for (llvm::SmallVectorImpl<ExplodedNode*>::iterator I = G->EndNodes.begin(),
221 E = G->EndNodes.end(); I != E; ++I) {
222 Dst.Add(*I);
223 }
224}
225
Douglas Gregora2fbc942010-02-25 19:01:53 +0000226void GRCoreEngine::HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
227 unsigned Index, ExplodedNode *Pred) {
Zhongxing Xu84f65e02010-07-19 01:31:21 +0000228 GRCallEnterNodeBuilder Builder(*this, Pred, L.getCallExpr(),
229 L.getCalleeContext(), Block, Index);
Douglas Gregora2fbc942010-02-25 19:01:53 +0000230 ProcessCallEnter(Builder);
231}
232
233void GRCoreEngine::HandleCallExit(const CallExit &L, ExplodedNode *Pred) {
234 GRCallExitNodeBuilder Builder(*this, Pred);
235 ProcessCallExit(Builder);
236}
Zhongxing Xu82003da2009-08-06 10:00:15 +0000237
238void GRCoreEngine::HandleBlockEdge(const BlockEdge& L, ExplodedNode* Pred) {
Mike Stump11289f42009-09-09 15:08:12 +0000239
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000240 const CFGBlock* Blk = L.getDst();
Mike Stump11289f42009-09-09 15:08:12 +0000241
242 // Check if we are entering the EXIT block.
Zhongxing Xud2ab38e2009-12-23 08:54:57 +0000243 if (Blk == &(L.getLocationContext()->getCFG()->getExit())) {
Mike Stump11289f42009-09-09 15:08:12 +0000244
Zhongxing Xud2ab38e2009-12-23 08:54:57 +0000245 assert (L.getLocationContext()->getCFG()->getExit().size() == 0
Ted Kremenek997d8722008-01-29 00:33:40 +0000246 && "EXIT block cannot contain Stmts.");
Ted Kremenek3e743662008-01-14 23:24:37 +0000247
Ted Kremenek811c2b42008-04-11 22:03:04 +0000248 // Process the final state transition.
Zhongxing Xu107f7592009-08-06 12:48:26 +0000249 GREndPathNodeBuilder Builder(Blk, Pred, this);
Ted Kremenek811c2b42008-04-11 22:03:04 +0000250 ProcessEndPath(Builder);
Ted Kremenek3e743662008-01-14 23:24:37 +0000251
Ted Kremenek3e743662008-01-14 23:24:37 +0000252 // This path is done. Don't enqueue any more nodes.
253 return;
254 }
Ted Kremenek17f4dbd2008-02-29 20:27:50 +0000255
256 // FIXME: Should we allow ProcessBlockEntrance to also manipulate state?
Mike Stump11289f42009-09-09 15:08:12 +0000257
Zhongxing Xu3c0c81a2010-03-23 05:05:02 +0000258 if (ProcessBlockEntrance(Blk, Pred, WList->getBlockCounter()))
Ted Kremenek090d62e2010-06-29 21:58:54 +0000259 GenerateNode(BlockEntrance(Blk, Pred->getLocationContext()),
260 Pred->State, Pred);
Ted Kremenek2b4adff2010-08-11 00:03:02 +0000261 else {
262 blocksAborted.push_back(std::make_pair(L, Pred));
263 }
Ted Kremenek3e743662008-01-14 23:24:37 +0000264}
265
Zhongxing Xu82003da2009-08-06 10:00:15 +0000266void GRCoreEngine::HandleBlockEntrance(const BlockEntrance& L,
Zhongxing Xu107f7592009-08-06 12:48:26 +0000267 ExplodedNode* Pred) {
Mike Stump11289f42009-09-09 15:08:12 +0000268
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000269 // Increment the block counter.
270 GRBlockCounter Counter = WList->getBlockCounter();
Zhongxing Xu3c0c81a2010-03-23 05:05:02 +0000271 Counter = BCounterFactory.IncrementCount(Counter,
272 Pred->getLocationContext()->getCurrentStackFrame(),
273 L.getBlock()->getBlockID());
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000274 WList->setBlockCounter(Counter);
Mike Stump11289f42009-09-09 15:08:12 +0000275
276 // Process the entrance of the block.
Ted Kremenek4cad5fc2009-12-16 03:18:58 +0000277 if (CFGElement E = L.getFirstElement()) {
Mike Stump11289f42009-09-09 15:08:12 +0000278 GRStmtNodeBuilder Builder(L.getBlock(), 0, Pred, this,
Zhongxing Xu107f7592009-08-06 12:48:26 +0000279 SubEngine.getStateManager());
Ted Kremenek4cad5fc2009-12-16 03:18:58 +0000280 ProcessStmt(E, Builder);
Ted Kremenek3e743662008-01-14 23:24:37 +0000281 }
Mike Stump11289f42009-09-09 15:08:12 +0000282 else
Ted Kremeneke5843592008-01-15 00:24:08 +0000283 HandleBlockExit(L.getBlock(), Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000284}
285
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000286void GRCoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode* Pred) {
Mike Stump11289f42009-09-09 15:08:12 +0000287
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000288 if (const Stmt* Term = B->getTerminator()) {
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000289 switch (Term->getStmtClass()) {
290 default:
291 assert(false && "Analysis for this terminator not implemented.");
292 break;
Mike Stump11289f42009-09-09 15:08:12 +0000293
Ted Kremenek822f7372008-02-12 21:51:20 +0000294 case Stmt::BinaryOperatorClass: // '&&' and '||'
295 HandleBranch(cast<BinaryOperator>(Term)->getLHS(), Term, B, Pred);
296 return;
Mike Stump11289f42009-09-09 15:08:12 +0000297
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000298 case Stmt::ConditionalOperatorClass:
299 HandleBranch(cast<ConditionalOperator>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000300 return;
Mike Stump11289f42009-09-09 15:08:12 +0000301
Ted Kremenek822f7372008-02-12 21:51:20 +0000302 // FIXME: Use constant-folding in CFG construction to simplify this
303 // case.
Mike Stump11289f42009-09-09 15:08:12 +0000304
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000305 case Stmt::ChooseExprClass:
306 HandleBranch(cast<ChooseExpr>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000307 return;
Mike Stump11289f42009-09-09 15:08:12 +0000308
Ted Kremenek822f7372008-02-12 21:51:20 +0000309 case Stmt::DoStmtClass:
310 HandleBranch(cast<DoStmt>(Term)->getCond(), Term, B, Pred);
311 return;
Mike Stump11289f42009-09-09 15:08:12 +0000312
Ted Kremenek822f7372008-02-12 21:51:20 +0000313 case Stmt::ForStmtClass:
314 HandleBranch(cast<ForStmt>(Term)->getCond(), Term, B, Pred);
315 return;
Mike Stump11289f42009-09-09 15:08:12 +0000316
Ted Kremenek632bcb82008-02-13 16:56:51 +0000317 case Stmt::ContinueStmtClass:
318 case Stmt::BreakStmtClass:
Mike Stump11289f42009-09-09 15:08:12 +0000319 case Stmt::GotoStmtClass:
Ted Kremenek3f2f1ad2008-02-05 00:26:40 +0000320 break;
Mike Stump11289f42009-09-09 15:08:12 +0000321
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000322 case Stmt::IfStmtClass:
323 HandleBranch(cast<IfStmt>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000324 return;
Mike Stump11289f42009-09-09 15:08:12 +0000325
Ted Kremenek7022efb2008-02-13 00:24:44 +0000326 case Stmt::IndirectGotoStmtClass: {
327 // Only 1 successor: the indirect goto dispatch block.
328 assert (B->succ_size() == 1);
Mike Stump11289f42009-09-09 15:08:12 +0000329
Zhongxing Xu107f7592009-08-06 12:48:26 +0000330 GRIndirectGotoNodeBuilder
Ted Kremenek7022efb2008-02-13 00:24:44 +0000331 builder(Pred, B, cast<IndirectGotoStmt>(Term)->getTarget(),
332 *(B->succ_begin()), this);
Mike Stump11289f42009-09-09 15:08:12 +0000333
Ted Kremenek7022efb2008-02-13 00:24:44 +0000334 ProcessIndirectGoto(builder);
335 return;
336 }
Mike Stump11289f42009-09-09 15:08:12 +0000337
Ted Kremenek17810802008-11-12 19:24:17 +0000338 case Stmt::ObjCForCollectionStmtClass: {
339 // In the case of ObjCForCollectionStmt, it appears twice in a CFG:
340 //
341 // (1) inside a basic block, which represents the binding of the
342 // 'element' variable to a value.
343 // (2) in a terminator, which represents the branch.
344 //
345 // For (1), subengines will bind a value (i.e., 0 or 1) indicating
346 // whether or not collection contains any more elements. We cannot
347 // just test to see if the element is nil because a container can
348 // contain nil elements.
349 HandleBranch(Term, Term, B, Pred);
350 return;
351 }
Mike Stump11289f42009-09-09 15:08:12 +0000352
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000353 case Stmt::SwitchStmtClass: {
Zhongxing Xu107f7592009-08-06 12:48:26 +0000354 GRSwitchNodeBuilder builder(Pred, B, cast<SwitchStmt>(Term)->getCond(),
355 this);
Mike Stump11289f42009-09-09 15:08:12 +0000356
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000357 ProcessSwitch(builder);
358 return;
359 }
Mike Stump11289f42009-09-09 15:08:12 +0000360
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000361 case Stmt::WhileStmtClass:
362 HandleBranch(cast<WhileStmt>(Term)->getCond(), Term, B, Pred);
Ted Kremenek822f7372008-02-12 21:51:20 +0000363 return;
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000364 }
365 }
Ted Kremenek822f7372008-02-12 21:51:20 +0000366
367 assert (B->succ_size() == 1 &&
368 "Blocks with no terminator should have at most 1 successor.");
Mike Stump11289f42009-09-09 15:08:12 +0000369
370 GenerateNode(BlockEdge(B, *(B->succ_begin()), Pred->getLocationContext()),
Zhongxing Xue1190f72009-08-15 03:17:38 +0000371 Pred->State, Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000372}
373
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000374void GRCoreEngine::HandleBranch(const Stmt* Cond, const Stmt* Term,
375 const CFGBlock * B, ExplodedNode* Pred) {
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000376 assert (B->succ_size() == 2);
377
Zhongxing Xu107f7592009-08-06 12:48:26 +0000378 GRBranchNodeBuilder Builder(B, *(B->succ_begin()), *(B->succ_begin()+1),
379 Pred, this);
Mike Stump11289f42009-09-09 15:08:12 +0000380
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000381 ProcessBranch(Cond, Term, Builder);
382}
383
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000384void GRCoreEngine::HandlePostStmt(const PostStmt& L, const CFGBlock* B,
Zhongxing Xu20227f72009-08-06 01:32:16 +0000385 unsigned StmtIdx, ExplodedNode* Pred) {
Mike Stump11289f42009-09-09 15:08:12 +0000386
Ted Kremenek3e743662008-01-14 23:24:37 +0000387 assert (!B->empty());
388
Ted Kremeneke5843592008-01-15 00:24:08 +0000389 if (StmtIdx == B->size())
390 HandleBlockExit(B, Pred);
Ted Kremenek3e743662008-01-14 23:24:37 +0000391 else {
Mike Stump11289f42009-09-09 15:08:12 +0000392 GRStmtNodeBuilder Builder(B, StmtIdx, Pred, this,
Zhongxing Xu107f7592009-08-06 12:48:26 +0000393 SubEngine.getStateManager());
Ted Kremeneke914bb82008-01-16 22:13:19 +0000394 ProcessStmt((*B)[StmtIdx], Builder);
Ted Kremenek3e743662008-01-14 23:24:37 +0000395 }
396}
397
Ted Kremenek3e743662008-01-14 23:24:37 +0000398/// GenerateNode - Utility method to generate nodes, hook up successors,
399/// and add nodes to the worklist.
Mike Stump11289f42009-09-09 15:08:12 +0000400void GRCoreEngine::GenerateNode(const ProgramPoint& Loc,
Zhongxing Xu82003da2009-08-06 10:00:15 +0000401 const GRState* State, ExplodedNode* Pred) {
Mike Stump11289f42009-09-09 15:08:12 +0000402
Ted Kremenek3e743662008-01-14 23:24:37 +0000403 bool IsNew;
Zhongxing Xuc90a0c22009-08-06 06:28:40 +0000404 ExplodedNode* Node = G->getNode(Loc, State, &IsNew);
Mike Stump11289f42009-09-09 15:08:12 +0000405
406 if (Pred)
Ted Kremenekc3661de2009-10-07 00:42:52 +0000407 Node->addPredecessor(Pred, *G); // Link 'Node' with its predecessor.
Ted Kremenek3e743662008-01-14 23:24:37 +0000408 else {
409 assert (IsNew);
410 G->addRoot(Node); // 'Node' has no predecessor. Make it a root.
411 }
Mike Stump11289f42009-09-09 15:08:12 +0000412
Ted Kremenek3e743662008-01-14 23:24:37 +0000413 // Only add 'Node' to the worklist if it was freshly generated.
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000414 if (IsNew) WList->Enqueue(Node);
Ted Kremenek3e743662008-01-14 23:24:37 +0000415}
416
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000417GRStmtNodeBuilder::GRStmtNodeBuilder(const CFGBlock* b, unsigned idx,
Zhongxing Xu107f7592009-08-06 12:48:26 +0000418 ExplodedNode* N, GRCoreEngine* e,
419 GRStateManager &mgr)
Ted Kremenek982b32b2010-10-20 23:48:34 +0000420 : Eng(*e), B(*b), Idx(idx), Pred(N), Mgr(mgr),
Zhongxing Xu107f7592009-08-06 12:48:26 +0000421 PurgingDeadSymbols(false), BuildSinks(false), HasGeneratedNode(false),
422 PointKind(ProgramPoint::PostStmtKind), Tag(0) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000423 Deferred.insert(N);
Zhongxing Xud041bc62010-02-26 02:38:09 +0000424 CleanedState = Pred->getState();
Ted Kremenek3e743662008-01-14 23:24:37 +0000425}
426
Zhongxing Xu107f7592009-08-06 12:48:26 +0000427GRStmtNodeBuilder::~GRStmtNodeBuilder() {
Ted Kremenek3e743662008-01-14 23:24:37 +0000428 for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
Ted Kremeneka50d9852008-01-30 23:03:39 +0000429 if (!(*I)->isSink())
Ted Kremenek3e743662008-01-14 23:24:37 +0000430 GenerateAutoTransition(*I);
431}
432
Zhongxing Xu107f7592009-08-06 12:48:26 +0000433void GRStmtNodeBuilder::GenerateAutoTransition(ExplodedNode* N) {
Ted Kremeneka50d9852008-01-30 23:03:39 +0000434 assert (!N->isSink());
Mike Stump11289f42009-09-09 15:08:12 +0000435
Douglas Gregora2fbc942010-02-25 19:01:53 +0000436 // Check if this node entered a callee.
437 if (isa<CallEnter>(N->getLocation())) {
438 // Still use the index of the CallExpr. It's needed to create the callee
439 // StackFrameContext.
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000440 Eng.WList->Enqueue(N, &B, Idx);
Douglas Gregora2fbc942010-02-25 19:01:53 +0000441 return;
442 }
443
Zhongxing Xue1190f72009-08-15 03:17:38 +0000444 PostStmt Loc(getStmt(), N->getLocationContext());
Mike Stump11289f42009-09-09 15:08:12 +0000445
Ted Kremenek3e743662008-01-14 23:24:37 +0000446 if (Loc == N->getLocation()) {
447 // Note: 'N' should be a fresh node because otherwise it shouldn't be
448 // a member of Deferred.
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000449 Eng.WList->Enqueue(N, &B, Idx+1);
Ted Kremenek3e743662008-01-14 23:24:37 +0000450 return;
451 }
Mike Stump11289f42009-09-09 15:08:12 +0000452
Ted Kremenek3e743662008-01-14 23:24:37 +0000453 bool IsNew;
Zhongxing Xuc90a0c22009-08-06 06:28:40 +0000454 ExplodedNode* Succ = Eng.G->getNode(Loc, N->State, &IsNew);
Ted Kremenekc3661de2009-10-07 00:42:52 +0000455 Succ->addPredecessor(N, *Eng.G);
Ted Kremenek3e743662008-01-14 23:24:37 +0000456
457 if (IsNew)
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000458 Eng.WList->Enqueue(Succ, &B, Idx+1);
Ted Kremenek3e743662008-01-14 23:24:37 +0000459}
460
Zhongxing Xuc2acbe02010-07-20 02:41:28 +0000461ExplodedNode* GRStmtNodeBuilder::MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
Zhongxing Xu5eb08f72010-04-14 06:35:09 +0000462 ExplodedNode* Pred, const GRState* St,
463 ProgramPoint::Kind K) {
Ted Kremenekbd2c8002010-10-20 23:38:56 +0000464
Zhongxing Xu5eb08f72010-04-14 06:35:09 +0000465 const GRState* PredState = GetState(Pred);
Zhongxing Xu5eb08f72010-04-14 06:35:09 +0000466 ExplodedNode* N = generateNode(S, St, Pred, K);
467
468 if (N) {
469 if (BuildSinks)
470 N->markAsSink();
Ted Kremenek982b32b2010-10-20 23:48:34 +0000471 else
Zhongxing Xu5eb08f72010-04-14 06:35:09 +0000472 Dst.Add(N);
Zhongxing Xu5eb08f72010-04-14 06:35:09 +0000473 }
474
475 return N;
476}
477
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000478static ProgramPoint GetProgramPoint(const Stmt *S, ProgramPoint::Kind K,
479 const LocationContext *LC, const void *tag){
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000480 switch (K) {
481 default:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000482 assert(false && "Unhandled ProgramPoint kind");
483 case ProgramPoint::PreStmtKind:
484 return PreStmt(S, LC, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000485 case ProgramPoint::PostStmtKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000486 return PostStmt(S, LC, tag);
487 case ProgramPoint::PreLoadKind:
488 return PreLoad(S, LC, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000489 case ProgramPoint::PostLoadKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000490 return PostLoad(S, LC, tag);
491 case ProgramPoint::PreStoreKind:
492 return PreStore(S, LC, tag);
Ted Kremeneka1966182008-10-17 20:49:23 +0000493 case ProgramPoint::PostStoreKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000494 return PostStore(S, LC, tag);
Ted Kremeneka6e08322009-05-07 18:27:16 +0000495 case ProgramPoint::PostLValueKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000496 return PostLValue(S, LC, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000497 case ProgramPoint::PostPurgeDeadSymbolsKind:
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000498 return PostPurgeDeadSymbols(S, LC, tag);
Ted Kremenek9a935fb2008-06-18 05:34:07 +0000499 }
500}
501
Zhongxing Xu20227f72009-08-06 01:32:16 +0000502ExplodedNode*
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000503GRStmtNodeBuilder::generateNodeInternal(const Stmt* S, const GRState* state,
Zhongxing Xu20227f72009-08-06 01:32:16 +0000504 ExplodedNode* Pred,
Ted Kremenekdf240002009-04-11 00:11:10 +0000505 ProgramPoint::Kind K,
506 const void *tag) {
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000507
Zhongxing Xud2ab38e2009-12-23 08:54:57 +0000508 const ProgramPoint &L = GetProgramPoint(S, K, Pred->getLocationContext(),tag);
Ted Kremenek5e1f78a2009-11-11 03:26:34 +0000509 return generateNodeInternal(L, state, Pred);
Ted Kremenek513f0b12009-02-19 23:45:28 +0000510}
511
Zhongxing Xu20227f72009-08-06 01:32:16 +0000512ExplodedNode*
Zhongxing Xu107f7592009-08-06 12:48:26 +0000513GRStmtNodeBuilder::generateNodeInternal(const ProgramPoint &Loc,
Zhongxing Xuc90a0c22009-08-06 06:28:40 +0000514 const GRState* State,
Zhongxing Xu20227f72009-08-06 01:32:16 +0000515 ExplodedNode* Pred) {
Ted Kremenek3e743662008-01-14 23:24:37 +0000516 bool IsNew;
Zhongxing Xuc90a0c22009-08-06 06:28:40 +0000517 ExplodedNode* N = Eng.G->getNode(Loc, State, &IsNew);
Ted Kremenekc3661de2009-10-07 00:42:52 +0000518 N->addPredecessor(Pred, *Eng.G);
Ted Kremenek3e743662008-01-14 23:24:37 +0000519 Deferred.erase(Pred);
Mike Stump11289f42009-09-09 15:08:12 +0000520
Ted Kremenek3e743662008-01-14 23:24:37 +0000521 if (IsNew) {
522 Deferred.insert(N);
Ted Kremenek3e743662008-01-14 23:24:37 +0000523 return N;
524 }
Mike Stump11289f42009-09-09 15:08:12 +0000525
Mike Stump11289f42009-09-09 15:08:12 +0000526 return NULL;
Ted Kremenek3e743662008-01-14 23:24:37 +0000527}
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000528
Zhongxing Xu107f7592009-08-06 12:48:26 +0000529ExplodedNode* GRBranchNodeBuilder::generateNode(const GRState* State,
530 bool branch) {
Mike Stump11289f42009-09-09 15:08:12 +0000531
Ted Kremenekaf9f3622009-07-20 18:44:36 +0000532 // If the branch has been marked infeasible we should not generate a node.
533 if (!isFeasible(branch))
534 return NULL;
Mike Stump11289f42009-09-09 15:08:12 +0000535
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000536 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000537
Zhongxing Xu20227f72009-08-06 01:32:16 +0000538 ExplodedNode* Succ =
Zhongxing Xue1190f72009-08-15 03:17:38 +0000539 Eng.G->getNode(BlockEdge(Src,branch ? DstT:DstF,Pred->getLocationContext()),
540 State, &IsNew);
Mike Stump11289f42009-09-09 15:08:12 +0000541
Ted Kremenekc3661de2009-10-07 00:42:52 +0000542 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000543
Ted Kremenekaf9f3622009-07-20 18:44:36 +0000544 if (branch)
545 GeneratedTrue = true;
546 else
Mike Stump11289f42009-09-09 15:08:12 +0000547 GeneratedFalse = true;
548
Ted Kremeneka50d9852008-01-30 23:03:39 +0000549 if (IsNew) {
Ted Kremenek2531fce2008-01-30 23:24:39 +0000550 Deferred.push_back(Succ);
Ted Kremeneka50d9852008-01-30 23:03:39 +0000551 return Succ;
552 }
Mike Stump11289f42009-09-09 15:08:12 +0000553
Ted Kremeneka50d9852008-01-30 23:03:39 +0000554 return NULL;
Ted Kremenek9b4211d2008-01-29 22:56:11 +0000555}
Ted Kremenek7ff18932008-01-29 23:32:35 +0000556
Zhongxing Xu107f7592009-08-06 12:48:26 +0000557GRBranchNodeBuilder::~GRBranchNodeBuilder() {
558 if (!GeneratedTrue) generateNode(Pred->State, true);
559 if (!GeneratedFalse) generateNode(Pred->State, false);
Mike Stump11289f42009-09-09 15:08:12 +0000560
Ted Kremenek2531fce2008-01-30 23:24:39 +0000561 for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
Ted Kremenek90ae68f2008-02-12 18:08:17 +0000562 if (!(*I)->isSink()) Eng.WList->Enqueue(*I);
Ted Kremenek7ff18932008-01-29 23:32:35 +0000563}
Ted Kremenek7022efb2008-02-13 00:24:44 +0000564
Ted Kremenek7022efb2008-02-13 00:24:44 +0000565
Zhongxing Xu20227f72009-08-06 01:32:16 +0000566ExplodedNode*
Zhongxing Xu107f7592009-08-06 12:48:26 +0000567GRIndirectGotoNodeBuilder::generateNode(const iterator& I, const GRState* St,
568 bool isSink) {
Ted Kremenek7022efb2008-02-13 00:24:44 +0000569 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000570
571 ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
Zhongxing Xue1190f72009-08-15 03:17:38 +0000572 Pred->getLocationContext()), St, &IsNew);
Mike Stump11289f42009-09-09 15:08:12 +0000573
Ted Kremenekc3661de2009-10-07 00:42:52 +0000574 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000575
Ted Kremenek7022efb2008-02-13 00:24:44 +0000576 if (IsNew) {
Mike Stump11289f42009-09-09 15:08:12 +0000577
Ted Kremenek7022efb2008-02-13 00:24:44 +0000578 if (isSink)
579 Succ->markAsSink();
580 else
581 Eng.WList->Enqueue(Succ);
Mike Stump11289f42009-09-09 15:08:12 +0000582
Ted Kremenek7022efb2008-02-13 00:24:44 +0000583 return Succ;
584 }
Mike Stump11289f42009-09-09 15:08:12 +0000585
Ted Kremenek7022efb2008-02-13 00:24:44 +0000586 return NULL;
587}
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000588
589
Zhongxing Xu20227f72009-08-06 01:32:16 +0000590ExplodedNode*
Zhongxing Xu107f7592009-08-06 12:48:26 +0000591GRSwitchNodeBuilder::generateCaseStmtNode(const iterator& I, const GRState* St){
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000592
593 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000594
Zhongxing Xue1190f72009-08-15 03:17:38 +0000595 ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
596 Pred->getLocationContext()), St, &IsNew);
Ted Kremenekc3661de2009-10-07 00:42:52 +0000597 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000598
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000599 if (IsNew) {
600 Eng.WList->Enqueue(Succ);
601 return Succ;
602 }
Mike Stump11289f42009-09-09 15:08:12 +0000603
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000604 return NULL;
605}
606
607
Zhongxing Xu20227f72009-08-06 01:32:16 +0000608ExplodedNode*
Zhongxing Xu107f7592009-08-06 12:48:26 +0000609GRSwitchNodeBuilder::generateDefaultCaseNode(const GRState* St, bool isSink) {
Mike Stump11289f42009-09-09 15:08:12 +0000610
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000611 // Get the block for the default case.
612 assert (Src->succ_rbegin() != Src->succ_rend());
613 CFGBlock* DefaultBlock = *Src->succ_rbegin();
Mike Stump11289f42009-09-09 15:08:12 +0000614
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000615 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000616
Zhongxing Xue1190f72009-08-15 03:17:38 +0000617 ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, DefaultBlock,
618 Pred->getLocationContext()), St, &IsNew);
Ted Kremenekc3661de2009-10-07 00:42:52 +0000619 Succ->addPredecessor(Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000620
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000621 if (IsNew) {
622 if (isSink)
623 Succ->markAsSink();
624 else
625 Eng.WList->Enqueue(Succ);
Mike Stump11289f42009-09-09 15:08:12 +0000626
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000627 return Succ;
628 }
Mike Stump11289f42009-09-09 15:08:12 +0000629
Ted Kremenek80ebc1d2008-02-13 23:08:21 +0000630 return NULL;
631}
Ted Kremenek811c2b42008-04-11 22:03:04 +0000632
Zhongxing Xu107f7592009-08-06 12:48:26 +0000633GREndPathNodeBuilder::~GREndPathNodeBuilder() {
Ted Kremenek811c2b42008-04-11 22:03:04 +0000634 // Auto-generate an EOP node if one has not been generated.
Douglas Gregora2fbc942010-02-25 19:01:53 +0000635 if (!HasGeneratedNode) {
636 // If we are in an inlined call, generate CallExit node.
637 if (Pred->getLocationContext()->getParent())
638 GenerateCallExitNode(Pred->State);
639 else
640 generateNode(Pred->State);
641 }
Ted Kremenek811c2b42008-04-11 22:03:04 +0000642}
643
Zhongxing Xu20227f72009-08-06 01:32:16 +0000644ExplodedNode*
Zhongxing Xu107f7592009-08-06 12:48:26 +0000645GREndPathNodeBuilder::generateNode(const GRState* State, const void *tag,
646 ExplodedNode* P) {
Mike Stump11289f42009-09-09 15:08:12 +0000647 HasGeneratedNode = true;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000648 bool IsNew;
Mike Stump11289f42009-09-09 15:08:12 +0000649
650 ExplodedNode* Node = Eng.G->getNode(BlockEntrance(&B,
Zhongxing Xue1190f72009-08-15 03:17:38 +0000651 Pred->getLocationContext(), tag), State, &IsNew);
Mike Stump11289f42009-09-09 15:08:12 +0000652
Ted Kremenekc3661de2009-10-07 00:42:52 +0000653 Node->addPredecessor(P ? P : Pred, *Eng.G);
Mike Stump11289f42009-09-09 15:08:12 +0000654
Ted Kremenek811c2b42008-04-11 22:03:04 +0000655 if (IsNew) {
Ted Kremenek811c2b42008-04-11 22:03:04 +0000656 Eng.G->addEndOfPath(Node);
Ted Kremenekd004c412008-04-18 16:30:14 +0000657 return Node;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000658 }
Mike Stump11289f42009-09-09 15:08:12 +0000659
Ted Kremenekd004c412008-04-18 16:30:14 +0000660 return NULL;
Ted Kremenek811c2b42008-04-11 22:03:04 +0000661}
Douglas Gregora2fbc942010-02-25 19:01:53 +0000662
663void GREndPathNodeBuilder::GenerateCallExitNode(const GRState *state) {
664 HasGeneratedNode = true;
665 // Create a CallExit node and enqueue it.
666 const StackFrameContext *LocCtx
667 = cast<StackFrameContext>(Pred->getLocationContext());
668 const Stmt *CE = LocCtx->getCallSite();
669
670 // Use the the callee location context.
671 CallExit Loc(CE, LocCtx);
672
673 bool isNew;
674 ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew);
675 Node->addPredecessor(Pred, *Eng.G);
676
677 if (isNew)
678 Eng.WList->Enqueue(Node);
679}
680
681
682void GRCallEnterNodeBuilder::GenerateNode(const GRState *state,
683 const LocationContext *LocCtx) {
Zhongxing Xu84f65e02010-07-19 01:31:21 +0000684 // Check if the callee is in the same translation unit.
685 if (CalleeCtx->getTranslationUnit() !=
686 Pred->getLocationContext()->getTranslationUnit()) {
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000687 // Create a new engine. We must be careful that the new engine should not
688 // reference data structures owned by the old engine.
689
690 AnalysisManager &OldMgr = Eng.SubEngine.getAnalysisManager();
691
692 // Get the callee's translation unit.
693 idx::TranslationUnit *TU = CalleeCtx->getTranslationUnit();
694
695 // Create a new AnalysisManager with components of the callee's
696 // TranslationUnit.
Sebastian Redld44cd6a2010-08-18 23:57:06 +0000697 // The Diagnostic is actually shared when we create ASTUnits from AST files.
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000698 AnalysisManager AMgr(TU->getASTContext(), TU->getDiagnostic(),
699 OldMgr.getLangOptions(),
700 OldMgr.getPathDiagnosticClient(),
701 OldMgr.getStoreManagerCreator(),
702 OldMgr.getConstraintManagerCreator(),
703 OldMgr.getIndexer(),
Tom Carec88ed952010-09-14 21:35:27 +0000704 OldMgr.getMaxNodes(), OldMgr.getMaxVisit(),
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000705 OldMgr.shouldVisualizeGraphviz(),
706 OldMgr.shouldVisualizeUbigraph(),
707 OldMgr.shouldPurgeDead(),
708 OldMgr.shouldEagerlyAssume(),
709 OldMgr.shouldTrimGraph(),
Ted Kremenek4a2b2372010-08-03 00:09:51 +0000710 OldMgr.shouldInlineCall(),
Marcin Swiderski99a90402010-09-30 07:41:24 +0000711 OldMgr.getAnalysisContextManager().getUseUnoptimizedCFG(),
712 OldMgr.getAnalysisContextManager().getAddImplicitDtors(),
713 OldMgr.getAnalysisContextManager().getAddInitializers());
Zhongxing Xuadf644d2010-07-22 13:52:13 +0000714 llvm::OwningPtr<GRTransferFuncs> TF(MakeCFRefCountTF(AMgr.getASTContext(),
715 /* GCEnabled */ false,
716 AMgr.getLangOptions()));
717 // Create the new engine.
718 GRExprEngine NewEng(AMgr, TF.take());
719
720 // Create the new LocationContext.
721 AnalysisContext *NewAnaCtx = AMgr.getAnalysisContext(CalleeCtx->getDecl(),
722 CalleeCtx->getTranslationUnit());
723 const StackFrameContext *OldLocCtx = cast<StackFrameContext>(LocCtx);
724 const StackFrameContext *NewLocCtx = AMgr.getStackFrame(NewAnaCtx,
725 OldLocCtx->getParent(),
726 OldLocCtx->getCallSite(),
727 OldLocCtx->getCallSiteBlock(),
728 OldLocCtx->getIndex());
729
730 // Now create an initial state for the new engine.
731 const GRState *NewState = NewEng.getStateManager().MarshalState(state,
732 NewLocCtx);
733 ExplodedNodeSet ReturnNodes;
734 NewEng.ExecuteWorkListWithInitialState(NewLocCtx, AMgr.getMaxNodes(),
735 NewState, ReturnNodes);
736 return;
Zhongxing Xu84f65e02010-07-19 01:31:21 +0000737 }
738
Douglas Gregora2fbc942010-02-25 19:01:53 +0000739 // Get the callee entry block.
740 const CFGBlock *Entry = &(LocCtx->getCFG()->getEntry());
741 assert(Entry->empty());
742 assert(Entry->succ_size() == 1);
743
744 // Get the solitary successor.
745 const CFGBlock *SuccB = *(Entry->succ_begin());
746
747 // Construct an edge representing the starting location in the callee.
748 BlockEdge Loc(Entry, SuccB, LocCtx);
749
750 bool isNew;
751 ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew);
752 Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G);
753
754 if (isNew)
755 Eng.WList->Enqueue(Node);
756}
757
758void GRCallExitNodeBuilder::GenerateNode(const GRState *state) {
759 // Get the callee's location context.
760 const StackFrameContext *LocCtx
761 = cast<StackFrameContext>(Pred->getLocationContext());
762
763 PostStmt Loc(LocCtx->getCallSite(), LocCtx->getParent());
764 bool isNew;
765 ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew);
766 Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G);
767 if (isNew)
Zhongxing Xuedb77fe2010-07-20 06:22:24 +0000768 Eng.WList->Enqueue(Node, LocCtx->getCallSiteBlock(),
Douglas Gregora2fbc942010-02-25 19:01:53 +0000769 LocCtx->getIndex() + 1);
770}