mboehme created this revision.
Herald added subscribers: martong, xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
mboehme requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Instead of `StmtToEnvMap`, we pass an `AnalysisContext`, which contains all of
the data that `StmtToEnvMapImpl` required to implement its sole member function,
getEnvironment().
The layering issue that originally required the indirection through the
`StmtToEnvMap` interface no longer exists.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D146507
Files:
clang/include/clang/Analysis/FlowSensitive/Transfer.h
clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
clang/lib/Analysis/FlowSensitive/Transfer.cpp
clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
Index: clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -40,27 +40,6 @@
namespace clang {
namespace dataflow {
-class StmtToEnvMapImpl : public StmtToEnvMap {
-public:
- StmtToEnvMapImpl(
- const ControlFlowContext &CFCtx,
- llvm::ArrayRef<std::optional<TypeErasedDataflowAnalysisState>>
- BlockToState)
- : CFCtx(CFCtx), BlockToState(BlockToState) {}
-
- const Environment *getEnvironment(const Stmt &S) const override {
- auto BlockIt = CFCtx.getStmtToBlock().find(&ignoreCFGOmittedNodes(S));
- assert(BlockIt != CFCtx.getStmtToBlock().end());
- const auto &State = BlockToState[BlockIt->getSecond()->getBlockID()];
- assert(State);
- return &State->Env;
- }
-
-private:
- const ControlFlowContext &CFCtx;
- llvm::ArrayRef<std::optional<TypeErasedDataflowAnalysisState>> BlockToState;
-};
-
/// Returns the index of `Block` in the successors of `Pred`.
static int blockIndexInPredecessor(const CFGBlock &Pred,
const CFGBlock &Block) {
@@ -96,9 +75,9 @@
class TerminatorVisitor
: public ConstStmtVisitor<TerminatorVisitor, TerminatorVisitorRetTy> {
public:
- TerminatorVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env,
+ TerminatorVisitor(const AnalysisContext &AC, Environment &Env,
int BlockSuccIdx)
- : StmtToEnv(StmtToEnv), Env(Env), BlockSuccIdx(BlockSuccIdx) {}
+ : AC(AC), Env(Env), BlockSuccIdx(BlockSuccIdx) {}
TerminatorVisitorRetTy VisitIfStmt(const IfStmt *S) {
auto *Cond = S->getCond();
@@ -143,7 +122,7 @@
TerminatorVisitorRetTy extendFlowCondition(const Expr &Cond) {
// The terminator sub-expression might not be evaluated.
if (Env.getStorageLocation(Cond, SkipPast::None) == nullptr)
- transfer(StmtToEnv, Cond, Env);
+ transfer(AC, Cond, Env);
// FIXME: The flow condition must be an r-value, so `SkipPast::None` should
// suffice.
@@ -176,32 +155,11 @@
return {&Cond, ConditionValue};
}
- const StmtToEnvMap &StmtToEnv;
+ const AnalysisContext &AC;
Environment &Env;
int BlockSuccIdx;
};
-/// Holds data structures required for running dataflow analysis.
-struct AnalysisContext {
- AnalysisContext(const ControlFlowContext &CFCtx,
- TypeErasedDataflowAnalysis &Analysis,
- const Environment &InitEnv,
- llvm::ArrayRef<std::optional<TypeErasedDataflowAnalysisState>>
- BlockStates)
- : CFCtx(CFCtx), Analysis(Analysis), InitEnv(InitEnv),
- BlockStates(BlockStates) {}
-
- /// Contains the CFG being analyzed.
- const ControlFlowContext &CFCtx;
- /// The analysis to be run.
- TypeErasedDataflowAnalysis &Analysis;
- /// Initial state to start the analysis.
- const Environment &InitEnv;
- /// Stores the state of a CFG block if it has been evaluated by the analysis.
- /// The indices correspond to the block IDs.
- llvm::ArrayRef<std::optional<TypeErasedDataflowAnalysisState>> BlockStates;
-};
-
/// Computes the input state for a given basic block by joining the output
/// states of its predecessors.
///
@@ -263,9 +221,8 @@
TypeErasedDataflowAnalysisState PredState = *MaybePredState;
if (Analysis.builtinOptions()) {
if (const Stmt *PredTerminatorStmt = Pred->getTerminatorStmt()) {
- const StmtToEnvMapImpl StmtToEnv(AC.CFCtx, AC.BlockStates);
auto [Cond, CondValue] =
- TerminatorVisitor(StmtToEnv, PredState.Env,
+ TerminatorVisitor(AC, PredState.Env,
blockIndexInPredecessor(*Pred, Block))
.Visit(PredTerminatorStmt);
if (Cond != nullptr)
@@ -298,7 +255,7 @@
AnalysisContext &AC) {
const Stmt *S = Elt.getStmt();
assert(S != nullptr);
- transfer(StmtToEnvMapImpl(AC.CFCtx, AC.BlockStates), *S, InputState.Env);
+ transfer(AC, *S, InputState.Env);
}
/// Built-in transfer function for `CFGInitializer`.
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/FlowSensitive/Transfer.h"
+#include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
@@ -129,10 +130,19 @@
return &UnpackedVal;
}
+static const Environment *getEnvironment(const Stmt &S,
+ const AnalysisContext &AC) {
+ auto BlockIt = AC.CFCtx.getStmtToBlock().find(&ignoreCFGOmittedNodes(S));
+ assert(BlockIt != AC.CFCtx.getStmtToBlock().end());
+ const auto &State = AC.BlockStates[BlockIt->getSecond()->getBlockID()];
+ assert(State);
+ return &State->Env;
+}
+
class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
public:
- TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env)
- : StmtToEnv(StmtToEnv), Env(Env) {}
+ TransferVisitor(const AnalysisContext &AC, Environment &Env)
+ : AC(AC), Env(Env) {}
void VisitBinaryOperator(const BinaryOperator *S) {
const Expr *LHS = S->getLHS();
@@ -783,7 +793,7 @@
// `SubExpr` and its parent logic operator might be part of different basic
// blocks. We try to access the value that is assigned to `SubExpr` in the
// corresponding environment.
- if (const Environment *SubExprEnv = StmtToEnv.getEnvironment(SubExpr)) {
+ if (const Environment *SubExprEnv = getEnvironment(SubExpr, AC)) {
if (auto *Val = dyn_cast_or_null<BoolValue>(
SubExprEnv->getValue(SubExpr, SkipPast::Reference)))
return *Val;
@@ -854,12 +864,12 @@
Env.popCall(ExitState->Env);
}
- const StmtToEnvMap &StmtToEnv;
+ const AnalysisContext &AC;
Environment &Env;
};
-void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env) {
- TransferVisitor(StmtToEnv, Env).Visit(&S);
+void transfer(const AnalysisContext &AC, const Stmt &S, Environment &Env) {
+ TransferVisitor(AC, Env).Visit(&S);
}
} // namespace dataflow
Index: clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
===================================================================
--- clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
@@ -128,6 +128,27 @@
: Lattice(std::move(Lattice)), Env(std::move(Env)) {}
};
+/// Holds data structures required for running dataflow analysis.
+struct AnalysisContext {
+ AnalysisContext(const ControlFlowContext &CFCtx,
+ TypeErasedDataflowAnalysis &Analysis,
+ const Environment &InitEnv,
+ llvm::ArrayRef<std::optional<TypeErasedDataflowAnalysisState>>
+ BlockStates)
+ : CFCtx(CFCtx), Analysis(Analysis), InitEnv(InitEnv),
+ BlockStates(BlockStates) {}
+
+ /// Contains the CFG being analyzed.
+ const ControlFlowContext &CFCtx;
+ /// The analysis to be run.
+ TypeErasedDataflowAnalysis &Analysis;
+ /// Initial state to start the analysis.
+ const Environment &InitEnv;
+ /// Stores the state of a CFG block if it has been evaluated by the analysis.
+ /// The indices correspond to the block IDs.
+ llvm::ArrayRef<std::optional<TypeErasedDataflowAnalysisState>> BlockStates;
+};
+
/// Transfers the state of a basic block by evaluating each of its elements in
/// the context of `Analysis` and the states of its predecessors that are
/// available in `BlockStates`. `PostVisitCFG` (if provided) will be applied to
Index: clang/include/clang/Analysis/FlowSensitive/Transfer.h
===================================================================
--- clang/include/clang/Analysis/FlowSensitive/Transfer.h
+++ clang/include/clang/Analysis/FlowSensitive/Transfer.h
@@ -17,27 +17,17 @@
#include "clang/AST/Stmt.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
namespace clang {
namespace dataflow {
-/// Maps statements to the environments of basic blocks that contain them.
-class StmtToEnvMap {
-public:
- virtual ~StmtToEnvMap() = default;
-
- /// Returns the environment of the basic block that contains `S` or nullptr if
- /// there isn't one.
- /// FIXME: Ensure that the result can't be null and return a const reference.
- virtual const Environment *getEnvironment(const Stmt &S) const = 0;
-};
-
/// Evaluates `S` and updates `Env` accordingly.
///
/// Requirements:
///
/// `S` must not be `ParenExpr` or `ExprWithCleanups`.
-void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env);
+void transfer(const AnalysisContext &AC, const Stmt &S, Environment &Env);
} // namespace dataflow
} // namespace clang
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits