clang API Documentation
00001 //==- CFGReachabilityAnalysis.cpp - Basic reachability analysis --*- C++ -*-==// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines a flow-sensitive, (mostly) path-insensitive reachability 00011 // analysis based on Clang's CFGs. Clients can query if a given basic block 00012 // is reachable within the CFG. 00013 // 00014 //===----------------------------------------------------------------------===// 00015 00016 #include "llvm/ADT/SmallVector.h" 00017 #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" 00018 #include "clang/Analysis/CFG.h" 00019 00020 using namespace clang; 00021 00022 CFGReverseBlockReachabilityAnalysis::CFGReverseBlockReachabilityAnalysis(const CFG &cfg) 00023 : analyzed(cfg.getNumBlockIDs(), false) {} 00024 00025 bool CFGReverseBlockReachabilityAnalysis::isReachable(const CFGBlock *Src, 00026 const CFGBlock *Dst) { 00027 00028 const unsigned DstBlockID = Dst->getBlockID(); 00029 00030 // If we haven't analyzed the destination node, run the analysis now 00031 if (!analyzed[DstBlockID]) { 00032 mapReachability(Dst); 00033 analyzed[DstBlockID] = true; 00034 } 00035 00036 // Return the cached result 00037 return reachable[DstBlockID][Src->getBlockID()]; 00038 } 00039 00040 // Maps reachability to a common node by walking the predecessors of the 00041 // destination node. 00042 void CFGReverseBlockReachabilityAnalysis::mapReachability(const CFGBlock *Dst) { 00043 SmallVector<const CFGBlock *, 11> worklist; 00044 llvm::BitVector visited(analyzed.size()); 00045 00046 ReachableSet &DstReachability = reachable[Dst->getBlockID()]; 00047 DstReachability.resize(analyzed.size(), false); 00048 00049 // Start searching from the destination node, since we commonly will perform 00050 // multiple queries relating to a destination node. 00051 worklist.push_back(Dst); 00052 bool firstRun = true; 00053 00054 while (!worklist.empty()) { 00055 const CFGBlock *block = worklist.pop_back_val(); 00056 00057 if (visited[block->getBlockID()]) 00058 continue; 00059 visited[block->getBlockID()] = true; 00060 00061 // Update reachability information for this node -> Dst 00062 if (!firstRun) { 00063 // Don't insert Dst -> Dst unless it was a predecessor of itself 00064 DstReachability[block->getBlockID()] = true; 00065 } 00066 else 00067 firstRun = false; 00068 00069 // Add the predecessors to the worklist. 00070 for (CFGBlock::const_pred_iterator i = block->pred_begin(), 00071 e = block->pred_end(); i != e; ++i) { 00072 if (*i) 00073 worklist.push_back(*i); 00074 } 00075 } 00076 }