aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/ReachableCode.cpp
blob: 269aaf02c181733a32636d04c4812b3e6442ce8e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//=- ReachableCodePathInsensitive.cpp ---------------------------*- C++ --*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a flow-sensitive, path-insensitive analysis of
// determining reachable blocks within a CFG.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallVector.h"
#include "clang/Analysis/Analyses/ReachableCode.h"
#include "clang/Analysis/CFG.h"

using namespace clang;

/// ScanReachableFromBlock - Mark all blocks reachable from Start.
/// Returns the total number of blocks that were marked reachable.
unsigned clang::ScanReachableFromBlock(const CFGBlock &Start,
                                       llvm::BitVector &Reachable) {
  unsigned count = 0;
  llvm::SmallVector<const CFGBlock*, 12> WL;
  
  // Prep work queue
  Reachable.set(Start.getBlockID());
  ++count;
  WL.push_back(&Start);
  
  // Find the reachable blocks from 'Start'.
  while (!WL.empty()) {
    const CFGBlock *item = WL.back();
    WL.pop_back();
    
    // Look at the successors and mark then reachable.
    for (CFGBlock::const_succ_iterator I=item->succ_begin(), E=item->succ_end();
         I != E; ++I)
      if (const CFGBlock *B = *I) {
        unsigned blockID = B->getBlockID();
        if (!Reachable[blockID]) {
          Reachable.set(blockID);
          ++count;
          WL.push_back(B);
        }
      }
  }
  return count;
}