CoreEngine.h revision a7a8a450d908b34fa5f569f2e694ebd4b61aae2f
12bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian//==- GRCoreEngine.h - Path-Sensitive Dataflow Engine --------------*- C++ -*-//
22bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian//
32bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian//                     The LLVM Compiler Infrastructure
42bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian//
52bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian// This file is distributed under the University of Illinois Open Source
62bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian// License. See LICENSE.TXT for details.
72bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian//
82bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian//===----------------------------------------------------------------------===//
92bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian//
102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian//  This file defines a generic engine for intraprocedural, path-sensitive,
112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian//  dataflow analysis via graph reachability.
122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian//
132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian//===----------------------------------------------------------------------===//
142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifndef LLVM_CLANG_ANALYSIS_GRENGINE
162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#define LLVM_CLANG_ANALYSIS_GRENGINE
172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "clang/AST/Expr.h"
192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "clang/Checker/PathSensitive/ExplodedGraph.h"
202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "clang/Checker/PathSensitive/GRWorkList.h"
212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "clang/Checker/PathSensitive/GRBlockCounter.h"
222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "clang/Checker/PathSensitive/GRAuditor.h"
232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "clang/Checker/PathSensitive/GRSubEngine.h"
242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "llvm/ADT/OwningPtr.h"
252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramaniannamespace clang {
272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian//===----------------------------------------------------------------------===//
292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/// GRCoreEngine - Implements the core logic of the graph-reachability
302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian///   analysis. It traverses the CFG and generates the ExplodedGraph.
312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian///   Program "states" are treated as opaque void pointers.
322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian///   The template class GRCoreEngine (which subclasses GRCoreEngine)
332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian///   provides the matching component to the engine that knows the actual types
342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian///   for states.  Note that this engine only dispatches to transfer functions
352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian///   at the statement and block-level.  The analyses themselves must implement
362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian///   any transfer function logic and the sub-expression level (if any).
372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianclass GRCoreEngine {
382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  friend class GRStmtNodeBuilder;
392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  friend class GRBranchNodeBuilder;
402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  friend class GRIndirectGotoNodeBuilder;
412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  friend class GRSwitchNodeBuilder;
422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  friend class GREndPathNodeBuilder;
432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  friend class GRCallEnterNodeBuilder;
442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  friend class GRCallExitNodeBuilder;
452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianpublic:
472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> >
482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            BlocksAborted;
492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianprivate:
502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  GRSubEngine& SubEngine;
522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  /// G - The simulation graph.  Each node is a (location,state) pair.
542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  llvm::OwningPtr<ExplodedGraph> G;
552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  /// WList - A set of queued nodes that need to be processed by the
572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  ///  worklist algorithm.  It is up to the implementation of WList to decide
582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  ///  the order that nodes are processed.
592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  GRWorkList* WList;
602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  /// BCounterFactory - A factory object for created GRBlockCounter objects.
622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  ///   These are used to record for key nodes in the ExplodedGraph the
632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  ///   number of times different CFGBlocks have been visited along a path.
642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  GRBlockCounter::Factory BCounterFactory;
652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  /// The locations where we stopped doing work because we visited a location
672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  ///  too many times.
682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  BlocksAborted blocksAborted;
692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  void GenerateNode(const ProgramPoint& Loc, const GRState* State,
712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                    ExplodedNode* Pred);
722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  void HandleBlockEdge(const BlockEdge& E, ExplodedNode* Pred);
742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  void HandleBlockEntrance(const BlockEntrance& E, ExplodedNode* Pred);
752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  void HandleBlockExit(const CFGBlock* B, ExplodedNode* Pred);
762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  void HandlePostStmt(const PostStmt& S, const CFGBlock* B,
772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                      unsigned StmtIdx, ExplodedNode *Pred);
782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  void HandleBranch(const Stmt* Cond, const Stmt* Term, const CFGBlock* B,
802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                    ExplodedNode* Pred);
812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  void HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                       unsigned Index, ExplodedNode *Pred);
832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  void HandleCallExit(const CallExit &L, ExplodedNode *Pred);
842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  /// Get the initial state from the subengine.
862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  const GRState* getInitialState(const LocationContext *InitLoc) {
872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    return SubEngine.getInitialState(InitLoc);
882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  }
892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  void ProcessEndPath(GREndPathNodeBuilder& Builder) {
912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    SubEngine.ProcessEndPath(Builder);
922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  }
932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  void ProcessStmt(const CFGElement E, GRStmtNodeBuilder& Builder) {
952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    SubEngine.ProcessStmt(E, Builder);
962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  }
972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  bool ProcessBlockEntrance(const CFGBlock* Blk, const ExplodedNode *Pred,
992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                            GRBlockCounter BC) {
1002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    return SubEngine.ProcessBlockEntrance(Blk, Pred, BC);
1012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  }
102
103
104  void ProcessBranch(const Stmt* Condition, const Stmt* Terminator,
105                     GRBranchNodeBuilder& Builder) {
106    SubEngine.ProcessBranch(Condition, Terminator, Builder);
107  }
108
109
110  void ProcessIndirectGoto(GRIndirectGotoNodeBuilder& Builder) {
111    SubEngine.ProcessIndirectGoto(Builder);
112  }
113
114
115  void ProcessSwitch(GRSwitchNodeBuilder& Builder) {
116    SubEngine.ProcessSwitch(Builder);
117  }
118
119  void ProcessCallEnter(GRCallEnterNodeBuilder &Builder) {
120    SubEngine.ProcessCallEnter(Builder);
121  }
122
123  void ProcessCallExit(GRCallExitNodeBuilder &Builder) {
124    SubEngine.ProcessCallExit(Builder);
125  }
126
127private:
128  GRCoreEngine(const GRCoreEngine&); // Do not implement.
129  GRCoreEngine& operator=(const GRCoreEngine&);
130
131public:
132  /// Construct a GRCoreEngine object to analyze the provided CFG using
133  ///  a DFS exploration of the exploded graph.
134  GRCoreEngine(GRSubEngine& subengine)
135    : SubEngine(subengine), G(new ExplodedGraph()),
136      WList(GRWorkList::MakeBFS()),
137      BCounterFactory(G->getAllocator()) {}
138
139  /// Construct a GRCoreEngine object to analyze the provided CFG and to
140  ///  use the provided worklist object to execute the worklist algorithm.
141  ///  The GRCoreEngine object assumes ownership of 'wlist'.
142  GRCoreEngine(GRWorkList* wlist, GRSubEngine& subengine)
143    : SubEngine(subengine), G(new ExplodedGraph()), WList(wlist),
144      BCounterFactory(G->getAllocator()) {}
145
146  ~GRCoreEngine() {
147    delete WList;
148  }
149
150  /// getGraph - Returns the exploded graph.
151  ExplodedGraph& getGraph() { return *G.get(); }
152
153  /// takeGraph - Returns the exploded graph.  Ownership of the graph is
154  ///  transfered to the caller.
155  ExplodedGraph* takeGraph() { return G.take(); }
156
157  /// ExecuteWorkList - Run the worklist algorithm for a maximum number of
158  ///  steps.  Returns true if there is still simulation state on the worklist.
159  bool ExecuteWorkList(const LocationContext *L, unsigned Steps,
160                       const GRState *InitState);
161  void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
162                                       const GRState *InitState,
163                                       ExplodedNodeSet &Dst);
164
165  // Functions for external checking of whether we have unfinished work
166  bool wasBlockAborted() const { return !blocksAborted.empty(); }
167  bool hasWorkRemaining() const { return wasBlockAborted() || WList->hasWork(); }
168
169  GRWorkList *getWorkList() const { return WList; }
170
171  BlocksAborted::const_iterator blocks_aborted_begin() const {
172    return blocksAborted.begin();
173  }
174  BlocksAborted::const_iterator blocks_aborted_end() const {
175    return blocksAborted.end();
176  }
177};
178
179class GRStmtNodeBuilder {
180  GRCoreEngine& Eng;
181  const CFGBlock& B;
182  const unsigned Idx;
183  ExplodedNode* Pred;
184  GRStateManager& Mgr;
185  GRAuditor* Auditor;
186
187public:
188  bool PurgingDeadSymbols;
189  bool BuildSinks;
190  bool HasGeneratedNode;
191  ProgramPoint::Kind PointKind;
192  const void *Tag;
193
194  const GRState* CleanedState;
195
196
197  typedef llvm::SmallPtrSet<ExplodedNode*,5> DeferredTy;
198  DeferredTy Deferred;
199
200  void GenerateAutoTransition(ExplodedNode* N);
201
202public:
203  GRStmtNodeBuilder(const CFGBlock* b, unsigned idx, ExplodedNode* N,
204                    GRCoreEngine* e, GRStateManager &mgr);
205
206  ~GRStmtNodeBuilder();
207
208  ExplodedNode* getBasePredecessor() const { return Pred; }
209
210  // FIXME: This should not be exposed.
211  GRWorkList *getWorkList() { return Eng.WList; }
212
213  void SetCleanedState(const GRState* St) {
214    CleanedState = St;
215  }
216
217  GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
218
219  unsigned getCurrentBlockCount() const {
220    return getBlockCounter().getNumVisited(
221                            Pred->getLocationContext()->getCurrentStackFrame(),
222                                           B.getBlockID());
223  }
224
225  ExplodedNode* generateNode(PostStmt PP,const GRState* St,ExplodedNode* Pred) {
226    HasGeneratedNode = true;
227    return generateNodeInternal(PP, St, Pred);
228  }
229
230  ExplodedNode* generateNode(const Stmt *S, const GRState *St,
231                             ExplodedNode *Pred, ProgramPoint::Kind K) {
232    HasGeneratedNode = true;
233
234    if (PurgingDeadSymbols)
235      K = ProgramPoint::PostPurgeDeadSymbolsKind;
236
237    return generateNodeInternal(S, St, Pred, K, Tag);
238  }
239
240  ExplodedNode* generateNode(const Stmt *S, const GRState *St,
241                             ExplodedNode *Pred) {
242    return generateNode(S, St, Pred, PointKind);
243  }
244
245  ExplodedNode *generateNode(const ProgramPoint &PP, const GRState* State,
246                             ExplodedNode* Pred) {
247    HasGeneratedNode = true;
248    return generateNodeInternal(PP, State, Pred);
249  }
250
251  ExplodedNode*
252  generateNodeInternal(const ProgramPoint &PP, const GRState* State,
253                       ExplodedNode* Pred);
254
255  ExplodedNode*
256  generateNodeInternal(const Stmt* S, const GRState* State, ExplodedNode* Pred,
257                   ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
258                   const void *tag = 0);
259
260  /// getStmt - Return the current block-level expression associated with
261  ///  this builder.
262  const Stmt* getStmt() const { return B[Idx]; }
263
264  /// getBlock - Return the CFGBlock associated with the block-level expression
265  ///  of this builder.
266  const CFGBlock* getBlock() const { return &B; }
267
268  unsigned getIndex() const { return Idx; }
269
270  void setAuditor(GRAuditor* A) { Auditor = A; }
271
272  const GRState* GetState(ExplodedNode* Pred) const {
273    if (Pred == getBasePredecessor())
274      return CleanedState;
275    else
276      return Pred->getState();
277  }
278
279  ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
280                         ExplodedNode* Pred, const GRState* St) {
281    return MakeNode(Dst, S, Pred, St, PointKind);
282  }
283
284  ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S,ExplodedNode* Pred,
285                         const GRState* St, ProgramPoint::Kind K);
286
287  ExplodedNode* MakeSinkNode(ExplodedNodeSet& Dst, const Stmt* S,
288                       ExplodedNode* Pred, const GRState* St) {
289    bool Tmp = BuildSinks;
290    BuildSinks = true;
291    ExplodedNode* N = MakeNode(Dst, S, Pred, St);
292    BuildSinks = Tmp;
293    return N;
294  }
295};
296
297class GRBranchNodeBuilder {
298  GRCoreEngine& Eng;
299  const CFGBlock* Src;
300  const CFGBlock* DstT;
301  const CFGBlock* DstF;
302  ExplodedNode* Pred;
303
304  typedef llvm::SmallVector<ExplodedNode*,3> DeferredTy;
305  DeferredTy Deferred;
306
307  bool GeneratedTrue;
308  bool GeneratedFalse;
309  bool InFeasibleTrue;
310  bool InFeasibleFalse;
311
312public:
313  GRBranchNodeBuilder(const CFGBlock* src, const CFGBlock* dstT,
314                      const CFGBlock* dstF, ExplodedNode* pred, GRCoreEngine* e)
315  : Eng(*e), Src(src), DstT(dstT), DstF(dstF), Pred(pred),
316    GeneratedTrue(false), GeneratedFalse(false),
317    InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {}
318
319  ~GRBranchNodeBuilder();
320
321  ExplodedNode* getPredecessor() const { return Pred; }
322
323  const ExplodedGraph& getGraph() const { return *Eng.G; }
324
325  GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
326
327  ExplodedNode* generateNode(const GRState* State, bool branch);
328
329  const CFGBlock* getTargetBlock(bool branch) const {
330    return branch ? DstT : DstF;
331  }
332
333  void markInfeasible(bool branch) {
334    if (branch)
335      InFeasibleTrue = GeneratedTrue = true;
336    else
337      InFeasibleFalse = GeneratedFalse = true;
338  }
339
340  bool isFeasible(bool branch) {
341    return branch ? !InFeasibleTrue : !InFeasibleFalse;
342  }
343
344  const GRState* getState() const {
345    return getPredecessor()->getState();
346  }
347};
348
349class GRIndirectGotoNodeBuilder {
350  GRCoreEngine& Eng;
351  const CFGBlock* Src;
352  const CFGBlock& DispatchBlock;
353  const Expr* E;
354  ExplodedNode* Pred;
355
356public:
357  GRIndirectGotoNodeBuilder(ExplodedNode* pred, const CFGBlock* src,
358                    const Expr* e, const CFGBlock* dispatch, GRCoreEngine* eng)
359    : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
360
361  class iterator {
362    CFGBlock::const_succ_iterator I;
363
364    friend class GRIndirectGotoNodeBuilder;
365    iterator(CFGBlock::const_succ_iterator i) : I(i) {}
366  public:
367
368    iterator& operator++() { ++I; return *this; }
369    bool operator!=(const iterator& X) const { return I != X.I; }
370
371    const LabelStmt* getLabel() const {
372      return llvm::cast<LabelStmt>((*I)->getLabel());
373    }
374
375    const CFGBlock*  getBlock() const {
376      return *I;
377    }
378  };
379
380  iterator begin() { return iterator(DispatchBlock.succ_begin()); }
381  iterator end() { return iterator(DispatchBlock.succ_end()); }
382
383  ExplodedNode* generateNode(const iterator& I, const GRState* State,
384                             bool isSink = false);
385
386  const Expr* getTarget() const { return E; }
387
388  const GRState* getState() const { return Pred->State; }
389};
390
391class GRSwitchNodeBuilder {
392  GRCoreEngine& Eng;
393  const CFGBlock* Src;
394  const Expr* Condition;
395  ExplodedNode* Pred;
396
397public:
398  GRSwitchNodeBuilder(ExplodedNode* pred, const CFGBlock* src,
399                      const Expr* condition, GRCoreEngine* eng)
400  : Eng(*eng), Src(src), Condition(condition), Pred(pred) {}
401
402  class iterator {
403    CFGBlock::const_succ_reverse_iterator I;
404
405    friend class GRSwitchNodeBuilder;
406    iterator(CFGBlock::const_succ_reverse_iterator i) : I(i) {}
407
408  public:
409    iterator& operator++() { ++I; return *this; }
410    bool operator!=(const iterator& X) const { return I != X.I; }
411
412    const CaseStmt* getCase() const {
413      return llvm::cast<CaseStmt>((*I)->getLabel());
414    }
415
416    const CFGBlock* getBlock() const {
417      return *I;
418    }
419  };
420
421  iterator begin() { return iterator(Src->succ_rbegin()+1); }
422  iterator end() { return iterator(Src->succ_rend()); }
423
424  ExplodedNode* generateCaseStmtNode(const iterator& I, const GRState* State);
425
426  ExplodedNode* generateDefaultCaseNode(const GRState* State,
427                                        bool isSink = false);
428
429  const Expr* getCondition() const { return Condition; }
430
431  const GRState* getState() const { return Pred->State; }
432};
433
434class GREndPathNodeBuilder {
435  GRCoreEngine &Eng;
436  const CFGBlock& B;
437  ExplodedNode* Pred;
438
439public:
440  bool HasGeneratedNode;
441
442public:
443  GREndPathNodeBuilder(const CFGBlock* b, ExplodedNode* N, GRCoreEngine* e)
444    : Eng(*e), B(*b), Pred(N), HasGeneratedNode(false) {}
445
446  ~GREndPathNodeBuilder();
447
448  GRWorkList &getWorkList() { return *Eng.WList; }
449
450  ExplodedNode* getPredecessor() const { return Pred; }
451
452  GRBlockCounter getBlockCounter() const {
453    return Eng.WList->getBlockCounter();
454  }
455
456  unsigned getCurrentBlockCount() const {
457    return getBlockCounter().getNumVisited(
458                            Pred->getLocationContext()->getCurrentStackFrame(),
459                                           B.getBlockID());
460  }
461
462  ExplodedNode* generateNode(const GRState* State, const void *tag = 0,
463                             ExplodedNode *P = 0);
464
465  void GenerateCallExitNode(const GRState *state);
466
467  const CFGBlock* getBlock() const { return &B; }
468
469  const GRState* getState() const {
470    return getPredecessor()->getState();
471  }
472};
473
474class GRCallEnterNodeBuilder {
475  GRCoreEngine &Eng;
476
477  const ExplodedNode *Pred;
478
479  // The call site.
480  const Stmt *CE;
481
482  // The AnalysisContext of the callee.
483  AnalysisContext *CalleeCtx;
484
485  // The parent block of the CallExpr.
486  const CFGBlock *Block;
487
488  // The CFGBlock index of the CallExpr.
489  unsigned Index;
490
491public:
492  GRCallEnterNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred,
493                         const Stmt *s, AnalysisContext *callee,
494                         const CFGBlock *blk, unsigned idx)
495    : Eng(eng), Pred(pred), CE(s), CalleeCtx(callee), Block(blk), Index(idx) {}
496
497  const GRState *getState() const { return Pred->getState(); }
498
499  const LocationContext *getLocationContext() const {
500    return Pred->getLocationContext();
501  }
502
503  const Stmt *getCallExpr() const { return CE; }
504
505  AnalysisContext *getCalleeContext() const { return CalleeCtx; }
506
507  const CFGBlock *getBlock() const { return Block; }
508
509  unsigned getIndex() const { return Index; }
510
511  void GenerateNode(const GRState *state, const LocationContext *LocCtx);
512};
513
514class GRCallExitNodeBuilder {
515  GRCoreEngine &Eng;
516  const ExplodedNode *Pred;
517
518public:
519  GRCallExitNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred)
520    : Eng(eng), Pred(pred) {}
521
522  const ExplodedNode *getPredecessor() const { return Pred; }
523
524  const GRState *getState() const { return Pred->getState(); }
525
526  void GenerateNode(const GRState *state);
527};
528} // end clang namespace
529
530#endif
531