| //===--- CFGStmtMap.h - Map from Stmt* to CFGBlock* -----------*- C++ -*-===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | // | 
 | //  This file defines the CFGStmtMap class, which defines a mapping from | 
 | //  Stmt* to CFGBlock* | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "llvm/ADT/DenseMap.h" | 
 | #include "clang/AST/ParentMap.h" | 
 | #include "clang/Analysis/CFG.h" | 
 | #include "clang/Analysis/CFGStmtMap.h" | 
 |  | 
 | using namespace clang; | 
 |  | 
 | typedef llvm::DenseMap<Stmt*,CFGBlock*> SMap; | 
 | static SMap *AsMap(void *m) { return (SMap*) m; } | 
 |  | 
 | CFGStmtMap::~CFGStmtMap() { delete AsMap(M); } | 
 |  | 
 | CFGBlock *CFGStmtMap::getBlock(Stmt *S) {   | 
 |   SMap *SM = AsMap(M); | 
 |   Stmt *X = S; | 
 |  | 
 |   // If 'S' isn't in the map, walk the ParentMap to see if one of its ancestors | 
 |   // is in the map. | 
 |   while (X) { | 
 |     SMap::iterator I = SM->find(X); | 
 |     if (I != SM->end()) { | 
 |       CFGBlock *B = I->second; | 
 |       // Memoize this lookup. | 
 |       if (X != S) | 
 |         (*SM)[X] = B; | 
 |       return B; | 
 |     } | 
 |  | 
 |     X = PM->getParentIgnoreParens(X); | 
 |   } | 
 |    | 
 |   return 0; | 
 | } | 
 |  | 
 | static void Accumulate(SMap &SM, CFGBlock *B) { | 
 |   // First walk the block-level expressions. | 
 |   for (CFGBlock::iterator I = B->begin(), E = B->end(); I != E; ++I) { | 
 |     const CFGElement &CE = *I; | 
 |     CFGStmt CS = CE.getAs<CFGStmt>(); | 
 |     if (!CS.isValid()) | 
 |       continue; | 
 |      | 
 |     CFGBlock *&Entry = SM[CS]; | 
 |     // If 'Entry' is already initialized (e.g., a terminator was already), | 
 |     // skip. | 
 |     if (Entry) | 
 |       continue; | 
 |        | 
 |     Entry = B; | 
 |      | 
 |   } | 
 |    | 
 |   // Look at the label of the block. | 
 |   if (Stmt *Label = B->getLabel()) | 
 |     SM[Label] = B; | 
 |  | 
 |   // Finally, look at the terminator.  If the terminator was already added | 
 |   // because it is a block-level expression in another block, overwrite | 
 |   // that mapping. | 
 |   if (Stmt *Term = B->getTerminator()) | 
 |     SM[Term] = B; | 
 | } | 
 |  | 
 | CFGStmtMap *CFGStmtMap::Build(CFG *C, ParentMap *PM) { | 
 |   if (!C || !PM) | 
 |     return 0; | 
 |  | 
 |   SMap *SM = new SMap(); | 
 |  | 
 |   // Walk all blocks, accumulating the block-level expressions, labels, | 
 |   // and terminators.   | 
 |   for (CFG::iterator I = C->begin(), E = C->end(); I != E; ++I) | 
 |     Accumulate(*SM, *I); | 
 |  | 
 |   return new CFGStmtMap(PM, SM); | 
 | } | 
 |  |