10b57cec5SDimitry Andric //===--- CFGStmtMap.h - Map from Stmt* to CFGBlock* -----------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the CFGStmtMap class, which defines a mapping from
100b57cec5SDimitry Andric // Stmt* to CFGBlock*
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
150b57cec5SDimitry Andric #include "clang/AST/ParentMap.h"
160b57cec5SDimitry Andric #include "clang/Analysis/CFG.h"
170b57cec5SDimitry Andric #include "clang/Analysis/CFGStmtMap.h"
18*bdd1243dSDimitry Andric #include <optional>
190b57cec5SDimitry Andric
200b57cec5SDimitry Andric using namespace clang;
210b57cec5SDimitry Andric
220b57cec5SDimitry Andric typedef llvm::DenseMap<const Stmt*, CFGBlock*> SMap;
AsMap(void * m)230b57cec5SDimitry Andric static SMap *AsMap(void *m) { return (SMap*) m; }
240b57cec5SDimitry Andric
~CFGStmtMap()250b57cec5SDimitry Andric CFGStmtMap::~CFGStmtMap() { delete AsMap(M); }
260b57cec5SDimitry Andric
getBlock(Stmt * S)270b57cec5SDimitry Andric CFGBlock *CFGStmtMap::getBlock(Stmt *S) {
280b57cec5SDimitry Andric SMap *SM = AsMap(M);
290b57cec5SDimitry Andric Stmt *X = S;
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric // If 'S' isn't in the map, walk the ParentMap to see if one of its ancestors
320b57cec5SDimitry Andric // is in the map.
330b57cec5SDimitry Andric while (X) {
340b57cec5SDimitry Andric SMap::iterator I = SM->find(X);
350b57cec5SDimitry Andric if (I != SM->end()) {
360b57cec5SDimitry Andric CFGBlock *B = I->second;
370b57cec5SDimitry Andric // Memoize this lookup.
380b57cec5SDimitry Andric if (X != S)
390b57cec5SDimitry Andric (*SM)[X] = B;
400b57cec5SDimitry Andric return B;
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric
430b57cec5SDimitry Andric X = PM->getParentIgnoreParens(X);
440b57cec5SDimitry Andric }
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric return nullptr;
470b57cec5SDimitry Andric }
480b57cec5SDimitry Andric
Accumulate(SMap & SM,CFGBlock * B)490b57cec5SDimitry Andric static void Accumulate(SMap &SM, CFGBlock *B) {
500b57cec5SDimitry Andric // First walk the block-level expressions.
510b57cec5SDimitry Andric for (CFGBlock::iterator I = B->begin(), E = B->end(); I != E; ++I) {
520b57cec5SDimitry Andric const CFGElement &CE = *I;
53*bdd1243dSDimitry Andric std::optional<CFGStmt> CS = CE.getAs<CFGStmt>();
540b57cec5SDimitry Andric if (!CS)
550b57cec5SDimitry Andric continue;
560b57cec5SDimitry Andric
570b57cec5SDimitry Andric CFGBlock *&Entry = SM[CS->getStmt()];
580b57cec5SDimitry Andric // If 'Entry' is already initialized (e.g., a terminator was already),
590b57cec5SDimitry Andric // skip.
600b57cec5SDimitry Andric if (Entry)
610b57cec5SDimitry Andric continue;
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric Entry = B;
640b57cec5SDimitry Andric
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric
670b57cec5SDimitry Andric // Look at the label of the block.
680b57cec5SDimitry Andric if (Stmt *Label = B->getLabel())
690b57cec5SDimitry Andric SM[Label] = B;
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric // Finally, look at the terminator. If the terminator was already added
720b57cec5SDimitry Andric // because it is a block-level expression in another block, overwrite
730b57cec5SDimitry Andric // that mapping.
740b57cec5SDimitry Andric if (Stmt *Term = B->getTerminatorStmt())
750b57cec5SDimitry Andric SM[Term] = B;
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric
Build(CFG * C,ParentMap * PM)780b57cec5SDimitry Andric CFGStmtMap *CFGStmtMap::Build(CFG *C, ParentMap *PM) {
790b57cec5SDimitry Andric if (!C || !PM)
800b57cec5SDimitry Andric return nullptr;
810b57cec5SDimitry Andric
820b57cec5SDimitry Andric SMap *SM = new SMap();
830b57cec5SDimitry Andric
840b57cec5SDimitry Andric // Walk all blocks, accumulating the block-level expressions, labels,
850b57cec5SDimitry Andric // and terminators.
860b57cec5SDimitry Andric for (CFG::iterator I = C->begin(), E = C->end(); I != E; ++I)
870b57cec5SDimitry Andric Accumulate(*SM, *I);
880b57cec5SDimitry Andric
890b57cec5SDimitry Andric return new CFGStmtMap(PM, SM);
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric
92