clang 20.0.0 (based on r547379) from build 12806354. Bug: http://b/379133546 Test: N/A Change-Id: I2eb8938af55d809de674be63cb30cf27e801862b Upstream-Commit: ad834e67b1105d15ef907f6255d4c96e8e733f57
112 lines
4.0 KiB
C++
112 lines
4.0 KiB
C++
//===-- AdornedCFG.h ------------------------------------*- 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 an AdornedCFG class that is used by dataflow analyses that
|
|
// run over Control-Flow Graphs (CFGs).
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ADORNEDCFG_H
|
|
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ADORNEDCFG_H
|
|
|
|
#include "clang/AST/ASTContext.h"
|
|
#include "clang/AST/Decl.h"
|
|
#include "clang/AST/Stmt.h"
|
|
#include "clang/Analysis/CFG.h"
|
|
#include "clang/Analysis/FlowSensitive/ASTOps.h"
|
|
#include "llvm/ADT/BitVector.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/Support/Error.h"
|
|
#include <memory>
|
|
#include <utility>
|
|
|
|
namespace clang {
|
|
namespace dataflow {
|
|
|
|
namespace internal {
|
|
class StmtToBlockMap {
|
|
public:
|
|
StmtToBlockMap(const CFG &Cfg);
|
|
|
|
const CFGBlock *lookup(const Stmt &S) const {
|
|
return StmtToBlock.lookup(&ignoreCFGOmittedNodes(S));
|
|
}
|
|
|
|
private:
|
|
llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock;
|
|
};
|
|
} // namespace internal
|
|
|
|
/// Holds CFG with additional information derived from it that is needed to
|
|
/// perform dataflow analysis.
|
|
class AdornedCFG {
|
|
public:
|
|
/// Builds an `AdornedCFG` from a `FunctionDecl`.
|
|
/// `Func.doesThisDeclarationHaveABody()` must be true, and
|
|
/// `Func.isTemplated()` must be false.
|
|
static llvm::Expected<AdornedCFG> build(const FunctionDecl &Func);
|
|
|
|
/// Builds an `AdornedCFG` from an AST node. `D` is the function in which
|
|
/// `S` resides. `D.isTemplated()` must be false.
|
|
static llvm::Expected<AdornedCFG> build(const Decl &D, Stmt &S,
|
|
ASTContext &C);
|
|
|
|
/// Returns the `Decl` containing the statement used to construct the CFG, if
|
|
/// available.
|
|
const Decl &getDecl() const { return ContainingDecl; }
|
|
|
|
/// Returns the CFG that is stored in this context.
|
|
const CFG &getCFG() const { return *Cfg; }
|
|
|
|
/// Returns the basic block that contains `S`, or null if no basic block
|
|
/// containing `S` is found.
|
|
const CFGBlock *blockForStmt(const Stmt &S) const {
|
|
return StmtToBlock.lookup(S);
|
|
}
|
|
|
|
/// Returns whether `B` is reachable from the entry block.
|
|
bool isBlockReachable(const CFGBlock &B) const {
|
|
return BlockReachable[B.getBlockID()];
|
|
}
|
|
|
|
/// Returns whether `B` contains an expression that is consumed in a
|
|
/// different block than `B` (i.e. the parent of the expression is in a
|
|
/// different block).
|
|
/// This happens if there is control flow within a full-expression (triggered
|
|
/// by `&&`, `||`, or the conditional operator). Note that the operands of
|
|
/// these operators are not the only expressions that can be consumed in a
|
|
/// different block. For example, in the function call
|
|
/// `f(&i, cond() ? 1 : 0)`, `&i` is in a different block than the `CallExpr`.
|
|
bool containsExprConsumedInDifferentBlock(const CFGBlock &B) const {
|
|
return ContainsExprConsumedInDifferentBlock.contains(&B);
|
|
}
|
|
|
|
private:
|
|
AdornedCFG(
|
|
const Decl &D, std::unique_ptr<CFG> Cfg,
|
|
internal::StmtToBlockMap StmtToBlock, llvm::BitVector BlockReachable,
|
|
llvm::DenseSet<const CFGBlock *> ContainsExprConsumedInDifferentBlock)
|
|
: ContainingDecl(D), Cfg(std::move(Cfg)),
|
|
StmtToBlock(std::move(StmtToBlock)),
|
|
BlockReachable(std::move(BlockReachable)),
|
|
ContainsExprConsumedInDifferentBlock(
|
|
std::move(ContainsExprConsumedInDifferentBlock)) {}
|
|
|
|
/// The `Decl` containing the statement used to construct the CFG.
|
|
const Decl &ContainingDecl;
|
|
std::unique_ptr<CFG> Cfg;
|
|
internal::StmtToBlockMap StmtToBlock;
|
|
llvm::BitVector BlockReachable;
|
|
llvm::DenseSet<const CFGBlock *> ContainsExprConsumedInDifferentBlock;
|
|
};
|
|
|
|
} // namespace dataflow
|
|
} // namespace clang
|
|
|
|
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ADORNEDCFG_H
|