clang API Documentation

CFGReachabilityAnalysis.cpp
Go to the documentation of this file.
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 }