Coverage Report

Created: 2022-05-17 06:19

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
Line
Count
Source (jump to first uncovered line)
1
//===- DataflowAnalysis.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 base types and functions for building dataflow analyses
10
//  that run over Control-Flow Graphs (CFGs).
11
//
12
//===----------------------------------------------------------------------===//
13
14
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWANALYSIS_H
15
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWANALYSIS_H
16
17
#include <iterator>
18
#include <utility>
19
#include <vector>
20
21
#include "clang/AST/ASTContext.h"
22
#include "clang/AST/Stmt.h"
23
#include "clang/Analysis/CFG.h"
24
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
25
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
26
#include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
27
#include "llvm/ADT/Any.h"
28
#include "llvm/ADT/Optional.h"
29
#include "llvm/ADT/STLExtras.h"
30
#include "llvm/Support/Error.h"
31
32
namespace clang {
33
namespace dataflow {
34
35
/// Base class template for dataflow analyses built on a single lattice type.
36
///
37
/// Requirements:
38
///
39
///  `Derived` must be derived from a specialization of this class template and
40
///  must provide the following public members:
41
///   * `LatticeT initialElement()` - returns a lattice element that models the
42
///     initial state of a basic block;
43
///   * `void transfer(const Stmt *, LatticeT &, Environment &)` - applies the
44
///     analysis transfer function for a given statement and lattice element.
45
///
46
///  `Derived` can optionally override the following members:
47
///   * `bool merge(QualType, const Value &, const Value &, Value &,
48
///     Environment &)` -  joins distinct values. This could be a strict
49
///     lattice join or a more general widening operation.
50
///
51
///  `LatticeT` is a bounded join-semilattice that is used by `Derived` and must
52
///  provide the following public members:
53
///   * `LatticeJoinEffect join(const LatticeT &)` - joins the object and the
54
///     argument by computing their least upper bound, modifies the object if
55
///     necessary, and returns an effect indicating whether any changes were
56
///     made to it;
57
///   * `bool operator==(const LatticeT &) const` - returns true if and only if
58
///     the object is equal to the argument.
59
template <typename Derived, typename LatticeT>
60
class DataflowAnalysis : public TypeErasedDataflowAnalysis {
61
public:
62
  /// Bounded join-semilattice that is used in the analysis.
63
  using Lattice = LatticeT;
64
65
165
  explicit DataflowAnalysis(ASTContext &Context) : Context(Context) {}
66
  explicit DataflowAnalysis(ASTContext &Context, bool ApplyBuiltinTransfer)
67
      : TypeErasedDataflowAnalysis(ApplyBuiltinTransfer), Context(Context) {}
68
69
3.66k
  ASTContext &getASTContext() final { return Context; }
70
71
330
  TypeErasedLattice typeErasedInitialElement() final {
72
330
    return {static_cast<Derived *>(this)->initialElement()};
73
330
  }
74
75
  LatticeJoinEffect joinTypeErased(TypeErasedLattice &E1,
76
54
                                   const TypeErasedLattice &E2) final {
77
54
    Lattice &L1 = llvm::any_cast<Lattice &>(E1.Value);
78
54
    const Lattice &L2 = llvm::any_cast<const Lattice &>(E2.Value);
79
54
    return L1.join(L2);
80
54
  }
81
82
  bool isEqualTypeErased(const TypeErasedLattice &E1,
83
0
                         const TypeErasedLattice &E2) final {
84
0
    const Lattice &L1 = llvm::any_cast<const Lattice &>(E1.Value);
85
0
    const Lattice &L2 = llvm::any_cast<const Lattice &>(E2.Value);
86
0
    return L1 == L2;
87
0
  }
88
89
  void transferTypeErased(const Stmt *Stmt, TypeErasedLattice &E,
90
3.66k
                          Environment &Env) final {
91
3.66k
    Lattice &L = llvm::any_cast<Lattice &>(E.Value);
92
3.66k
    static_cast<Derived *>(this)->transfer(Stmt, L, Env);
93
3.66k
  }
94
95
private:
96
  ASTContext &Context;
97
};
98
99
// Model of the program at a given program point.
100
template <typename LatticeT> struct DataflowAnalysisState {
101
  // Model of a program property.
102
  LatticeT Lattice;
103
104
  // Model of the state of the program (store and heap).
105
  Environment Env;
106
};
107
108
/// Performs dataflow analysis and returns a mapping from basic block IDs to
109
/// dataflow analysis states that model the respective basic blocks. The
110
/// returned vector, if any, will have the same size as the number of CFG
111
/// blocks, with indices corresponding to basic block IDs. Returns an error if
112
/// the dataflow analysis cannot be performed successfully.
113
template <typename AnalysisT>
114
llvm::Expected<std::vector<
115
    llvm::Optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>>
116
runDataflowAnalysis(const ControlFlowContext &CFCtx, AnalysisT &Analysis,
117
                    const Environment &InitEnv) {
118
  auto TypeErasedBlockStates =
119
      runTypeErasedDataflowAnalysis(CFCtx, Analysis, InitEnv);
120
  if (!TypeErasedBlockStates)
121
    return TypeErasedBlockStates.takeError();
122
123
  std::vector<
124
      llvm::Optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>
125
      BlockStates;
126
  BlockStates.reserve(TypeErasedBlockStates->size());
127
128
  llvm::transform(std::move(*TypeErasedBlockStates),
129
                  std::back_inserter(BlockStates), [](auto &OptState) {
130
                    return std::move(OptState).map([](auto &&State) {
131
                      return DataflowAnalysisState<typename AnalysisT::Lattice>{
132
                          llvm::any_cast<typename AnalysisT::Lattice>(
133
                              std::move(State.Lattice.Value)),
134
                          std::move(State.Env)};
135
                    });
136
                  });
137
  return BlockStates;
138
}
139
140
/// Abstract base class for dataflow "models": reusable analysis components that
141
/// model a particular aspect of program semantics in the `Environment`. For
142
/// example, a model may capture a type and its related functions.
143
class DataflowModel : public Environment::ValueModel {
144
public:
145
  /// Return value indicates whether the model processed the `Stmt`.
146
  virtual bool transfer(const Stmt *Stmt, Environment &Env) = 0;
147
};
148
149
} // namespace dataflow
150
} // namespace clang
151
152
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWANALYSIS_H