clang 17.0.0git
ControlFlowContext.cpp
Go to the documentation of this file.
1//===- ControlFlowContext.cpp ---------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines a ControlFlowContext class that is used by dataflow
10// analyses that run over Control-Flow Graphs (CFGs).
11//
12//===----------------------------------------------------------------------===//
13
16#include "clang/AST/Decl.h"
17#include "clang/AST/Stmt.h"
18#include "clang/Analysis/CFG.h"
19#include "llvm/ADT/BitVector.h"
20#include "llvm/ADT/DenseMap.h"
21#include "llvm/Support/Error.h"
22#include <utility>
23
24namespace clang {
25namespace dataflow {
26
27/// Returns a map from statements to basic blocks that contain them.
28static llvm::DenseMap<const Stmt *, const CFGBlock *>
30 llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock;
31 for (const CFGBlock *Block : Cfg) {
32 if (Block == nullptr)
33 continue;
34
35 for (const CFGElement &Element : *Block) {
36 auto Stmt = Element.getAs<CFGStmt>();
37 if (!Stmt)
38 continue;
39
40 StmtToBlock[Stmt->getStmt()] = Block;
41 }
42 if (const Stmt *TerminatorStmt = Block->getTerminatorStmt())
43 StmtToBlock[TerminatorStmt] = Block;
44 }
45 return StmtToBlock;
46}
47
48static llvm::BitVector findReachableBlocks(const CFG &Cfg) {
49 llvm::BitVector BlockReachable(Cfg.getNumBlockIDs(), false);
50
52 BlocksToVisit.push_back(&Cfg.getEntry());
53 while (!BlocksToVisit.empty()) {
54 const CFGBlock *Block = BlocksToVisit.back();
55 BlocksToVisit.pop_back();
56
57 if (BlockReachable[Block->getBlockID()])
58 continue;
59
60 BlockReachable[Block->getBlockID()] = true;
61
62 for (const CFGBlock *Succ : Block->succs())
63 if (Succ)
64 BlocksToVisit.push_back(Succ);
65 }
66
67 return BlockReachable;
68}
69
72 if (!Func.hasBody())
73 return llvm::createStringError(
74 std::make_error_code(std::errc::invalid_argument),
75 "Cannot analyze function without a body");
76
77 return build(Func, *Func.getBody(), Func.getASTContext());
78}
79
82 if (D.isTemplated())
83 return llvm::createStringError(
84 std::make_error_code(std::errc::invalid_argument),
85 "Cannot analyze templated declarations");
86
87 CFG::BuildOptions Options;
88 Options.PruneTriviallyFalseEdges = true;
89 Options.AddImplicitDtors = true;
90 Options.AddTemporaryDtors = true;
91 Options.AddInitializers = true;
92 Options.AddCXXDefaultInitExprInCtors = true;
93
94 // Ensure that all sub-expressions in basic blocks are evaluated.
95 Options.setAllAlwaysAdd();
96
97 auto Cfg = CFG::buildCFG(&D, &S, &C, Options);
98 if (Cfg == nullptr)
99 return llvm::createStringError(
100 std::make_error_code(std::errc::invalid_argument),
101 "CFG::buildCFG failed");
102
103 llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock =
105
106 llvm::BitVector BlockReachable = findReachableBlocks(*Cfg);
107
108 return ControlFlowContext(&D, std::move(Cfg), std::move(StmtToBlock),
109 std::move(BlockReachable));
110}
111
114 if (D == nullptr)
115 return llvm::createStringError(
116 std::make_error_code(std::errc::invalid_argument),
117 "Declaration must not be null");
118
119 return build(*D, S, C);
120}
121
122} // namespace dataflow
123} // namespace clang
Defines the clang::ASTContext interface.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:182
Represents a single basic block in a source-level CFG.
Definition: CFG.h:576
Represents a top-level expression in a basic block.
Definition: CFG.h:54
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Definition: CFG.h:1225
static std::unique_ptr< CFG > buildCFG(const Decl *D, Stmt *AST, ASTContext *C, const BuildOptions &BO)
Builds a CFG from an AST.
Definition: CFG.cpp:5228
CFGBlock & getEntry()
Definition: CFG.h:1331
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
Definition: CFG.h:1411
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:83
ASTContext & getASTContext() const LLVM_READONLY
Definition: DeclBase.cpp:429
bool isTemplated() const
Determine whether this declaration is a templated entity (whether it is.
Definition: DeclBase.cpp:263
Represents a function declaration or definition.
Definition: Decl.h:1917
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition: Decl.cpp:3138
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition: Decl.cpp:3058
Stmt - This represents one statement.
Definition: Stmt.h:72
Holds CFG and other derived context that is needed to perform dataflow analysis.
static llvm::Expected< ControlFlowContext > build(const FunctionDecl &Func)
Builds a ControlFlowContext from a FunctionDecl.
static llvm::DenseMap< const Stmt *, const CFGBlock * > buildStmtToBasicBlockMap(const CFG &Cfg)
Returns a map from statements to basic blocks that contain them.
static llvm::BitVector findReachableBlocks(const CFG &Cfg)
@ C
Languages that the frontend can parse and compile.