blob: ae8955922fef54a9b3958d09d2dd3e400f430933 [file] [log] [blame] [edit]
//===--- CFGStmtMap.h - Map from Stmt* to CFGBlock* -----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the CFGStmtMap class, which defines a mapping from
// Stmt* to CFGBlock*
//
//===----------------------------------------------------------------------===//
#include "clang/AST/ParentMap.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CFGStmtMap.h"
#include <optional>
using namespace clang;
const CFGBlock *CFGStmtMap::getBlock(const Stmt *S) const {
const Stmt *X = S;
// If 'S' isn't in the map, walk the ParentMap to see if one of its ancestors
// is in the map.
while (X) {
auto I = M.find(X);
if (I != M.end())
return I->second;
X = PM->getParentIgnoreParens(X);
}
return nullptr;
}
CFGStmtMap::CFGStmtMap(const CFG &C, const ParentMap &PM) : PM(&PM) {
// Walk all blocks, accumulating the block-level expressions, labels,
// and terminators.
for (const CFGBlock *B : C) {
// First walk the block-level expressions.
for (const CFGElement &CE : *B) {
if (std::optional<CFGStmt> CS = CE.getAs<CFGStmt>())
M.try_emplace(CS->getStmt(), B);
}
// Look at the label of the block.
if (const Stmt *Label = B->getLabel())
M[Label] = B;
// Finally, look at the terminator. If the terminator was already added
// because it is a block-level expression in another block, overwrite
// that mapping.
if (const Stmt *Term = B->getTerminatorStmt())
M[Term] = B;
}
}