Coverage Report

Created: 2022-07-16 07:03

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/Analysis/FlowSensitive/Value.h
Line
Count
Source
1
//===-- Value.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 classes for values computed by abstract interpretation
10
// during dataflow analysis.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_VALUE_H
15
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_VALUE_H
16
17
#include "clang/AST/Decl.h"
18
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
19
#include "llvm/ADT/DenseMap.h"
20
#include "llvm/ADT/StringMap.h"
21
#include "llvm/ADT/StringRef.h"
22
#include <cassert>
23
#include <utility>
24
25
namespace clang {
26
namespace dataflow {
27
28
/// Base class for all values computed by abstract interpretation.
29
///
30
/// Don't use `Value` instances by value. All `Value` instances are allocated
31
/// and owned by `DataflowAnalysisContext`.
32
class Value {
33
public:
34
  enum class Kind {
35
    Integer,
36
    Reference,
37
    Pointer,
38
    Struct,
39
40
    // Synthetic boolean values are either atomic values or composites that
41
    // represent conjunctions, disjunctions, and negations.
42
    AtomicBool,
43
    Conjunction,
44
    Disjunction,
45
    Negation
46
  };
47
48
25.8k
  explicit Value(Kind ValKind) : ValKind(ValKind) {}
49
50
  // Non-copyable because addresses of values are used as their identities
51
  // throughout framework and user code. The framework is responsible for
52
  // construction and destruction of values.
53
  Value(const Value &) = delete;
54
  Value &operator=(const Value &) = delete;
55
56
25.8k
  virtual ~Value() = default;
57
58
187k
  Kind getKind() const { return ValKind; }
59
60
  /// Returns the value of the synthetic property with the given `Name` or null
61
  /// if the property isn't assigned a value.
62
2.45k
  Value *getProperty(llvm::StringRef Name) const {
63
2.45k
    auto It = Properties.find(Name);
64
2.45k
    return It == Properties.end() ? 
nullptr633
:
It->second1.82k
;
65
2.45k
  }
66
67
  /// Assigns `Val` as the value of the synthetic property with the given
68
  /// `Name`.
69
1.24k
  void setProperty(llvm::StringRef Name, Value &Val) {
70
1.24k
    Properties.insert_or_assign(Name, &Val);
71
1.24k
  }
72
73
private:
74
  Kind ValKind;
75
  llvm::StringMap<Value *> Properties;
76
};
77
78
/// Models a boolean.
79
class BoolValue : public Value {
80
public:
81
21.3k
  explicit BoolValue(Kind ValueKind) : Value(ValueKind) {}
82
83
4.02k
  static bool classof(const Value *Val) {
84
4.02k
    return Val->getKind() == Kind::AtomicBool ||
85
4.02k
           
Val->getKind() == Kind::Conjunction892
||
86
4.02k
           
Val->getKind() == Kind::Disjunction720
||
87
4.02k
           
Val->getKind() == Kind::Negation684
;
88
4.02k
  }
89
};
90
91
/// Models an atomic boolean.
92
class AtomicBoolValue : public BoolValue {
93
public:
94
9.93k
  explicit AtomicBoolValue() : BoolValue(Kind::AtomicBool) {}
95
96
17.9k
  static bool classof(const Value *Val) {
97
17.9k
    return Val->getKind() == Kind::AtomicBool;
98
17.9k
  }
99
};
100
101
/// Models a boolean conjunction.
102
// FIXME: Consider representing binary and unary boolean operations similar
103
// to how they are represented in the AST. This might become more pressing
104
// when such operations need to be added for other data types.
105
class ConjunctionValue : public BoolValue {
106
public:
107
  explicit ConjunctionValue(BoolValue &LeftSubVal, BoolValue &RightSubVal)
108
      : BoolValue(Kind::Conjunction), LeftSubVal(LeftSubVal),
109
2.87k
        RightSubVal(RightSubVal) {}
110
111
41.7k
  static bool classof(const Value *Val) {
112
41.7k
    return Val->getKind() == Kind::Conjunction;
113
41.7k
  }
114
115
  /// Returns the left sub-value of the conjunction.
116
18.0k
  BoolValue &getLeftSubValue() const { return LeftSubVal; }
117
118
  /// Returns the right sub-value of the conjunction.
119
18.0k
  BoolValue &getRightSubValue() const { return RightSubVal; }
120
121
private:
122
  BoolValue &LeftSubVal;
123
  BoolValue &RightSubVal;
124
};
125
126
/// Models a boolean disjunction.
127
class DisjunctionValue : public BoolValue {
128
public:
129
  explicit DisjunctionValue(BoolValue &LeftSubVal, BoolValue &RightSubVal)
130
      : BoolValue(Kind::Disjunction), LeftSubVal(LeftSubVal),
131
4.73k
        RightSubVal(RightSubVal) {}
132
133
41.6k
  static bool classof(const Value *Val) {
134
41.6k
    return Val->getKind() == Kind::Disjunction;
135
41.6k
  }
136
137
  /// Returns the left sub-value of the disjunction.
138
30.3k
  BoolValue &getLeftSubValue() const { return LeftSubVal; }
139
140
  /// Returns the right sub-value of the disjunction.
141
30.3k
  BoolValue &getRightSubValue() const { return RightSubVal; }
142
143
private:
144
  BoolValue &LeftSubVal;
145
  BoolValue &RightSubVal;
146
};
147
148
/// Models a boolean negation.
149
class NegationValue : public BoolValue {
150
public:
151
  explicit NegationValue(BoolValue &SubVal)
152
3.76k
      : BoolValue(Kind::Negation), SubVal(SubVal) {}
153
154
29.1k
  static bool classof(const Value *Val) {
155
29.1k
    return Val->getKind() == Kind::Negation;
156
29.1k
  }
157
158
  /// Returns the sub-value of the negation.
159
26.1k
  BoolValue &getSubVal() const { return SubVal; }
160
161
private:
162
  BoolValue &SubVal;
163
};
164
165
/// Models an integer.
166
class IntegerValue : public Value {
167
public:
168
611
  explicit IntegerValue() : Value(Kind::Integer) {}
169
170
674
  static bool classof(const Value *Val) {
171
674
    return Val->getKind() == Kind::Integer;
172
674
  }
173
};
174
175
/// Models a dereferenced pointer. For example, a reference in C++ or an lvalue
176
/// in C.
177
class ReferenceValue final : public Value {
178
public:
179
  explicit ReferenceValue(StorageLocation &ReferentLoc)
180
2.21k
      : Value(Kind::Reference), ReferentLoc(ReferentLoc) {}
181
182
7.38k
  static bool classof(const Value *Val) {
183
7.38k
    return Val->getKind() == Kind::Reference;
184
7.38k
  }
185
186
3.20k
  StorageLocation &getReferentLoc() const { return ReferentLoc; }
187
188
private:
189
  StorageLocation &ReferentLoc;
190
};
191
192
/// Models a symbolic pointer. Specifically, any value of type `T*`.
193
class PointerValue final : public Value {
194
public:
195
  explicit PointerValue(StorageLocation &PointeeLoc)
196
134
      : Value(Kind::Pointer), PointeeLoc(PointeeLoc) {}
197
198
1.90k
  static bool classof(const Value *Val) {
199
1.90k
    return Val->getKind() == Kind::Pointer;
200
1.90k
  }
201
202
189
  StorageLocation &getPointeeLoc() const { return PointeeLoc; }
203
204
private:
205
  StorageLocation &PointeeLoc;
206
};
207
208
/// Models a value of `struct` or `class` type, with a flat map of fields to
209
/// child storage locations, containing all accessible members of base struct
210
/// and class types.
211
class StructValue final : public Value {
212
public:
213
510
  StructValue() : StructValue(llvm::DenseMap<const ValueDecl *, Value *>()) {}
Unexecuted instantiation: clang::dataflow::StructValue::StructValue()
clang::dataflow::StructValue::StructValue()
Line
Count
Source
213
510
  StructValue() : StructValue(llvm::DenseMap<const ValueDecl *, Value *>()) {}
214
215
  explicit StructValue(llvm::DenseMap<const ValueDecl *, Value *> Children)
216
1.54k
      : Value(Kind::Struct), Children(std::move(Children)) {}
217
218
7.65k
  static bool classof(const Value *Val) {
219
7.65k
    return Val->getKind() == Kind::Struct;
220
7.65k
  }
221
222
  /// Returns the child value that is assigned for `D` or null if the child is
223
  /// not initialized.
224
266
  Value *getChild(const ValueDecl &D) const {
225
266
    auto It = Children.find(&D);
226
266
    if (It == Children.end())
227
2
      return nullptr;
228
264
    return It->second;
229
266
  }
230
231
  /// Assigns `Val` as the child value for `D`.
232
248
  void setChild(const ValueDecl &D, Value &Val) { Children[&D] = &Val; }
233
234
private:
235
  llvm::DenseMap<const ValueDecl *, Value *> Children;
236
};
237
238
} // namespace dataflow
239
} // namespace clang
240
241
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_VALUE_H