/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 |