Skip to content

Commit

Permalink
[clang][dataflow] Add a ControlFlowContext::build() overload taking…
Browse files Browse the repository at this point in the history
… a `FunctionDecl`.

This is the most common use case, so it makes sense to have a specific overload for it.

Reviewed By: xazax.hun

Differential Revision: https://reviews.llvm.org/D151183
  • Loading branch information
martinboehme committed May 25, 2023
1 parent ca7167d commit 246626a
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 6 deletions.
Expand Up @@ -31,6 +31,11 @@ namespace dataflow {
/// analysis.
class ControlFlowContext {
public:
/// Builds a ControlFlowContext from a `FunctionDecl`.
/// `Func.hasBody()` must be true, and `Func.isTemplated()` must be false.
static llvm::Expected<ControlFlowContext> build(const FunctionDecl &Func,
ASTContext &C);

/// 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,
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
Expand Up @@ -67,6 +67,16 @@ static llvm::BitVector findReachableBlocks(const CFG &Cfg) {
return BlockReachable;
}

llvm::Expected<ControlFlowContext>
ControlFlowContext::build(const FunctionDecl &Func, ASTContext &C) {
if (!Func.hasBody())
return llvm::createStringError(
std::make_error_code(std::errc::invalid_argument),
"Cannot analyze function without a body");

return build(Func, *Func.getBody(), C);
}

llvm::Expected<ControlFlowContext>
ControlFlowContext::build(const Decl &D, Stmt &S, ASTContext &C) {
if (D.isTemplated())
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
Expand Up @@ -210,8 +210,8 @@ DataflowAnalysisContext::getControlFlowContext(const FunctionDecl *F) {
if (It != FunctionContexts.end())
return &It->second;

if (Stmt *Body = F->getBody()) {
auto CFCtx = ControlFlowContext::build(*F, *Body, F->getASTContext());
if (F->hasBody()) {
auto CFCtx = ControlFlowContext::build(*F, F->getASTContext());
// FIXME: Handle errors.
assert(CFCtx);
auto Result = FunctionContexts.insert({F, std::move(*CFCtx)});
Expand Down
3 changes: 1 addition & 2 deletions clang/unittests/Analysis/FlowSensitive/TestingSupport.h
Expand Up @@ -241,8 +241,7 @@ checkDataflow(AnalysisInputs<AnalysisT> AI,
llvm::errc::invalid_argument, "Could not find the target function.");

// Build the control flow graph for the target function.
auto MaybeCFCtx =
ControlFlowContext::build(*Target, *Target->getBody(), Context);
auto MaybeCFCtx = ControlFlowContext::build(*Target, Context);
if (!MaybeCFCtx) return MaybeCFCtx.takeError();
auto &CFCtx = *MaybeCFCtx;

Expand Down
Expand Up @@ -67,8 +67,8 @@ runAnalysis(llvm::StringRef Code, AnalysisT (*MakeAnalysis)(ASTContext &)) {
Stmt *Body = Func->getBody();
assert(Body != nullptr);

auto CFCtx = llvm::cantFail(
ControlFlowContext::build(*Func, *Body, AST->getASTContext()));
auto CFCtx =
llvm::cantFail(ControlFlowContext::build(*Func, AST->getASTContext()));

AnalysisT Analysis = MakeAnalysis(AST->getASTContext());
DataflowAnalysisContext DACtx(std::make_unique<WatchedLiteralsSolver>());
Expand Down

0 comments on commit 246626a

Please sign in to comment.