Coverage Report

Created: 2022-05-21 09:15

/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
class Value {
30
public:
31
  enum class Kind {
32
    Integer,
33
    Reference,
34
    Pointer,
35
    Struct,
36
37
    // Synthetic boolean values are either atomic values or composites that
38
    // represent conjunctions, disjunctions, and negations.
39
    AtomicBool,
40
    Conjunction,
41
    Disjunction,
42
    Negation
43
  };
44
45
790k
  explicit Value(Kind ValKind) : ValKind(ValKind) {}
46
47
790k
  virtual ~Value() = default;
48
49
65.6k
  Kind getKind() const { return ValKind; }
50
51
private:
52
  Kind ValKind;
53
};
54
55
/// Models a boolean.
56
class BoolValue : public Value {
57
public:
58
788k
  explicit BoolValue(Kind ValueKind) : Value(ValueKind) {}
59
60
582
  static bool classof(const Value *Val) {
61
582
    return Val->getKind() == Kind::AtomicBool ||
62
582
           
Val->getKind() == Kind::Conjunction198
||
63
582
           
Val->getKind() == Kind::Disjunction166
||
64
582
           
Val->getKind() == Kind::Negation150
;
65
582
  }
66
};
67
68
/// Models an atomic boolean.
69
class AtomicBoolValue : public BoolValue {
70
public:
71
202k
  explicit AtomicBoolValue() : BoolValue(Kind::AtomicBool) {}
72
73
  static bool classof(const Value *Val) {
74
    return Val->getKind() == Kind::AtomicBool;
75
  }
76
};
77
78
/// Models a boolean conjunction.
79
// FIXME: Consider representing binary and unary boolean operations similar
80
// to how they are represented in the AST. This might become more pressing
81
// when such operations need to be added for other data types.
82
class ConjunctionValue : public BoolValue {
83
public:
84
  explicit ConjunctionValue(BoolValue &LeftSubVal, BoolValue &RightSubVal)
85
      : BoolValue(Kind::Conjunction), LeftSubVal(LeftSubVal),
86
77
        RightSubVal(RightSubVal) {}
87
88
21.6k
  static bool classof(const Value *Val) {
89
21.6k
    return Val->getKind() == Kind::Conjunction;
90
21.6k
  }
91
92
  /// Returns the left sub-value of the conjunction.
93
113
  BoolValue &getLeftSubValue() const { return LeftSubVal; }
94
95
  /// Returns the right sub-value of the conjunction.
96
113
  BoolValue &getRightSubValue() const { return RightSubVal; }
97
98
private:
99
  BoolValue &LeftSubVal;
100
  BoolValue &RightSubVal;
101
};
102
103
/// Models a boolean disjunction.
104
class DisjunctionValue : public BoolValue {
105
public:
106
  explicit DisjunctionValue(BoolValue &LeftSubVal, BoolValue &RightSubVal)
107
      : BoolValue(Kind::Disjunction), LeftSubVal(LeftSubVal),
108
382k
        RightSubVal(RightSubVal) {}
109
110
21.5k
  static bool classof(const Value *Val) {
111
21.5k
    return Val->getKind() == Kind::Disjunction;
112
21.5k
  }
113
114
  /// Returns the left sub-value of the disjunction.
115
12.2k
  BoolValue &getLeftSubValue() const { return LeftSubVal; }
116
117
  /// Returns the right sub-value of the disjunction.
118
12.2k
  BoolValue &getRightSubValue() const { return RightSubVal; }
119
120
private:
121
  BoolValue &LeftSubVal;
122
  BoolValue &RightSubVal;
123
};
124
125
/// Models a boolean negation.
126
class NegationValue : public BoolValue {
127
public:
128
  explicit NegationValue(BoolValue &SubVal)
129
202k
      : BoolValue(Kind::Negation), SubVal(SubVal) {}
130
131
13.3k
  static bool classof(const Value *Val) {
132
13.3k
    return Val->getKind() == Kind::Negation;
133
13.3k
  }
134
135
  /// Returns the sub-value of the negation.
136
10.0k
  BoolValue &getSubVal() const { return SubVal; }
137
138
private:
139
  BoolValue &SubVal;
140
};
141
142
/// Models an integer.
143
class IntegerValue : public Value {
144
public:
145
210
  explicit IntegerValue() : Value(Kind::Integer) {}
146
147
  static bool classof(const Value *Val) {
148
    return Val->getKind() == Kind::Integer;
149
  }
150
};
151
152
/// Base class for values that refer to storage locations.
153
class IndirectionValue : public Value {
154
public:
155
  /// Constructs a value that refers to `PointeeLoc`.
156
  explicit IndirectionValue(Kind ValueKind, StorageLocation &PointeeLoc)
157
1.14k
      : Value(ValueKind), PointeeLoc(PointeeLoc) {}
158
159
33
  static bool classof(const Value *Val) {
160
33
    return Val->getKind() == Kind::Reference || 
Val->getKind() == Kind::Pointer26
;
161
33
  }
162
163
1.67k
  StorageLocation &getPointeeLoc() const { return PointeeLoc; }
164
165
private:
166
  StorageLocation &PointeeLoc;
167
};
168
169
/// Models a dereferenced pointer. For example, a reference in C++ or an lvalue
170
/// in C.
171
class ReferenceValue final : public IndirectionValue {
172
public:
173
  explicit ReferenceValue(StorageLocation &PointeeLoc)
174
1.08k
      : IndirectionValue(Kind::Reference, PointeeLoc) {}
175
176
2.34k
  static bool classof(const Value *Val) {
177
2.34k
    return Val->getKind() == Kind::Reference;
178
2.34k
  }
179
};
180
181
/// Models a symbolic pointer. Specifically, any value of type `T*`.
182
class PointerValue final : public IndirectionValue {
183
public:
184
  explicit PointerValue(StorageLocation &PointeeLoc)
185
58
      : IndirectionValue(Kind::Pointer, PointeeLoc) {}
186
187
704
  static bool classof(const Value *Val) {
188
704
    return Val->getKind() == Kind::Pointer;
189
704
  }
190
};
191
192
/// Models a value of `struct` or `class` type, with a flat map of fields to
193
/// child storage locations, containing all accessible members of base struct
194
/// and class types.
195
class StructValue final : public Value {
196
public:
197
288
  StructValue() : StructValue(llvm::DenseMap<const ValueDecl *, Value *>()) {}
Unexecuted instantiation: clang::dataflow::StructValue::StructValue()
clang::dataflow::StructValue::StructValue()
Line
Count
Source
197
288
  StructValue() : StructValue(llvm::DenseMap<const ValueDecl *, Value *>()) {}
198
199
  explicit StructValue(llvm::DenseMap<const ValueDecl *, Value *> Children)
200
818
      : Value(Kind::Struct), Children(std::move(Children)) {}
201
202
4.82k
  static bool classof(const Value *Val) {
203
4.82k
    return Val->getKind() == Kind::Struct;
204
4.82k
  }
205
206
  /// Returns the child value that is assigned for `D` or null if the child is
207
  /// not initialized.
208
212
  Value *getChild(const ValueDecl &D) const {
209
212
    auto It = Children.find(&D);
210
212
    if (It == Children.end())
211
4
      return nullptr;
212
208
    return It->second;
213
212
  }
214
215
  /// Assigns `Val` as the child value for `D`.
216
192
  void setChild(const ValueDecl &D, Value &Val) { Children[&D] = &Val; }
217
218
  /// Returns the value of the synthetic property with the given `Name` or null
219
  /// if the property isn't assigned a value.
220
1.01k
  Value *getProperty(llvm::StringRef Name) const {
221
1.01k
    auto It = Properties.find(Name);
222
1.01k
    return It == Properties.end() ? 
nullptr108
:
It->second906
;
223
1.01k
  }
224
225
  /// Assigns `Val` as the value of the synthetic property with the given
226
  /// `Name`.
227
426
  void setProperty(llvm::StringRef Name, Value &Val) {
228
426
    Properties.insert_or_assign(Name, &Val);
229
426
  }
230
231
private:
232
  llvm::DenseMap<const ValueDecl *, Value *> Children;
233
  llvm::StringMap<Value *> Properties;
234
};
235
236
} // namespace dataflow
237
} // namespace clang
238
239
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_VALUE_H