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