Coverage Report

Created: 2023-05-31 04:38

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/Analysis/FlowSensitive/Arena.h
Line
Count
Source
1
//===-- Arena.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
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE__ARENA_H
9
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE__ARENA_H
10
11
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
12
#include "clang/Analysis/FlowSensitive/Value.h"
13
#include <vector>
14
15
namespace clang::dataflow {
16
17
/// The Arena owns the objects that model data within an analysis.
18
/// For example, `Value` and `StorageLocation`.
19
class Arena {
20
public:
21
  Arena()
22
      : TrueVal(create<AtomicBoolValue>()),
23
590
        FalseVal(create<AtomicBoolValue>()) {}
24
  Arena(const Arena &) = delete;
25
  Arena &operator=(const Arena &) = delete;
26
27
  /// Creates a `T` (some subclass of `StorageLocation`), forwarding `args` to
28
  /// the constructor, and returns a reference to it.
29
  ///
30
  /// The `DataflowAnalysisContext` takes ownership of the created object. The
31
  /// object will be destroyed when the `DataflowAnalysisContext` is destroyed.
32
  template <typename T, typename... Args>
33
  std::enable_if_t<std::is_base_of<StorageLocation, T>::value, T &>
34
5.94k
  create(Args &&...args) {
35
    // Note: If allocation of individual `StorageLocation`s turns out to be
36
    // costly, consider creating specializations of `create<T>` for commonly
37
    // used `StorageLocation` subclasses and make them use a `BumpPtrAllocator`.
38
5.94k
    return *cast<T>(
39
5.94k
        Locs.emplace_back(std::make_unique<T>(std::forward<Args>(args)...))
40
5.94k
            .get());
41
5.94k
  }
std::__1::enable_if<std::is_base_of<clang::dataflow::StorageLocation, clang::dataflow::AggregateStorageLocation>::value, clang::dataflow::AggregateStorageLocation&>::type clang::dataflow::Arena::create<clang::dataflow::AggregateStorageLocation, clang::QualType&, llvm::DenseMap<clang::ValueDecl const*, clang::dataflow::StorageLocation*, llvm::DenseMapInfo<clang::ValueDecl const*, void>, llvm::detail::DenseMapPair<clang::ValueDecl const*, clang::dataflow::StorageLocation*> > >(clang::QualType&, llvm::DenseMap<clang::ValueDecl const*, clang::dataflow::StorageLocation*, llvm::DenseMapInfo<clang::ValueDecl const*, void>, llvm::detail::DenseMapPair<clang::ValueDecl const*, clang::dataflow::StorageLocation*> >&&)
Line
Count
Source
34
2.19k
  create(Args &&...args) {
35
    // Note: If allocation of individual `StorageLocation`s turns out to be
36
    // costly, consider creating specializations of `create<T>` for commonly
37
    // used `StorageLocation` subclasses and make them use a `BumpPtrAllocator`.
38
2.19k
    return *cast<T>(
39
2.19k
        Locs.emplace_back(std::make_unique<T>(std::forward<Args>(args)...))
40
2.19k
            .get());
41
2.19k
  }
std::__1::enable_if<std::is_base_of<clang::dataflow::StorageLocation, clang::dataflow::ScalarStorageLocation>::value, clang::dataflow::ScalarStorageLocation&>::type clang::dataflow::Arena::create<clang::dataflow::ScalarStorageLocation, clang::QualType&>(clang::QualType&)
Line
Count
Source
34
3.75k
  create(Args &&...args) {
35
    // Note: If allocation of individual `StorageLocation`s turns out to be
36
    // costly, consider creating specializations of `create<T>` for commonly
37
    // used `StorageLocation` subclasses and make them use a `BumpPtrAllocator`.
38
3.75k
    return *cast<T>(
39
3.75k
        Locs.emplace_back(std::make_unique<T>(std::forward<Args>(args)...))
40
3.75k
            .get());
41
3.75k
  }
42
43
  /// Creates a `T` (some subclass of `Value`), forwarding `args` to the
44
  /// constructor, and returns a reference to it.
45
  ///
46
  /// The `DataflowAnalysisContext` takes ownership of the created object. The
47
  /// object will be destroyed when the `DataflowAnalysisContext` is destroyed.
48
  template <typename T, typename... Args>
49
  std::enable_if_t<std::is_base_of<Value, T>::value, T &>
50
31.4k
  create(Args &&...args) {
51
    // Note: If allocation of individual `Value`s turns out to be costly,
52
    // consider creating specializations of `create<T>` for commonly used
53
    // `Value` subclasses and make them use a `BumpPtrAllocator`.
54
31.4k
    return *cast<T>(
55
31.4k
        Vals.emplace_back(std::make_unique<T>(std::forward<Args>(args)...))
56
31.4k
            .get());
57
31.4k
  }
std::__1::enable_if<std::is_base_of<clang::dataflow::Value, clang::dataflow::ConjunctionValue>::value, clang::dataflow::ConjunctionValue&>::type clang::dataflow::Arena::create<clang::dataflow::ConjunctionValue, clang::dataflow::BoolValue&, clang::dataflow::BoolValue&>(clang::dataflow::BoolValue&, clang::dataflow::BoolValue&)
Line
Count
Source
50
1.83k
  create(Args &&...args) {
51
    // Note: If allocation of individual `Value`s turns out to be costly,
52
    // consider creating specializations of `create<T>` for commonly used
53
    // `Value` subclasses and make them use a `BumpPtrAllocator`.
54
1.83k
    return *cast<T>(
55
1.83k
        Vals.emplace_back(std::make_unique<T>(std::forward<Args>(args)...))
56
1.83k
            .get());
57
1.83k
  }
std::__1::enable_if<std::is_base_of<clang::dataflow::Value, clang::dataflow::DisjunctionValue>::value, clang::dataflow::DisjunctionValue&>::type clang::dataflow::Arena::create<clang::dataflow::DisjunctionValue, clang::dataflow::BoolValue&, clang::dataflow::BoolValue&>(clang::dataflow::BoolValue&, clang::dataflow::BoolValue&)
Line
Count
Source
50
1.12k
  create(Args &&...args) {
51
    // Note: If allocation of individual `Value`s turns out to be costly,
52
    // consider creating specializations of `create<T>` for commonly used
53
    // `Value` subclasses and make them use a `BumpPtrAllocator`.
54
1.12k
    return *cast<T>(
55
1.12k
        Vals.emplace_back(std::make_unique<T>(std::forward<Args>(args)...))
56
1.12k
            .get());
57
1.12k
  }
std::__1::enable_if<std::is_base_of<clang::dataflow::Value, clang::dataflow::NegationValue>::value, clang::dataflow::NegationValue&>::type clang::dataflow::Arena::create<clang::dataflow::NegationValue, clang::dataflow::BoolValue&>(clang::dataflow::BoolValue&)
Line
Count
Source
50
1.72k
  create(Args &&...args) {
51
    // Note: If allocation of individual `Value`s turns out to be costly,
52
    // consider creating specializations of `create<T>` for commonly used
53
    // `Value` subclasses and make them use a `BumpPtrAllocator`.
54
1.72k
    return *cast<T>(
55
1.72k
        Vals.emplace_back(std::make_unique<T>(std::forward<Args>(args)...))
56
1.72k
            .get());
57
1.72k
  }
std::__1::enable_if<std::is_base_of<clang::dataflow::Value, clang::dataflow::ImplicationValue>::value, clang::dataflow::ImplicationValue&>::type clang::dataflow::Arena::create<clang::dataflow::ImplicationValue, clang::dataflow::BoolValue&, clang::dataflow::BoolValue&>(clang::dataflow::BoolValue&, clang::dataflow::BoolValue&)
Line
Count
Source
50
364
  create(Args &&...args) {
51
    // Note: If allocation of individual `Value`s turns out to be costly,
52
    // consider creating specializations of `create<T>` for commonly used
53
    // `Value` subclasses and make them use a `BumpPtrAllocator`.
54
364
    return *cast<T>(
55
364
        Vals.emplace_back(std::make_unique<T>(std::forward<Args>(args)...))
56
364
            .get());
57
364
  }
std::__1::enable_if<std::is_base_of<clang::dataflow::Value, clang::dataflow::BiconditionalValue>::value, clang::dataflow::BiconditionalValue&>::type clang::dataflow::Arena::create<clang::dataflow::BiconditionalValue, clang::dataflow::BoolValue&, clang::dataflow::BoolValue&>(clang::dataflow::BoolValue&, clang::dataflow::BoolValue&)
Line
Count
Source
50
3.77k
  create(Args &&...args) {
51
    // Note: If allocation of individual `Value`s turns out to be costly,
52
    // consider creating specializations of `create<T>` for commonly used
53
    // `Value` subclasses and make them use a `BumpPtrAllocator`.
54
3.77k
    return *cast<T>(
55
3.77k
        Vals.emplace_back(std::make_unique<T>(std::forward<Args>(args)...))
56
3.77k
            .get());
57
3.77k
  }
std::__1::enable_if<std::is_base_of<clang::dataflow::Value, clang::dataflow::AtomicBoolValue>::value, clang::dataflow::AtomicBoolValue&>::type clang::dataflow::Arena::create<clang::dataflow::AtomicBoolValue>()
Line
Count
Source
50
16.1k
  create(Args &&...args) {
51
    // Note: If allocation of individual `Value`s turns out to be costly,
52
    // consider creating specializations of `create<T>` for commonly used
53
    // `Value` subclasses and make them use a `BumpPtrAllocator`.
54
16.1k
    return *cast<T>(
55
16.1k
        Vals.emplace_back(std::make_unique<T>(std::forward<Args>(args)...))
56
16.1k
            .get());
57
16.1k
  }
std::__1::enable_if<std::is_base_of<clang::dataflow::Value, clang::dataflow::PointerValue>::value, clang::dataflow::PointerValue&>::type clang::dataflow::Arena::create<clang::dataflow::PointerValue, clang::dataflow::StorageLocation&>(clang::dataflow::StorageLocation&)
Line
Count
Source
50
1.35k
  create(Args &&...args) {
51
    // Note: If allocation of individual `Value`s turns out to be costly,
52
    // consider creating specializations of `create<T>` for commonly used
53
    // `Value` subclasses and make them use a `BumpPtrAllocator`.
54
1.35k
    return *cast<T>(
55
1.35k
        Vals.emplace_back(std::make_unique<T>(std::forward<Args>(args)...))
56
1.35k
            .get());
57
1.35k
  }
std::__1::enable_if<std::is_base_of<clang::dataflow::Value, clang::dataflow::TopBoolValue>::value, clang::dataflow::TopBoolValue&>::type clang::dataflow::Arena::create<clang::dataflow::TopBoolValue>()
Line
Count
Source
50
46
  create(Args &&...args) {
51
    // Note: If allocation of individual `Value`s turns out to be costly,
52
    // consider creating specializations of `create<T>` for commonly used
53
    // `Value` subclasses and make them use a `BumpPtrAllocator`.
54
46
    return *cast<T>(
55
46
        Vals.emplace_back(std::make_unique<T>(std::forward<Args>(args)...))
56
46
            .get());
57
46
  }
std::__1::enable_if<std::is_base_of<clang::dataflow::Value, clang::dataflow::IntegerValue>::value, clang::dataflow::IntegerValue&>::type clang::dataflow::Arena::create<clang::dataflow::IntegerValue>()
Line
Count
Source
50
1.23k
  create(Args &&...args) {
51
    // Note: If allocation of individual `Value`s turns out to be costly,
52
    // consider creating specializations of `create<T>` for commonly used
53
    // `Value` subclasses and make them use a `BumpPtrAllocator`.
54
1.23k
    return *cast<T>(
55
1.23k
        Vals.emplace_back(std::make_unique<T>(std::forward<Args>(args)...))
56
1.23k
            .get());
57
1.23k
  }
std::__1::enable_if<std::is_base_of<clang::dataflow::Value, clang::dataflow::ReferenceValue>::value, clang::dataflow::ReferenceValue&>::type clang::dataflow::Arena::create<clang::dataflow::ReferenceValue, clang::dataflow::StorageLocation&>(clang::dataflow::StorageLocation&)
Line
Count
Source
50
1.07k
  create(Args &&...args) {
51
    // Note: If allocation of individual `Value`s turns out to be costly,
52
    // consider creating specializations of `create<T>` for commonly used
53
    // `Value` subclasses and make them use a `BumpPtrAllocator`.
54
1.07k
    return *cast<T>(
55
1.07k
        Vals.emplace_back(std::make_unique<T>(std::forward<Args>(args)...))
56
1.07k
            .get());
57
1.07k
  }
std::__1::enable_if<std::is_base_of<clang::dataflow::Value, clang::dataflow::StructValue>::value, clang::dataflow::StructValue&>::type clang::dataflow::Arena::create<clang::dataflow::StructValue, llvm::DenseMap<clang::ValueDecl const*, clang::dataflow::Value*, llvm::DenseMapInfo<clang::ValueDecl const*, void>, llvm::detail::DenseMapPair<clang::ValueDecl const*, clang::dataflow::Value*> > >(llvm::DenseMap<clang::ValueDecl const*, clang::dataflow::Value*, llvm::DenseMapInfo<clang::ValueDecl const*, void>, llvm::detail::DenseMapPair<clang::ValueDecl const*, clang::dataflow::Value*> >&&)
Line
Count
Source
50
1.67k
  create(Args &&...args) {
51
    // Note: If allocation of individual `Value`s turns out to be costly,
52
    // consider creating specializations of `create<T>` for commonly used
53
    // `Value` subclasses and make them use a `BumpPtrAllocator`.
54
1.67k
    return *cast<T>(
55
1.67k
        Vals.emplace_back(std::make_unique<T>(std::forward<Args>(args)...))
56
1.67k
            .get());
57
1.67k
  }
std::__1::enable_if<std::is_base_of<clang::dataflow::Value, clang::dataflow::StructValue>::value, clang::dataflow::StructValue&>::type clang::dataflow::Arena::create<clang::dataflow::StructValue>()
Line
Count
Source
50
1.05k
  create(Args &&...args) {
51
    // Note: If allocation of individual `Value`s turns out to be costly,
52
    // consider creating specializations of `create<T>` for commonly used
53
    // `Value` subclasses and make them use a `BumpPtrAllocator`.
54
1.05k
    return *cast<T>(
55
1.05k
        Vals.emplace_back(std::make_unique<T>(std::forward<Args>(args)...))
56
1.05k
            .get());
57
1.05k
  }
58
59
  /// Returns a boolean value that represents the conjunction of `LHS` and
60
  /// `RHS`. Subsequent calls with the same arguments, regardless of their
61
  /// order, will return the same result. If the given boolean values represent
62
  /// the same value, the result will be the value itself.
63
  BoolValue &makeAnd(BoolValue &LHS, BoolValue &RHS);
64
65
  /// Returns a boolean value that represents the disjunction of `LHS` and
66
  /// `RHS`. Subsequent calls with the same arguments, regardless of their
67
  /// order, will return the same result. If the given boolean values represent
68
  /// the same value, the result will be the value itself.
69
  BoolValue &makeOr(BoolValue &LHS, BoolValue &RHS);
70
71
  /// Returns a boolean value that represents the negation of `Val`. Subsequent
72
  /// calls with the same argument will return the same result.
73
  BoolValue &makeNot(BoolValue &Val);
74
75
  /// Returns a boolean value that represents `LHS => RHS`. Subsequent calls
76
  /// with the same arguments, will return the same result. If the given boolean
77
  /// values represent the same value, the result will be a value that
78
  /// represents the true boolean literal.
79
  BoolValue &makeImplies(BoolValue &LHS, BoolValue &RHS);
80
81
  /// Returns a boolean value that represents `LHS <=> RHS`. Subsequent calls
82
  /// with the same arguments, regardless of their order, will return the same
83
  /// result. If the given boolean values represent the same value, the result
84
  /// will be a value that represents the true boolean literal.
85
  BoolValue &makeEquals(BoolValue &LHS, BoolValue &RHS);
86
87
  /// Returns a symbolic boolean value that models a boolean literal equal to
88
  /// `Value`. These literals are the same every time.
89
4.12k
  AtomicBoolValue &makeLiteral(bool Value) const {
90
4.12k
    return Value ? 
TrueVal2.04k
:
FalseVal2.08k
;
91
4.12k
  }
92
93
  /// Creates a fresh flow condition and returns a token that identifies it. The
94
  /// token can be used to perform various operations on the flow condition such
95
  /// as adding constraints to it, forking it, joining it with another flow
96
  /// condition, or checking implications.
97
13.4k
  AtomicBoolValue &makeFlowConditionToken() {
98
13.4k
    return create<AtomicBoolValue>();
99
13.4k
  }
100
101
private:
102
  // Storage for the state of a program.
103
  std::vector<std::unique_ptr<StorageLocation>> Locs;
104
  std::vector<std::unique_ptr<Value>> Vals;
105
106
  // Indices that are used to avoid recreating the same composite boolean
107
  // values.
108
  llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, ConjunctionValue *>
109
      ConjunctionVals;
110
  llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, DisjunctionValue *>
111
      DisjunctionVals;
112
  llvm::DenseMap<BoolValue *, NegationValue *> NegationVals;
113
  llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, ImplicationValue *>
114
      ImplicationVals;
115
  llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, BiconditionalValue *>
116
      BiconditionalVals;
117
118
  AtomicBoolValue &TrueVal;
119
  AtomicBoolValue &FalseVal;
120
};
121
122
} // namespace clang::dataflow
123
124
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE__ARENA_H