CFGStmtMap.cpp revision b36cd3e1757fb4fcd9509f35558c847b04bef35f
1//===--- CFGStmtMap.h - Map from Stmt* to CFGBlock* -----------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file defines the CFGStmtMap class, which defines a mapping from
11//  Stmt* to CFGBlock*
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/ADT/DenseMap.h"
16#include "clang/AST/ParentMap.h"
17#include "clang/Analysis/CFG.h"
18#include "clang/Analysis/CFGStmtMap.h"
19
20using namespace clang;
21
22typedef llvm::DenseMap<Stmt*,CFGBlock*> SMap;
23static SMap *AsMap(void *m) { return (SMap*) m; }
24
25CFGStmtMap::~CFGStmtMap() { delete AsMap(M); }
26
27CFGBlock *CFGStmtMap::getBlock(Stmt *S) {
28  SMap *SM = AsMap(M);
29  Stmt *X = S;
30
31  // If 'S' isn't in the map, walk the ParentMap to see if one of its ancestors
32  // is in the map.
33  while (X) {
34    SMap::iterator I = SM->find(X);
35    if (I != SM->end()) {
36      CFGBlock *B = I->second;
37      // Memoize this lookup.
38      if (X != S)
39        (*SM)[X] = B;
40      return B;
41    }
42
43    X = PM->getParentIgnoreParens(X);
44  }
45
46  return 0;
47}
48
49static void Accumulate(SMap &SM, CFGBlock *B) {
50  // First walk the block-level expressions.
51  for (CFGBlock::iterator I = B->begin(), E = B->end(); I != E; ++I) {
52    const CFGElement &CE = *I;
53    CFGStmt CS = CE.getAs<CFGStmt>();
54    if (!CS.isValid())
55      continue;
56
57    CFGBlock *&Entry = SM[CS];
58    // If 'Entry' is already initialized (e.g., a terminator was already),
59    // skip.
60    if (Entry)
61      continue;
62
63    Entry = B;
64
65  }
66
67  // Look at the label of the block.
68  if (Stmt *Label = B->getLabel())
69    SM[Label] = B;
70
71  // Finally, look at the terminator.  If the terminator was already added
72  // because it is a block-level expression in another block, overwrite
73  // that mapping.
74  if (Stmt *Term = B->getTerminator())
75    SM[Term] = B;
76}
77
78CFGStmtMap *CFGStmtMap::Build(CFG *C, ParentMap *PM) {
79  if (!C || !PM)
80    return 0;
81
82  SMap *SM = new SMap();
83
84  // Walk all blocks, accumulating the block-level expressions, labels,
85  // and terminators.
86  for (CFG::iterator I = C->begin(), E = C->end(); I != E; ++I)
87    Accumulate(*SM, *I);
88
89  return new CFGStmtMap(PM, SM);
90}
91
92