CoreEngine.cpp revision b07805485c603be3d8011f72611465324c9e664b
1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//==- CoreEngine.cpp - Path-Sensitive Dataflow Engine ------------*- C++ -*-//
2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//
3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//                     The LLVM Compiler Infrastructure
4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//
56e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source
66e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// License. See LICENSE.TXT for details.
76e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//
86e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//===----------------------------------------------------------------------===//
96e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//
106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//  This file defines a generic engine for intraprocedural, path-sensitive,
116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//  dataflow analysis via graph reachability engine.
126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//===----------------------------------------------------------------------===//
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#define DEBUG_TYPE "CoreEngine"
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "clang/AST/Expr.h"
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "clang/AST/StmtCXX.h"
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "llvm/ADT/DenseMap.h"
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "llvm/ADT/Statistic.h"
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "llvm/Support/Casting.h"
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)using namespace clang;
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)using namespace ento;
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)STATISTIC(NumSteps,
306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            "The # of steps executed.");
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)STATISTIC(NumReachedMaxSteps,
326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            "The # of times we reached the max number of steps.");
336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)STATISTIC(NumPathsExplored,
346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            "The # of paths explored by the analyzer.");
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//===----------------------------------------------------------------------===//
376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Worklist classes for exploration of reachable states.
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//===----------------------------------------------------------------------===//
396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)WorkList::Visitor::~Visitor() {}
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace {
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class DFS : public WorkList {
446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  SmallVector<WorkListUnit,20> Stack;
456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)public:
466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual bool hasWork() const {
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return !Stack.empty();
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void enqueue(const WorkListUnit& U) {
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    Stack.push_back(U);
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual WorkListUnit dequeue() {
556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    assert (!Stack.empty());
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const WorkListUnit& U = Stack.back();
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    Stack.pop_back(); // This technically "invalidates" U, but we are fine.
586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return U;
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual bool visitItemsInWorkList(Visitor &V) {
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    for (SmallVectorImpl<WorkListUnit>::iterator
636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)         I = Stack.begin(), E = Stack.end(); I != E; ++I) {
646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (V.visit(*I))
656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        return true;
666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)};
706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class BFS : public WorkList {
726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::deque<WorkListUnit> Queue;
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)public:
746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual bool hasWork() const {
756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return !Queue.empty();
766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual void enqueue(const WorkListUnit& U) {
796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    Queue.push_back(U);
806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual WorkListUnit dequeue() {
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    WorkListUnit U = Queue.front();
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    Queue.pop_front();
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return U;
866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual bool visitItemsInWorkList(Visitor &V) {
896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    for (std::deque<WorkListUnit>::iterator
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)         I = Queue.begin(), E = Queue.end(); I != E; ++I) {
916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (V.visit(*I))
926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        return true;
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return false;
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)};
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // end anonymous namespace
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Place the dstor for WorkList here because it contains virtual member
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// functions, and we the code for the dstor generated in one compilation unit.
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)WorkList::~WorkList() {}
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)WorkList *WorkList::makeDFS() { return new DFS(); }
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)WorkList *WorkList::makeBFS() { return new BFS(); }
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace {
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  class BFSBlockDFSContents : public WorkList {
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    std::deque<WorkListUnit> Queue;
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SmallVector<WorkListUnit,20> Stack;
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  public:
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    virtual bool hasWork() const {
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return !Queue.empty() || !Stack.empty();
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    virtual void enqueue(const WorkListUnit& U) {
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (U.getNode()->getLocation().getAs<BlockEntrance>())
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        Queue.push_front(U);
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      else
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        Stack.push_back(U);
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    virtual WorkListUnit dequeue() {
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Process all basic blocks to completion.
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (!Stack.empty()) {
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        const WorkListUnit& U = Stack.back();
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        Stack.pop_back(); // This technically "invalidates" U, but we are fine.
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return U;
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      assert(!Queue.empty());
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Don't use const reference.  The subsequent pop_back() might make it
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // unsafe.
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      WorkListUnit U = Queue.front();
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      Queue.pop_front();
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return U;
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    virtual bool visitItemsInWorkList(Visitor &V) {
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      for (SmallVectorImpl<WorkListUnit>::iterator
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)           I = Stack.begin(), E = Stack.end(); I != E; ++I) {
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (V.visit(*I))
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          return true;
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      for (std::deque<WorkListUnit>::iterator
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)           I = Queue.begin(), E = Queue.end(); I != E; ++I) {
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (V.visit(*I))
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          return true;
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return false;
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  };
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // end anonymous namespace
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)WorkList* WorkList::makeBFSBlockDFSContents() {
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return new BFSBlockDFSContents();
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//===----------------------------------------------------------------------===//
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Core analysis engine.
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//===----------------------------------------------------------------------===//
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                   ProgramStateRef InitState) {
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (G->num_roots() == 0) { // Initialize the analysis by constructing
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // the root if none exists.
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const CFGBlock *Entry = &(L->getCFG()->getEntry());
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    assert (Entry->empty() &&
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            "Entry block must be empty.");
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    assert (Entry->succ_size() == 1 &&
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            "Entry block must have 1 successor.");
1776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Mark the entry block as visited.
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    FunctionSummaries->markVisitedBasicBlock(Entry->getBlockID(),
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                             L->getDecl(),
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                             L->getCFG()->getNumBlockIDs());
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Get the solitary successor.
1846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const CFGBlock *Succ = *(Entry->succ_begin());
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Construct an edge representing the
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // starting location in the function.
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    BlockEdge StartLoc(Entry, Succ, L);
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Set the current block counter to being empty.
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    WList->setBlockCounter(BCounterFactory.GetEmptyCounter());
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!InitState)
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Generate the root.
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      generateNode(StartLoc, SubEng.getInitialState(L), 0);
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    else
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      generateNode(StartLoc, InitState, 0);
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Check if we have a steps limit
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool UnlimitedSteps = Steps == 0;
202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  while (WList->hasWork()) {
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!UnlimitedSteps) {
2056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (Steps == 0) {
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        NumReachedMaxSteps++;
2076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        break;
2086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      }
2096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      --Steps;
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    NumSteps++;
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const WorkListUnit& WU = WList->dequeue();
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Set the current block counter.
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    WList->setBlockCounter(WU.getBlockCounter());
2186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Retrieve the node.
2206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ExplodedNode *Node = WU.getNode();
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    dispatchWorkItem(Node, Node->getLocation(), WU);
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SubEng.processEndWorklist(hasWorkRemaining());
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return WList->hasWork();
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void CoreEngine::dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc,
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  const WorkListUnit& WU) {
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Dispatch on the location type.
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  switch (Loc.getKind()) {
2326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    case ProgramPoint::BlockEdgeKind:
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      HandleBlockEdge(Loc.castAs<BlockEdge>(), Pred);
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
2356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    case ProgramPoint::BlockEntranceKind:
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      HandleBlockEntrance(Loc.castAs<BlockEntrance>(), Pred);
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
23946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    case ProgramPoint::BlockExitKind:
24146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      assert (false && "BlockExit location never occur in forward analysis.");
2426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      break;
2436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    case ProgramPoint::CallEnterKind: {
2456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      CallEnter CEnter = Loc.castAs<CallEnter>();
2466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      SubEng.processCallEnter(CEnter, Pred);
24746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
24846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
24946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    case ProgramPoint::CallExitBeginKind:
2516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      SubEng.processCallExit(Pred);
2526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      break;
2536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    case ProgramPoint::EpsilonKind: {
25546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      assert(Pred->hasSinglePred() &&
25646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)             "Assume epsilon has exactly one predecessor by construction");
25746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      ExplodedNode *PNode = Pred->getFirstPred();
25846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      dispatchWorkItem(Pred, PNode->getLocation(), WU);
25946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    default:
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      assert(Loc.getAs<PostStmt>() ||
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)             Loc.getAs<PostInitializer>() ||
2646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)             Loc.getAs<PostImplicitCall>() ||
2656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)             Loc.getAs<CallExitEnd>());
2666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      HandlePostStmt(WU.getBlock(), WU.getIndex(), Pred);
2676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      break;
2686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
2706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L,
272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                 unsigned Steps,
273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                 ProgramStateRef InitState,
274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                 ExplodedNodeSet &Dst) {
275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool DidNotFinish = ExecuteWorkList(L, Steps, InitState);
276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (ExplodedGraph::eop_iterator I = G->eop_begin(),
277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                   E = G->eop_end(); I != E; ++I) {
278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Dst.Add(*I);
279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return DidNotFinish;
281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
2846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const CFGBlock *Blk = L.getDst();
2866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  NodeBuilderContext BuilderCtx(*this, Blk, Pred);
2876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Mark this block as visited.
289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const LocationContext *LC = Pred->getLocationContext();
290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  FunctionSummaries->markVisitedBasicBlock(Blk->getBlockID(),
291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                           LC->getDecl(),
292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                           LC->getCFG()->getNumBlockIDs());
293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Check if we are entering the EXIT block.
295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (Blk == &(L.getLocationContext()->getCFG()->getExit())) {
296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    assert (L.getLocationContext()->getCFG()->getExit().size() == 0
2986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            && "EXIT block cannot contain Stmts.");
2996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Process the final state transition.
301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SubEng.processEndOfFunction(BuilderCtx, Pred);
302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // This path is done. Don't enqueue any more nodes.
304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
3056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Call into the SubEngine to process entering the CFGBlock.
3086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ExplodedNodeSet dstNodes;
3096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  BlockEntrance BE(Blk, Pred->getLocationContext());
3106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  NodeBuilderWithSinks nodeBuilder(Pred, dstNodes, BuilderCtx, BE);
3116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  SubEng.processCFGBlockEntrance(L, nodeBuilder, Pred);
3126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Auto-generate a node.
3146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!nodeBuilder.hasGeneratedNodes()) {
3156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    nodeBuilder.generateNode(Pred->State, Pred);
3166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Enqueue nodes onto the worklist.
319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  enqueue(dstNodes);
3206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void CoreEngine::HandleBlockEntrance(const BlockEntrance &L,
323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                       ExplodedNode *Pred) {
324a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Increment the block counter.
326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const LocationContext *LC = Pred->getLocationContext();
3276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  unsigned BlockId = L.getBlock()->getBlockID();
328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  BlockCounter Counter = WList->getBlockCounter();
329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  Counter = BCounterFactory.IncrementCount(Counter, LC->getCurrentStackFrame(),
330a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           BlockId);
331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  WList->setBlockCounter(Counter);
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Process the entrance of the block.
334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (Optional<CFGElement> E = L.getFirstElement()) {
335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    NodeBuilderContext Ctx(*this, L.getBlock(), Pred);
336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SubEng.processCFGElement(*E, Pred, 0, &Ctx);
337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
338a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  else
339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    HandleBlockExit(L.getBlock(), Pred);
340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
341a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) {
3436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (const Stmt *Term = B->getTerminator()) {
345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    switch (Term->getStmtClass()) {
3466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      default:
3476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        llvm_unreachable("Analysis for this terminator not implemented.");
3486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
349a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      case Stmt::BinaryOperatorClass: // '&&' and '||'
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        HandleBranch(cast<BinaryOperator>(Term)->getLHS(), Term, B, Pred);
3516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        return;
352a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      case Stmt::BinaryConditionalOperatorClass:
354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      case Stmt::ConditionalOperatorClass:
355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        HandleBranch(cast<AbstractConditionalOperator>(Term)->getCond(),
356a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     Term, B, Pred);
3576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        return;
3586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
359a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // FIXME: Use constant-folding in CFG construction to simplify this
360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        // case.
3616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      case Stmt::ChooseExprClass:
3636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        HandleBranch(cast<ChooseExpr>(Term)->getCond(), Term, B, Pred);
3646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        return;
3656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
366a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      case Stmt::CXXTryStmtClass: {
367a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // Generate a node for each of the successors.
368a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // Our logic for EH analysis can certainly be improved.
369a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        for (CFGBlock::const_succ_iterator it = B->succ_begin(),
370             et = B->succ_end(); it != et; ++it) {
371          if (const CFGBlock *succ = *it) {
372            generateNode(BlockEdge(B, succ, Pred->getLocationContext()),
373                         Pred->State, Pred);
374          }
375        }
376        return;
377      }
378
379      case Stmt::DoStmtClass:
380        HandleBranch(cast<DoStmt>(Term)->getCond(), Term, B, Pred);
381        return;
382
383      case Stmt::CXXForRangeStmtClass:
384        HandleBranch(cast<CXXForRangeStmt>(Term)->getCond(), Term, B, Pred);
385        return;
386
387      case Stmt::ForStmtClass:
388        HandleBranch(cast<ForStmt>(Term)->getCond(), Term, B, Pred);
389        return;
390
391      case Stmt::ContinueStmtClass:
392      case Stmt::BreakStmtClass:
393      case Stmt::GotoStmtClass:
394        break;
395
396      case Stmt::IfStmtClass:
397        HandleBranch(cast<IfStmt>(Term)->getCond(), Term, B, Pred);
398        return;
399
400      case Stmt::IndirectGotoStmtClass: {
401        // Only 1 successor: the indirect goto dispatch block.
402        assert (B->succ_size() == 1);
403
404        IndirectGotoNodeBuilder
405           builder(Pred, B, cast<IndirectGotoStmt>(Term)->getTarget(),
406                   *(B->succ_begin()), this);
407
408        SubEng.processIndirectGoto(builder);
409        return;
410      }
411
412      case Stmt::ObjCForCollectionStmtClass: {
413        // In the case of ObjCForCollectionStmt, it appears twice in a CFG:
414        //
415        //  (1) inside a basic block, which represents the binding of the
416        //      'element' variable to a value.
417        //  (2) in a terminator, which represents the branch.
418        //
419        // For (1), subengines will bind a value (i.e., 0 or 1) indicating
420        // whether or not collection contains any more elements.  We cannot
421        // just test to see if the element is nil because a container can
422        // contain nil elements.
423        HandleBranch(Term, Term, B, Pred);
424        return;
425      }
426
427      case Stmt::SwitchStmtClass: {
428        SwitchNodeBuilder builder(Pred, B, cast<SwitchStmt>(Term)->getCond(),
429                                    this);
430
431        SubEng.processSwitch(builder);
432        return;
433      }
434
435      case Stmt::WhileStmtClass:
436        HandleBranch(cast<WhileStmt>(Term)->getCond(), Term, B, Pred);
437        return;
438    }
439  }
440
441  assert (B->succ_size() == 1 &&
442          "Blocks with no terminator should have at most 1 successor.");
443
444  generateNode(BlockEdge(B, *(B->succ_begin()), Pred->getLocationContext()),
445               Pred->State, Pred);
446}
447
448void CoreEngine::HandleBranch(const Stmt *Cond, const Stmt *Term,
449                                const CFGBlock * B, ExplodedNode *Pred) {
450  assert(B->succ_size() == 2);
451  NodeBuilderContext Ctx(*this, B, Pred);
452  ExplodedNodeSet Dst;
453  SubEng.processBranch(Cond, Term, Ctx, Pred, Dst,
454                       *(B->succ_begin()), *(B->succ_begin()+1));
455  // Enqueue the new frontier onto the worklist.
456  enqueue(Dst);
457}
458
459void CoreEngine::HandlePostStmt(const CFGBlock *B, unsigned StmtIdx,
460                                  ExplodedNode *Pred) {
461  assert(B);
462  assert(!B->empty());
463
464  if (StmtIdx == B->size())
465    HandleBlockExit(B, Pred);
466  else {
467    NodeBuilderContext Ctx(*this, B, Pred);
468    SubEng.processCFGElement((*B)[StmtIdx], Pred, StmtIdx, &Ctx);
469  }
470}
471
472/// generateNode - Utility method to generate nodes, hook up successors,
473///  and add nodes to the worklist.
474void CoreEngine::generateNode(const ProgramPoint &Loc,
475                              ProgramStateRef State,
476                              ExplodedNode *Pred) {
477
478  bool IsNew;
479  ExplodedNode *Node = G->getNode(Loc, State, false, &IsNew);
480
481  if (Pred)
482    Node->addPredecessor(Pred, *G);  // Link 'Node' with its predecessor.
483  else {
484    assert (IsNew);
485    G->addRoot(Node);  // 'Node' has no predecessor.  Make it a root.
486  }
487
488  // Only add 'Node' to the worklist if it was freshly generated.
489  if (IsNew) WList->enqueue(Node);
490}
491
492void CoreEngine::enqueueStmtNode(ExplodedNode *N,
493                                 const CFGBlock *Block, unsigned Idx) {
494  assert(Block);
495  assert (!N->isSink());
496
497  // Check if this node entered a callee.
498  if (N->getLocation().getAs<CallEnter>()) {
499    // Still use the index of the CallExpr. It's needed to create the callee
500    // StackFrameContext.
501    WList->enqueue(N, Block, Idx);
502    return;
503  }
504
505  // Do not create extra nodes. Move to the next CFG element.
506  if (N->getLocation().getAs<PostInitializer>() ||
507      N->getLocation().getAs<PostImplicitCall>()) {
508    WList->enqueue(N, Block, Idx+1);
509    return;
510  }
511
512  if (N->getLocation().getAs<EpsilonPoint>()) {
513    WList->enqueue(N, Block, Idx);
514    return;
515  }
516
517  // At this point, we know we're processing a normal statement.
518  CFGStmt CS = (*Block)[Idx].castAs<CFGStmt>();
519  PostStmt Loc(CS.getStmt(), N->getLocationContext());
520
521  if (Loc == N->getLocation()) {
522    // Note: 'N' should be a fresh node because otherwise it shouldn't be
523    // a member of Deferred.
524    WList->enqueue(N, Block, Idx+1);
525    return;
526  }
527
528  bool IsNew;
529  ExplodedNode *Succ = G->getNode(Loc, N->getState(), false, &IsNew);
530  Succ->addPredecessor(N, *G);
531
532  if (IsNew)
533    WList->enqueue(Succ, Block, Idx+1);
534}
535
536ExplodedNode *CoreEngine::generateCallExitBeginNode(ExplodedNode *N) {
537  // Create a CallExitBegin node and enqueue it.
538  const StackFrameContext *LocCtx
539                         = cast<StackFrameContext>(N->getLocationContext());
540
541  // Use the callee location context.
542  CallExitBegin Loc(LocCtx);
543
544  bool isNew;
545  ExplodedNode *Node = G->getNode(Loc, N->getState(), false, &isNew);
546  Node->addPredecessor(N, *G);
547  return isNew ? Node : 0;
548}
549
550
551void CoreEngine::enqueue(ExplodedNodeSet &Set) {
552  for (ExplodedNodeSet::iterator I = Set.begin(),
553                                 E = Set.end(); I != E; ++I) {
554    WList->enqueue(*I);
555  }
556}
557
558void CoreEngine::enqueue(ExplodedNodeSet &Set,
559                         const CFGBlock *Block, unsigned Idx) {
560  for (ExplodedNodeSet::iterator I = Set.begin(),
561                                 E = Set.end(); I != E; ++I) {
562    enqueueStmtNode(*I, Block, Idx);
563  }
564}
565
566void CoreEngine::enqueueEndOfFunction(ExplodedNodeSet &Set) {
567  for (ExplodedNodeSet::iterator I = Set.begin(), E = Set.end(); I != E; ++I) {
568    ExplodedNode *N = *I;
569    // If we are in an inlined call, generate CallExitBegin node.
570    if (N->getLocationContext()->getParent()) {
571      N = generateCallExitBeginNode(N);
572      if (N)
573        WList->enqueue(N);
574    } else {
575      // TODO: We should run remove dead bindings here.
576      G->addEndOfPath(N);
577      NumPathsExplored++;
578    }
579  }
580}
581
582
583void NodeBuilder::anchor() { }
584
585ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc,
586                                            ProgramStateRef State,
587                                            ExplodedNode *FromN,
588                                            bool MarkAsSink) {
589  HasGeneratedNodes = true;
590  bool IsNew;
591  ExplodedNode *N = C.Eng.G->getNode(Loc, State, MarkAsSink, &IsNew);
592  N->addPredecessor(FromN, *C.Eng.G);
593  Frontier.erase(FromN);
594
595  if (!IsNew)
596    return 0;
597
598  if (!MarkAsSink)
599    Frontier.Add(N);
600
601  return N;
602}
603
604void NodeBuilderWithSinks::anchor() { }
605
606StmtNodeBuilder::~StmtNodeBuilder() {
607  if (EnclosingBldr)
608    for (ExplodedNodeSet::iterator I = Frontier.begin(),
609                                   E = Frontier.end(); I != E; ++I )
610      EnclosingBldr->addNodes(*I);
611}
612
613void BranchNodeBuilder::anchor() { }
614
615ExplodedNode *BranchNodeBuilder::generateNode(ProgramStateRef State,
616                                              bool branch,
617                                              ExplodedNode *NodePred) {
618  // If the branch has been marked infeasible we should not generate a node.
619  if (!isFeasible(branch))
620    return NULL;
621
622  ProgramPoint Loc = BlockEdge(C.Block, branch ? DstT:DstF,
623                               NodePred->getLocationContext());
624  ExplodedNode *Succ = generateNodeImpl(Loc, State, NodePred);
625  return Succ;
626}
627
628ExplodedNode*
629IndirectGotoNodeBuilder::generateNode(const iterator &I,
630                                      ProgramStateRef St,
631                                      bool IsSink) {
632  bool IsNew;
633  ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
634                                      Pred->getLocationContext()), St,
635                                      IsSink, &IsNew);
636  Succ->addPredecessor(Pred, *Eng.G);
637
638  if (!IsNew)
639    return 0;
640
641  if (!IsSink)
642    Eng.WList->enqueue(Succ);
643
644  return Succ;
645}
646
647
648ExplodedNode*
649SwitchNodeBuilder::generateCaseStmtNode(const iterator &I,
650                                        ProgramStateRef St) {
651
652  bool IsNew;
653  ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
654                                      Pred->getLocationContext()), St,
655                                      false, &IsNew);
656  Succ->addPredecessor(Pred, *Eng.G);
657  if (!IsNew)
658    return 0;
659
660  Eng.WList->enqueue(Succ);
661  return Succ;
662}
663
664
665ExplodedNode*
666SwitchNodeBuilder::generateDefaultCaseNode(ProgramStateRef St,
667                                           bool IsSink) {
668  // Get the block for the default case.
669  assert(Src->succ_rbegin() != Src->succ_rend());
670  CFGBlock *DefaultBlock = *Src->succ_rbegin();
671
672  // Sanity check for default blocks that are unreachable and not caught
673  // by earlier stages.
674  if (!DefaultBlock)
675    return NULL;
676
677  bool IsNew;
678  ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, DefaultBlock,
679                                      Pred->getLocationContext()), St,
680                                      IsSink, &IsNew);
681  Succ->addPredecessor(Pred, *Eng.G);
682
683  if (!IsNew)
684    return 0;
685
686  if (!IsSink)
687    Eng.WList->enqueue(Succ);
688
689  return Succ;
690}
691