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