1//===-- AdornedCFG.h ------------------------------------*- C++ -*-===//
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 an AdornedCFG class that is used by dataflow analyses that
10// run over Control-Flow Graphs (CFGs).
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ADORNEDCFG_H
15#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ADORNEDCFG_H
16
17#include "clang/AST/ASTContext.h"
18#include "clang/AST/Decl.h"
19#include "clang/AST/Stmt.h"
20#include "clang/Analysis/CFG.h"
21#include "llvm/ADT/BitVector.h"
22#include "llvm/ADT/DenseMap.h"
23#include "llvm/Support/Error.h"
24#include <memory>
25#include <utility>
26
27namespace clang {
28namespace dataflow {
29
30/// Holds CFG with additional information derived from it that is needed to
31/// perform dataflow analysis.
32class AdornedCFG {
33public:
34 /// Builds an `AdornedCFG` from a `FunctionDecl`.
35 /// `Func.doesThisDeclarationHaveABody()` must be true, and
36 /// `Func.isTemplated()` must be false.
37 static llvm::Expected<AdornedCFG> build(const FunctionDecl &Func);
38
39 /// Builds an `AdornedCFG` from an AST node. `D` is the function in which
40 /// `S` resides. `D.isTemplated()` must be false.
41 static llvm::Expected<AdornedCFG> build(const Decl &D, Stmt &S,
42 ASTContext &C);
43
44 /// Returns the `Decl` containing the statement used to construct the CFG, if
45 /// available.
46 const Decl &getDecl() const { return ContainingDecl; }
47
48 /// Returns the CFG that is stored in this context.
49 const CFG &getCFG() const { return *Cfg; }
50
51 /// Returns a mapping from statements to basic blocks that contain them.
52 const llvm::DenseMap<const Stmt *, const CFGBlock *> &getStmtToBlock() const {
53 return StmtToBlock;
54 }
55
56 /// Returns whether `B` is reachable from the entry block.
57 bool isBlockReachable(const CFGBlock &B) const {
58 return BlockReachable[B.getBlockID()];
59 }
60
61 /// Returns whether `B` contains an expression that is consumed in a
62 /// different block than `B` (i.e. the parent of the expression is in a
63 /// different block).
64 /// This happens if there is control flow within a full-expression (triggered
65 /// by `&&`, `||`, or the conditional operator). Note that the operands of
66 /// these operators are not the only expressions that can be consumed in a
67 /// different block. For example, in the function call
68 /// `f(&i, cond() ? 1 : 0)`, `&i` is in a different block than the `CallExpr`.
69 bool containsExprConsumedInDifferentBlock(const CFGBlock &B) const {
70 return ContainsExprConsumedInDifferentBlock.contains(V: &B);
71 }
72
73private:
74 AdornedCFG(
75 const Decl &D, std::unique_ptr<CFG> Cfg,
76 llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock,
77 llvm::BitVector BlockReachable,
78 llvm::DenseSet<const CFGBlock *> ContainsExprConsumedInDifferentBlock)
79 : ContainingDecl(D), Cfg(std::move(Cfg)),
80 StmtToBlock(std::move(StmtToBlock)),
81 BlockReachable(std::move(BlockReachable)),
82 ContainsExprConsumedInDifferentBlock(
83 std::move(ContainsExprConsumedInDifferentBlock)) {}
84
85 /// The `Decl` containing the statement used to construct the CFG.
86 const Decl &ContainingDecl;
87 std::unique_ptr<CFG> Cfg;
88 llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock;
89 llvm::BitVector BlockReachable;
90 llvm::DenseSet<const CFGBlock *> ContainsExprConsumedInDifferentBlock;
91};
92
93} // namespace dataflow
94} // namespace clang
95
96#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ADORNEDCFG_H
97

source code of clang/include/clang/Analysis/FlowSensitive/AdornedCFG.h