CoreEngine.cpp revision 651f13cea278ec967336033dd032faef0e9fc2ec
10511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com//==- CoreEngine.cpp - Path-Sensitive Dataflow Engine ------------*- C++ -*-//
20511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com//
30511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com//                     The LLVM Compiler Infrastructure
40511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com//
50511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com// This file is distributed under the University of Illinois Open Source
60511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com// License. See LICENSE.TXT for details.
70511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com//
80511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com//===----------------------------------------------------------------------===//
90511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com//
100511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com//  This file defines a generic engine for intraprocedural, path-sensitive,
110511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com//  dataflow analysis via graph reachability engine.
120511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com//
130511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com//===----------------------------------------------------------------------===//
140511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
150511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com#define DEBUG_TYPE "CoreEngine"
160511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
170511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
180511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com#include "clang/AST/Expr.h"
190511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com#include "clang/AST/StmtCXX.h"
200511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
210511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
220511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com#include "llvm/ADT/DenseMap.h"
230511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com#include "llvm/ADT/Statistic.h"
240511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com#include "llvm/Support/Casting.h"
250511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
260511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comusing namespace clang;
270511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comusing namespace ento;
280511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
29ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgSTATISTIC(NumSteps,
300511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com            "The # of steps executed.");
310511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comSTATISTIC(NumReachedMaxSteps,
320511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com            "The # of times we reached the max number of steps.");
330511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comSTATISTIC(NumPathsExplored,
340511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com            "The # of paths explored by the analyzer.");
350511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
360511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com//===----------------------------------------------------------------------===//
374f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org// Worklist classes for exploration of reachable states.
380511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com//===----------------------------------------------------------------------===//
390511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
400511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comWorkList::Visitor::~Visitor() {}
410511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
424f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.orgnamespace {
434f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.orgclass DFS : public WorkList {
444f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  SmallVector<WorkListUnit,20> Stack;
454f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.orgpublic:
464f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  bool hasWork() const override {
474f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    return !Stack.empty();
484f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
494f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
500511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  void enqueue(const WorkListUnit& U) override {
514f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    Stack.push_back(U);
524f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
534f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
544f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  WorkListUnit dequeue() override {
550511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    assert (!Stack.empty());
560511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    const WorkListUnit& U = Stack.back();
570511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Stack.pop_back(); // This technically "invalidates" U, but we are fine.
584f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    return U;
594f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
600511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
610511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  bool visitItemsInWorkList(Visitor &V) override {
620511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    for (SmallVectorImpl<WorkListUnit>::iterator
630511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com         I = Stack.begin(), E = Stack.end(); I != E; ++I) {
640511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      if (V.visit(*I))
650511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        return true;
660511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
670511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    return false;
680511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
690511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com};
700511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
710511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comclass BFS : public WorkList {
720511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  std::deque<WorkListUnit> Queue;
730511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.compublic:
740511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  bool hasWork() const override {
750511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    return !Queue.empty();
760511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
770511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
780511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  void enqueue(const WorkListUnit& U) override {
790511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Queue.push_back(U);
800511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
810511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
820511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  WorkListUnit dequeue() override {
830511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    WorkListUnit U = Queue.front();
840511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Queue.pop_front();
850511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    return U;
860511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
870511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
880511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  bool visitItemsInWorkList(Visitor &V) override {
890511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    for (std::deque<WorkListUnit>::iterator
900511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com         I = Queue.begin(), E = Queue.end(); I != E; ++I) {
910511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      if (V.visit(*I))
920511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        return true;
930511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
940511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    return false;
950511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
960511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com};
970511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
980511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com} // end anonymous namespace
990511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1000511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com// Place the dstor for WorkList here because it contains virtual member
1010511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com// functions, and we the code for the dstor generated in one compilation unit.
1020511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comWorkList::~WorkList() {}
1030511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1040511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comWorkList *WorkList::makeDFS() { return new DFS(); }
1050511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comWorkList *WorkList::makeBFS() { return new BFS(); }
1060511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1070511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comnamespace {
1080511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  class BFSBlockDFSContents : public WorkList {
1090511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    std::deque<WorkListUnit> Queue;
1100511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    SmallVector<WorkListUnit,20> Stack;
1110511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  public:
1120511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    bool hasWork() const override {
1130511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      return !Queue.empty() || !Stack.empty();
1140511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
1150511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1160511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    void enqueue(const WorkListUnit& U) override {
1170511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      if (U.getNode()->getLocation().getAs<BlockEntrance>())
1180511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        Queue.push_front(U);
1190511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      else
1200511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        Stack.push_back(U);
1210511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
1220511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1230511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    WorkListUnit dequeue() override {
1240511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      // Process all basic blocks to completion.
1250511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      if (!Stack.empty()) {
1260511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        const WorkListUnit& U = Stack.back();
1270511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        Stack.pop_back(); // This technically "invalidates" U, but we are fine.
1284f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org        return U;
1290511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      }
1300511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1310511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      assert(!Queue.empty());
1320511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      // Don't use const reference.  The subsequent pop_back() might make it
1330511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      // unsafe.
1340511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      WorkListUnit U = Queue.front();
1350511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      Queue.pop_front();
1360511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      return U;
1370511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
1380511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    bool visitItemsInWorkList(Visitor &V) override {
1390511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      for (SmallVectorImpl<WorkListUnit>::iterator
1400511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com           I = Stack.begin(), E = Stack.end(); I != E; ++I) {
1410511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        if (V.visit(*I))
1420511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com          return true;
1430511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      }
1440511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      for (std::deque<WorkListUnit>::iterator
1450511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com           I = Queue.begin(), E = Queue.end(); I != E; ++I) {
1460511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        if (V.visit(*I))
1470511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com          return true;
1480511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      }
1490511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      return false;
1500511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
1510511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1520511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  };
1530511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com} // end anonymous namespace
1540511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1550511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comWorkList* WorkList::makeBFSBlockDFSContents() {
1560511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  return new BFSBlockDFSContents();
1570511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
1580511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1590511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com//===----------------------------------------------------------------------===//
1600511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com// Core analysis engine.
1610511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com//===----------------------------------------------------------------------===//
1620511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1630511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
1640511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.combool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
1650511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                   ProgramStateRef InitState) {
1660511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1670511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (G->num_roots() == 0) { // Initialize the analysis by constructing
1680511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // the root if none exists.
1690511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1700511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    const CFGBlock *Entry = &(L->getCFG()->getEntry());
1710511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1720511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    assert (Entry->empty() &&
1730511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com            "Entry block must be empty.");
1740511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1750511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    assert (Entry->succ_size() == 1 &&
1760511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com            "Entry block must have 1 successor.");
1770511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1780511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // Mark the entry block as visited.
1790511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    FunctionSummaries->markVisitedBasicBlock(Entry->getBlockID(),
1800511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                             L->getDecl(),
1814f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org                                             L->getCFG()->getNumBlockIDs());
1820511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1830511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // Get the solitary successor.
1840511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    const CFGBlock *Succ = *(Entry->succ_begin());
1850511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
1860511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // Construct an edge representing the
1870511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // starting location in the function.
1880511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    BlockEdge StartLoc(Entry, Succ, L);
1894f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
1904f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    // Set the current block counter to being empty.
1910511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    WList->setBlockCounter(BCounterFactory.GetEmptyCounter());
1924f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
1934f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    if (!InitState)
1944f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      // Generate the root.
1954f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      generateNode(StartLoc, SubEng.getInitialState(L), 0);
1964f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    else
1974f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      generateNode(StartLoc, InitState, 0);
1984f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
1994f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
2004f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // Check if we have a steps limit
2014f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  bool UnlimitedSteps = Steps == 0;
2024f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
2034f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  while (WList->hasWork()) {
2044f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    if (!UnlimitedSteps) {
2054f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      if (Steps == 0) {
2064f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org        NumReachedMaxSteps++;
2074f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org        break;
2084f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      }
2094f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      --Steps;
2104f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    }
2114f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
2124f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    NumSteps++;
2134f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
2144f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    const WorkListUnit& WU = WList->dequeue();
2154f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
2164f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    // Set the current block counter.
2174f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    WList->setBlockCounter(WU.getBlockCounter());
2184f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
2194f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    // Retrieve the node.
2204f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    ExplodedNode *Node = WU.getNode();
2214f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
2224f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    dispatchWorkItem(Node, Node->getLocation(), WU);
2234f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
2244f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  SubEng.processEndWorklist(hasWorkRemaining());
2254f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  return WList->hasWork();
2264f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org}
2274f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
2284f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.orgvoid CoreEngine::dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc,
2294f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org                                  const WorkListUnit& WU) {
2304f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // Dispatch on the location type.
2314f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  switch (Loc.getKind()) {
2324f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    case ProgramPoint::BlockEdgeKind:
2334f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      HandleBlockEdge(Loc.castAs<BlockEdge>(), Pred);
2344f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      break;
2354f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
2364f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    case ProgramPoint::BlockEntranceKind:
2374f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      HandleBlockEntrance(Loc.castAs<BlockEntrance>(), Pred);
2384f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      break;
2394f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
2404f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    case ProgramPoint::BlockExitKind:
2414f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      assert (false && "BlockExit location never occur in forward analysis.");
2420511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      break;
2430511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
2444f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    case ProgramPoint::CallEnterKind: {
2454f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      CallEnter CEnter = Loc.castAs<CallEnter>();
2464f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      SubEng.processCallEnter(CEnter, Pred);
2474f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      break;
2484f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    }
2494f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
2504f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    case ProgramPoint::CallExitBeginKind:
2514f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      SubEng.processCallExit(Pred);
2524f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      break;
2534f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
2544f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    case ProgramPoint::EpsilonKind: {
2554f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      assert(Pred->hasSinglePred() &&
2564f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org             "Assume epsilon has exactly one predecessor by construction");
2574f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      ExplodedNode *PNode = Pred->getFirstPred();
2584f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      dispatchWorkItem(Pred, PNode->getLocation(), WU);
2594f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      break;
2604f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    }
2614f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    default:
2624f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      assert(Loc.getAs<PostStmt>() ||
2634f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org             Loc.getAs<PostInitializer>() ||
2644f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org             Loc.getAs<PostImplicitCall>() ||
2654f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org             Loc.getAs<CallExitEnd>());
2664f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      HandlePostStmt(WU.getBlock(), WU.getIndex(), Pred);
2674f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      break;
2684f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
2694f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org}
2704f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
2714f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.orgbool CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L,
2724f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org                                                 unsigned Steps,
2734f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org                                                 ProgramStateRef InitState,
2744f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org                                                 ExplodedNodeSet &Dst) {
2754f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  bool DidNotFinish = ExecuteWorkList(L, Steps, InitState);
2764f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  for (ExplodedGraph::eop_iterator I = G->eop_begin(),
2774f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org                                   E = G->eop_end(); I != E; ++I) {
2784f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    Dst.Add(*I);
2794f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
2804f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  return DidNotFinish;
2814f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org}
2824f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
2834f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.orgvoid CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
2844f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
2854f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  const CFGBlock *Blk = L.getDst();
2864f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  NodeBuilderContext BuilderCtx(*this, Blk, Pred);
2874f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
2884f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // Mark this block as visited.
2894f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  const LocationContext *LC = Pred->getLocationContext();
2904f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  FunctionSummaries->markVisitedBasicBlock(Blk->getBlockID(),
2914f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org                                           LC->getDecl(),
2924f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org                                           LC->getCFG()->getNumBlockIDs());
2934f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
2944f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // Check if we are entering the EXIT block.
2954f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  if (Blk == &(L.getLocationContext()->getCFG()->getExit())) {
2964f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
2974f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    assert (L.getLocationContext()->getCFG()->getExit().size() == 0
2984f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org            && "EXIT block cannot contain Stmts.");
2994f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
3004f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    // Process the final state transition.
3014f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    SubEng.processEndOfFunction(BuilderCtx, Pred);
3024f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
3030511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    // This path is done. Don't enqueue any more nodes.
3040511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    return;
3050511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
3060511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3070511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Call into the SubEngine to process entering the CFGBlock.
3080511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  ExplodedNodeSet dstNodes;
3090511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  BlockEntrance BE(Blk, Pred->getLocationContext());
3100511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  NodeBuilderWithSinks nodeBuilder(Pred, dstNodes, BuilderCtx, BE);
3110511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  SubEng.processCFGBlockEntrance(L, nodeBuilder, Pred);
3120511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3130511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Auto-generate a node.
3140511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (!nodeBuilder.hasGeneratedNodes()) {
3150511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    nodeBuilder.generateNode(Pred->State, Pred);
3160511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
31731b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org
3180511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Enqueue nodes onto the worklist.
3190511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  enqueue(dstNodes);
3200511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
3210511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3220511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid CoreEngine::HandleBlockEntrance(const BlockEntrance &L,
3230511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                       ExplodedNode *Pred) {
3240511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3250511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Increment the block counter.
3260511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  const LocationContext *LC = Pred->getLocationContext();
3270511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  unsigned BlockId = L.getBlock()->getBlockID();
3280511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  BlockCounter Counter = WList->getBlockCounter();
3290511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  Counter = BCounterFactory.IncrementCount(Counter, LC->getCurrentStackFrame(),
3300511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                           BlockId);
3310511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  WList->setBlockCounter(Counter);
3320511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3330511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Process the entrance of the block.
3340511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (Optional<CFGElement> E = L.getFirstElement()) {
3350511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    NodeBuilderContext Ctx(*this, L.getBlock(), Pred);
3360511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    SubEng.processCFGElement(*E, Pred, 0, &Ctx);
3370511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
3380511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  else
3390511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    HandleBlockExit(L.getBlock(), Pred);
3400511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
3410511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3420511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) {
3430511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3440511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (const Stmt *Term = B->getTerminator()) {
3450511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    switch (Term->getStmtClass()) {
3460511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      default:
3470511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        llvm_unreachable("Analysis for this terminator not implemented.");
3480511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3490511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      // Model static initializers.
3500511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      case Stmt::DeclStmtClass:
3510511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        HandleStaticInit(cast<DeclStmt>(Term), B, Pred);
3520511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        return;
3530511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3540511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      case Stmt::BinaryOperatorClass: // '&&' and '||'
3550511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        HandleBranch(cast<BinaryOperator>(Term)->getLHS(), Term, B, Pred);
3560511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        return;
3570511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3580511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      case Stmt::BinaryConditionalOperatorClass:
3590511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      case Stmt::ConditionalOperatorClass:
3600511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        HandleBranch(cast<AbstractConditionalOperator>(Term)->getCond(),
3610511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                     Term, B, Pred);
3620511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        return;
3630511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3640511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        // FIXME: Use constant-folding in CFG construction to simplify this
3650511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        // case.
3660511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3670511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      case Stmt::ChooseExprClass:
3680511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        HandleBranch(cast<ChooseExpr>(Term)->getCond(), Term, B, Pred);
3690511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        return;
3700511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
3710511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      case Stmt::CXXTryStmtClass: {
3720511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        // Generate a node for each of the successors.
3734f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org        // Our logic for EH analysis can certainly be improved.
3744f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org        for (CFGBlock::const_succ_iterator it = B->succ_begin(),
3754f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org             et = B->succ_end(); it != et; ++it) {
3764f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org          if (const CFGBlock *succ = *it) {
3774f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org            generateNode(BlockEdge(B, succ, Pred->getLocationContext()),
3784f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org                         Pred->State, Pred);
3794f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org          }
3804f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org        }
3814f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org        return;
3824f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      }
3834f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
3844f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      case Stmt::DoStmtClass:
3854f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org        HandleBranch(cast<DoStmt>(Term)->getCond(), Term, B, Pred);
3864f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org        return;
3874f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
3884f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      case Stmt::CXXForRangeStmtClass:
3894f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org        HandleBranch(cast<CXXForRangeStmt>(Term)->getCond(), Term, B, Pred);
3900511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        return;
3914f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
3924f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      case Stmt::ForStmtClass:
3934f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org        HandleBranch(cast<ForStmt>(Term)->getCond(), Term, B, Pred);
3944f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org        return;
3954f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
3964f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      case Stmt::ContinueStmtClass:
3970511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      case Stmt::BreakStmtClass:
3984f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      case Stmt::GotoStmtClass:
3994f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org        break;
4004f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
4014f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      case Stmt::IfStmtClass:
4024f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org        HandleBranch(cast<IfStmt>(Term)->getCond(), Term, B, Pred);
4034f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org        return;
4044f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
4054f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      case Stmt::IndirectGotoStmtClass: {
4060511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        // Only 1 successor: the indirect goto dispatch block.
4070511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        assert (B->succ_size() == 1);
4080511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4090511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        IndirectGotoNodeBuilder
4100511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com           builder(Pred, B, cast<IndirectGotoStmt>(Term)->getTarget(),
4110511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                   *(B->succ_begin()), this);
4120511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4130511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        SubEng.processIndirectGoto(builder);
4140511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        return;
4150511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      }
4160511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4170511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      case Stmt::ObjCForCollectionStmtClass: {
4180511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        // In the case of ObjCForCollectionStmt, it appears twice in a CFG:
4190511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        //
4200511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        //  (1) inside a basic block, which represents the binding of the
4210511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        //      'element' variable to a value.
4220511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        //  (2) in a terminator, which represents the branch.
4230511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        //
4240511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        // For (1), subengines will bind a value (i.e., 0 or 1) indicating
4250511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        // whether or not collection contains any more elements.  We cannot
4260511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        // just test to see if the element is nil because a container can
4270511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        // contain nil elements.
4280511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        HandleBranch(Term, Term, B, Pred);
4290511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        return;
4300511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      }
4310511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4320511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      case Stmt::SwitchStmtClass: {
4330511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        SwitchNodeBuilder builder(Pred, B, cast<SwitchStmt>(Term)->getCond(),
4340511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                    this);
4350511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4360511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        SubEng.processSwitch(builder);
4370511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        return;
4380511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      }
4390511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4400511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      case Stmt::WhileStmtClass:
4410511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        HandleBranch(cast<WhileStmt>(Term)->getCond(), Term, B, Pred);
4420511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com        return;
4430511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    }
4440511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
4450511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4460511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  assert (B->succ_size() == 1 &&
4470511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com          "Blocks with no terminator should have at most 1 successor.");
4480511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4490511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  generateNode(BlockEdge(B, *(B->succ_begin()), Pred->getLocationContext()),
4500511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com               Pred->State, Pred);
4510511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
4520511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4530511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid CoreEngine::HandleBranch(const Stmt *Cond, const Stmt *Term,
4540511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                const CFGBlock * B, ExplodedNode *Pred) {
4550511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  assert(B->succ_size() == 2);
4560511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  NodeBuilderContext Ctx(*this, B, Pred);
4570511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  ExplodedNodeSet Dst;
4580511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  SubEng.processBranch(Cond, Term, Ctx, Pred, Dst,
4590511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                       *(B->succ_begin()), *(B->succ_begin()+1));
4600511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Enqueue the new frontier onto the worklist.
4610511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  enqueue(Dst);
4620511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
4630511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4640511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4650511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid CoreEngine::HandleStaticInit(const DeclStmt *DS, const CFGBlock *B,
4660511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                  ExplodedNode *Pred) {
4670511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  assert(B->succ_size() == 2);
4680511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  NodeBuilderContext Ctx(*this, B, Pred);
4690511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  ExplodedNodeSet Dst;
4700511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  SubEng.processStaticInitializer(DS, Ctx, Pred, Dst,
4710511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                  *(B->succ_begin()), *(B->succ_begin()+1));
4720511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Enqueue the new frontier onto the worklist.
4730511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  enqueue(Dst);
4740511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
4750511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4760511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4770511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid CoreEngine::HandlePostStmt(const CFGBlock *B, unsigned StmtIdx,
4780511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                  ExplodedNode *Pred) {
4790511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  assert(B);
4800511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  assert(!B->empty());
4810511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4820511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (StmtIdx == B->size())
4830511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    HandleBlockExit(B, Pred);
4840511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  else {
4850511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    NodeBuilderContext Ctx(*this, B, Pred);
4860511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    SubEng.processCFGElement((*B)[StmtIdx], Pred, StmtIdx, &Ctx);
4870511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
4880511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
4890511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
4900511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com/// generateNode - Utility method to generate nodes, hook up successors,
4910511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com///  and add nodes to the worklist.
4920511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid CoreEngine::generateNode(const ProgramPoint &Loc,
4930511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                              ProgramStateRef State,
4944f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org                              ExplodedNode *Pred) {
4954f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
4964f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  bool IsNew;
4974f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  ExplodedNode *Node = G->getNode(Loc, State, false, &IsNew);
4984f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
4994f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  if (Pred)
5004f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    Node->addPredecessor(Pred, *G);  // Link 'Node' with its predecessor.
5014f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  else {
5024f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    assert (IsNew);
5034f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    G->addRoot(Node);  // 'Node' has no predecessor.  Make it a root.
5044f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
5054f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
5064f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // Only add 'Node' to the worklist if it was freshly generated.
5074f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  if (IsNew) WList->enqueue(Node);
5084f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org}
5094f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
5104f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.orgvoid CoreEngine::enqueueStmtNode(ExplodedNode *N,
5114f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org                                 const CFGBlock *Block, unsigned Idx) {
5124f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  assert(Block);
5134f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  assert (!N->isSink());
5144f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
5154f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // Check if this node entered a callee.
5164f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  if (N->getLocation().getAs<CallEnter>()) {
5174f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    // Still use the index of the CallExpr. It's needed to create the callee
5184f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    // StackFrameContext.
5194f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    WList->enqueue(N, Block, Idx);
5204f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    return;
5214f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
5224f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
5234f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // Do not create extra nodes. Move to the next CFG element.
5244f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  if (N->getLocation().getAs<PostInitializer>() ||
5254f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      N->getLocation().getAs<PostImplicitCall>()) {
5264f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    WList->enqueue(N, Block, Idx+1);
5274f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    return;
5284f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
5294f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
5304f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  if (N->getLocation().getAs<EpsilonPoint>()) {
5314f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    WList->enqueue(N, Block, Idx);
5324f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    return;
5334f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
5344f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
5354f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  if ((*Block)[Idx].getKind() == CFGElement::NewAllocator) {
5364f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    WList->enqueue(N, Block, Idx+1);
5374f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    return;
5384f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
5394f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
5404f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // At this point, we know we're processing a normal statement.
5414f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  CFGStmt CS = (*Block)[Idx].castAs<CFGStmt>();
5424f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  PostStmt Loc(CS.getStmt(), N->getLocationContext());
5434f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
5444f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  if (Loc == N->getLocation()) {
5454f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    // Note: 'N' should be a fresh node because otherwise it shouldn't be
5464f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    // a member of Deferred.
5474f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    WList->enqueue(N, Block, Idx+1);
5484f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    return;
5494f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
5504f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
5514f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  bool IsNew;
5524f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  ExplodedNode *Succ = G->getNode(Loc, N->getState(), false, &IsNew);
5534f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  Succ->addPredecessor(N, *G);
5544f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
5554f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  if (IsNew)
5564f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    WList->enqueue(Succ, Block, Idx+1);
5574f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org}
5584f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
5594f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.orgExplodedNode *CoreEngine::generateCallExitBeginNode(ExplodedNode *N) {
5604f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // Create a CallExitBegin node and enqueue it.
5614f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  const StackFrameContext *LocCtx
5624f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org                         = cast<StackFrameContext>(N->getLocationContext());
5634f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
5644f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // Use the callee location context.
5654f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  CallExitBegin Loc(LocCtx);
5664f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
5674f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  bool isNew;
5684f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  ExplodedNode *Node = G->getNode(Loc, N->getState(), false, &isNew);
5694f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  Node->addPredecessor(N, *G);
5704f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  return isNew ? Node : 0;
5714f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org}
5724f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
5734f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
5744f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.orgvoid CoreEngine::enqueue(ExplodedNodeSet &Set) {
5754f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  for (ExplodedNodeSet::iterator I = Set.begin(),
5764f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org                                 E = Set.end(); I != E; ++I) {
5774f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    WList->enqueue(*I);
5784f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
5794f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org}
5804f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
5814f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.orgvoid CoreEngine::enqueue(ExplodedNodeSet &Set,
5824f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org                         const CFGBlock *Block, unsigned Idx) {
5834f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  for (ExplodedNodeSet::iterator I = Set.begin(),
5844f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org                                 E = Set.end(); I != E; ++I) {
5854f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    enqueueStmtNode(*I, Block, Idx);
5864f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
5874f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org}
5884f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
5894f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.orgvoid CoreEngine::enqueueEndOfFunction(ExplodedNodeSet &Set) {
5904f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  for (ExplodedNodeSet::iterator I = Set.begin(), E = Set.end(); I != E; ++I) {
5914f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    ExplodedNode *N = *I;
5924f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    // If we are in an inlined call, generate CallExitBegin node.
5934f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    if (N->getLocationContext()->getParent()) {
5944f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      N = generateCallExitBeginNode(N);
5954f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      if (N)
5964f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org        WList->enqueue(N);
5974f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    } else {
5984f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      // TODO: We should run remove dead bindings here.
5994f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      G->addEndOfPath(N);
6004f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      NumPathsExplored++;
6014f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    }
6024f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
6034f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org}
6044f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
6054f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
6064f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.orgvoid NodeBuilder::anchor() { }
6074f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
6084f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.orgExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc,
6094f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org                                            ProgramStateRef State,
6104f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org                                            ExplodedNode *FromN,
6114f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org                                            bool MarkAsSink) {
6124f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  HasGeneratedNodes = true;
6134f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  bool IsNew;
6144f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  ExplodedNode *N = C.Eng.G->getNode(Loc, State, MarkAsSink, &IsNew);
6154f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  N->addPredecessor(FromN, *C.Eng.G);
6164f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  Frontier.erase(FromN);
6174f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
6184f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  if (!IsNew)
6194f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    return 0;
6204f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
6214f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  if (!MarkAsSink)
6224f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    Frontier.Add(N);
6234f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
6240511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  return N;
6250511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
6264f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
6270511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid NodeBuilderWithSinks::anchor() { }
6280511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
6290511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comStmtNodeBuilder::~StmtNodeBuilder() {
6300511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (EnclosingBldr)
6310511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    for (ExplodedNodeSet::iterator I = Frontier.begin(),
6320511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                   E = Frontier.end(); I != E; ++I )
6330511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com      EnclosingBldr->addNodes(*I);
6340511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
6350511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
6360511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comvoid BranchNodeBuilder::anchor() { }
6370511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
6380511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comExplodedNode *BranchNodeBuilder::generateNode(ProgramStateRef State,
6390511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                              bool branch,
6400511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                              ExplodedNode *NodePred) {
6410511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // If the branch has been marked infeasible we should not generate a node.
6420511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (!isFeasible(branch))
6430511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    return NULL;
6440511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
6450511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  ProgramPoint Loc = BlockEdge(C.Block, branch ? DstT:DstF,
6460511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                               NodePred->getLocationContext());
6470511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  ExplodedNode *Succ = generateNodeImpl(Loc, State, NodePred);
6480511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  return Succ;
6490511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
6500511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
6510511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comExplodedNode*
6520511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comIndirectGotoNodeBuilder::generateNode(const iterator &I,
6530511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                      ProgramStateRef St,
6540511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                      bool IsSink) {
6550511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  bool IsNew;
6560511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
6570511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                      Pred->getLocationContext()), St,
6580511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                      IsSink, &IsNew);
6590511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  Succ->addPredecessor(Pred, *Eng.G);
6600511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
6610511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (!IsNew)
6620511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    return 0;
6630511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
6640511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (!IsSink)
6650511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Eng.WList->enqueue(Succ);
6660511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
6670511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  return Succ;
6680511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
6690511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
6700511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
6710511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comExplodedNode*
67249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.orgSwitchNodeBuilder::generateCaseStmtNode(const iterator &I,
6730511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                        ProgramStateRef St) {
6740511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
6750511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  bool IsNew;
6760511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
6770511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                      Pred->getLocationContext()), St,
6780511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                      false, &IsNew);
6790511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  Succ->addPredecessor(Pred, *Eng.G);
6800511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (!IsNew)
6810511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    return 0;
6820511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
6830511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  Eng.WList->enqueue(Succ);
6840511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  return Succ;
6850511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
6860511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
6870511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
6880511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comExplodedNode*
6890511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.comSwitchNodeBuilder::generateDefaultCaseNode(ProgramStateRef St,
69049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org                                           bool IsSink) {
69149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // Get the block for the default case.
69249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  assert(Src->succ_rbegin() != Src->succ_rend());
69349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  CFGBlock *DefaultBlock = *Src->succ_rbegin();
6940511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
6950511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Sanity check for default blocks that are unreachable and not caught
6960511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // by earlier stages.
6970511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (!DefaultBlock)
6980511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    return NULL;
6990511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
7000511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  bool IsNew;
7010511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, DefaultBlock,
7020511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                      Pred->getLocationContext()), St,
7030511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com                                      IsSink, &IsNew);
7040511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  Succ->addPredecessor(Pred, *Eng.G);
7050511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
7060511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (!IsNew)
7070511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    return 0;
7080511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
7090511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (!IsSink)
7100511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    Eng.WList->enqueue(Succ);
7110511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com
7120511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  return Succ;
7130511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com}
7140511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com