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