Skip to content

[clang][dataflow][NFC] Rename ControlFlowContext to AdornedCFG. #85640

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion clang/docs/tools/clang-formatted-files.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ clang/include/clang/Analysis/MacroExpansionContext.h
clang/include/clang/Analysis/Analyses/CalledOnceCheck.h
clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
clang/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h
clang/include/clang/Analysis/FlowSensitive/AdornedCFG.h
clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
Expand Down Expand Up @@ -306,7 +307,7 @@ clang/include/clang-c/Index.h
clang/lib/Analysis/CalledOnceCheck.cpp
clang/lib/Analysis/CloneDetection.cpp
clang/lib/Analysis/CodeInjector.cpp
clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
clang/lib/Analysis/FlowSensitive/AdornedCFG.cpp
clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
clang/lib/Analysis/FlowSensitive/DebugSupport.cpp
Expand Down
96 changes: 96 additions & 0 deletions clang/include/clang/Analysis/FlowSensitive/AdornedCFG.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//===-- 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 "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Error.h"
#include <memory>
#include <utility>

namespace clang {
namespace dataflow {

/// 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 a mapping from statements to basic blocks that contain them.
const llvm::DenseMap<const Stmt *, const CFGBlock *> &getStmtToBlock() const {
return StmtToBlock;
}

/// 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,
llvm::DenseMap<const Stmt *, const CFGBlock *> 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;
llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock;
llvm::BitVector BlockReachable;
llvm::DenseSet<const CFGBlock *> ContainsExprConsumedInDifferentBlock;
};

} // namespace dataflow
} // namespace clang

#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ADORNEDCFG_H
77 changes: 4 additions & 73 deletions clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,89 +6,20 @@
//
//===----------------------------------------------------------------------===//
//
// This file defines a ControlFlowContext class that is used by dataflow
// analyses that run over Control-Flow Graphs (CFGs).
// This file defines a deprecated alias for AdornedCFG.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CONTROLFLOWCONTEXT_H
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CONTROLFLOWCONTEXT_H

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Stmt.h"
#include "clang/Analysis/CFG.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Error.h"
#include <memory>
#include <utility>
#include "clang/Analysis/FlowSensitive/AdornedCFG.h"

namespace clang {
namespace dataflow {

/// Holds CFG and other derived context that is needed to perform dataflow
/// analysis.
class ControlFlowContext {
public:
/// Builds a ControlFlowContext from a `FunctionDecl`.
/// `Func.doesThisDeclarationHaveABody()` must be true, and
/// `Func.isTemplated()` must be false.
static llvm::Expected<ControlFlowContext> build(const FunctionDecl &Func);

/// Builds a ControlFlowContext from an AST node. `D` is the function in which
/// `S` resides. `D.isTemplated()` must be false.
static llvm::Expected<ControlFlowContext> 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 a mapping from statements to basic blocks that contain them.
const llvm::DenseMap<const Stmt *, const CFGBlock *> &getStmtToBlock() const {
return StmtToBlock;
}

/// 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:
ControlFlowContext(
const Decl &D, std::unique_ptr<CFG> Cfg,
llvm::DenseMap<const Stmt *, const CFGBlock *> 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;
llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock;
llvm::BitVector BlockReachable;
llvm::DenseSet<const CFGBlock *> ContainsExprConsumedInDifferentBlock;
};
// This is a deprecated alias. Use `AdornedCFG` instead.
using ControlFlowContext = AdornedCFG;

} // namespace dataflow
} // namespace clang
Expand Down
10 changes: 4 additions & 6 deletions clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

#include "clang/AST/ASTContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
#include "clang/Analysis/FlowSensitive/AdornedCFG.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
#include "clang/Analysis/FlowSensitive/MatchSwitch.h"
Expand Down Expand Up @@ -195,8 +195,7 @@ template <typename AnalysisT>
llvm::Expected<std::vector<
std::optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>>
runDataflowAnalysis(
const ControlFlowContext &CFCtx, AnalysisT &Analysis,
const Environment &InitEnv,
const AdornedCFG &ACFG, AnalysisT &Analysis, const Environment &InitEnv,
std::function<void(const CFGElement &, const DataflowAnalysisState<
typename AnalysisT::Lattice> &)>
PostVisitCFG = nullptr,
Expand All @@ -218,7 +217,7 @@ runDataflowAnalysis(
}

auto TypeErasedBlockStates = runTypeErasedDataflowAnalysis(
CFCtx, Analysis, InitEnv, PostVisitCFGClosure, MaxBlockVisits);
ACFG, Analysis, InitEnv, PostVisitCFGClosure, MaxBlockVisits);
if (!TypeErasedBlockStates)
return TypeErasedBlockStates.takeError();

Expand Down Expand Up @@ -280,8 +279,7 @@ llvm::Expected<llvm::SmallVector<Diagnostic>> diagnoseFunction(
Diagnoser,
std::int64_t MaxSATIterations = 1'000'000'000,
std::int32_t MaxBlockVisits = 20'000) {
llvm::Expected<ControlFlowContext> Context =
ControlFlowContext::build(FuncDecl);
llvm::Expected<AdornedCFG> Context = AdornedCFG::build(FuncDecl);
if (!Context)
return Context.takeError();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Analysis/FlowSensitive/AdornedCFG.h"
#include "clang/Analysis/FlowSensitive/Arena.h"
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
#include "clang/Analysis/FlowSensitive/Solver.h"
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
#include "clang/Analysis/FlowSensitive/Value.h"
Expand Down Expand Up @@ -183,9 +183,9 @@ class DataflowAnalysisContext {
LLVM_DUMP_METHOD void dumpFlowCondition(Atom Token,
llvm::raw_ostream &OS = llvm::dbgs());

/// Returns the `ControlFlowContext` registered for `F`, if any. Otherwise,
/// Returns the `AdornedCFG` registered for `F`, if any. Otherwise,
/// returns null.
const ControlFlowContext *getControlFlowContext(const FunctionDecl *F);
const AdornedCFG *getAdornedCFG(const FunctionDecl *F);

const Options &getOptions() { return Opts; }

Expand Down Expand Up @@ -296,7 +296,7 @@ class DataflowAnalysisContext {
llvm::DenseMap<Atom, const Formula *> FlowConditionConstraints;
const Formula *Invariant = nullptr;

llvm::DenseMap<const FunctionDecl *, ControlFlowContext> FunctionContexts;
llvm::DenseMap<const FunctionDecl *, AdornedCFG> FunctionContexts;

// Fields modeled by environments covered by this context.
FieldSet ModeledFields;
Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/Analysis/FlowSensitive/Logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

namespace clang::dataflow {
// Forward declarations so we can use Logger anywhere in the framework.
class ControlFlowContext;
class AdornedCFG;
class TypeErasedDataflowAnalysis;
struct TypeErasedDataflowAnalysisState;

Expand All @@ -40,8 +40,8 @@ class Logger {

/// Called by the framework as we start analyzing a new function or statement.
/// Forms a pair with endAnalysis().
virtual void beginAnalysis(const ControlFlowContext &,
TypeErasedDataflowAnalysis &) {}
virtual void beginAnalysis(const AdornedCFG &, TypeErasedDataflowAnalysis &) {
}
virtual void endAnalysis() {}

// At any time during the analysis, we're computing the state for some target
Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/Analysis/FlowSensitive/Transfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,20 @@ class StmtToEnvMap {
// `CurState` is the pending state currently associated with this block. These
// are supplied separately as the pending state for the current block may not
// yet be represented in `BlockToState`.
StmtToEnvMap(const ControlFlowContext &CFCtx,
StmtToEnvMap(const AdornedCFG &ACFG,
llvm::ArrayRef<std::optional<TypeErasedDataflowAnalysisState>>
BlockToState,
unsigned CurBlockID,
const TypeErasedDataflowAnalysisState &CurState)
: CFCtx(CFCtx), BlockToState(BlockToState), CurBlockID(CurBlockID),
: ACFG(ACFG), BlockToState(BlockToState), CurBlockID(CurBlockID),
CurState(CurState) {}

/// Returns the environment of the basic block that contains `S`.
/// The result is guaranteed never to be null.
const Environment *getEnvironment(const Stmt &S) const;

private:
const ControlFlowContext &CFCtx;
const AdornedCFG &ACFG;
llvm::ArrayRef<std::optional<TypeErasedDataflowAnalysisState>> BlockToState;
unsigned CurBlockID;
const TypeErasedDataflowAnalysisState &CurState;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Stmt.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
#include "clang/Analysis/FlowSensitive/AdornedCFG.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
Expand Down Expand Up @@ -146,7 +146,7 @@ struct TypeErasedDataflowAnalysisState {
/// from converging.
llvm::Expected<std::vector<std::optional<TypeErasedDataflowAnalysisState>>>
runTypeErasedDataflowAnalysis(
const ControlFlowContext &CFCtx, TypeErasedDataflowAnalysis &Analysis,
const AdornedCFG &ACFG, TypeErasedDataflowAnalysis &Analysis,
const Environment &InitEnv,
std::function<void(const CFGElement &,
const TypeErasedDataflowAnalysisState &)>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
//===- ControlFlowContext.cpp ---------------------------------------------===//
//===- AdornedCFG.cpp ---------------------------------------------===//
//
// 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 a ControlFlowContext class that is used by dataflow
// analyses that run over Control-Flow Graphs (CFGs).
// This file defines an `AdornedCFG` class that is used by dataflow analyses
// that run over Control-Flow Graphs (CFGs).
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
#include "clang/Analysis/FlowSensitive/AdornedCFG.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Stmt.h"
Expand Down Expand Up @@ -126,8 +126,7 @@ buildContainsExprConsumedInDifferentBlock(
return Result;
}

llvm::Expected<ControlFlowContext>
ControlFlowContext::build(const FunctionDecl &Func) {
llvm::Expected<AdornedCFG> AdornedCFG::build(const FunctionDecl &Func) {
if (!Func.doesThisDeclarationHaveABody())
return llvm::createStringError(
std::make_error_code(std::errc::invalid_argument),
Expand All @@ -136,8 +135,8 @@ ControlFlowContext::build(const FunctionDecl &Func) {
return build(Func, *Func.getBody(), Func.getASTContext());
}

llvm::Expected<ControlFlowContext>
ControlFlowContext::build(const Decl &D, Stmt &S, ASTContext &C) {
llvm::Expected<AdornedCFG> AdornedCFG::build(const Decl &D, Stmt &S,
ASTContext &C) {
if (D.isTemplated())
return llvm::createStringError(
std::make_error_code(std::errc::invalid_argument),
Expand Down Expand Up @@ -175,9 +174,9 @@ ControlFlowContext::build(const Decl &D, Stmt &S, ASTContext &C) {
llvm::DenseSet<const CFGBlock *> ContainsExprConsumedInDifferentBlock =
buildContainsExprConsumedInDifferentBlock(*Cfg, StmtToBlock);

return ControlFlowContext(D, std::move(Cfg), std::move(StmtToBlock),
std::move(BlockReachable),
std::move(ContainsExprConsumedInDifferentBlock));
return AdornedCFG(D, std::move(Cfg), std::move(StmtToBlock),
std::move(BlockReachable),
std::move(ContainsExprConsumedInDifferentBlock));
}

} // namespace dataflow
Expand Down
Loading