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 "llvm/Support/raw_ostream.h"
23 #include <cassert>
24 #include <utility>
25 
26 namespace clang {
27 namespace dataflow {
28 
29 /// Base class for all values computed by abstract interpretation.
30 ///
31 /// Don't use `Value` instances by value. All `Value` instances are allocated
32 /// and owned by `DataflowAnalysisContext`.
33 class Value {
34 public:
35   enum class Kind {
36     Integer,
37     Reference,
38     Pointer,
39     Struct,
40 
41     // Synthetic boolean values are either atomic values or logical connectives.
42     TopBool,
43     AtomicBool,
44     Conjunction,
45     Disjunction,
46     Negation,
47     Implication,
48     Biconditional,
49   };
50 
Value(Kind ValKind)51   explicit Value(Kind ValKind) : ValKind(ValKind) {}
52 
53   // Non-copyable because addresses of values are used as their identities
54   // throughout framework and user code. The framework is responsible for
55   // construction and destruction of values.
56   Value(const Value &) = delete;
57   Value &operator=(const Value &) = delete;
58 
59   virtual ~Value() = default;
60 
getKind()61   Kind getKind() const { return ValKind; }
62 
63   /// Returns the value of the synthetic property with the given `Name` or null
64   /// if the property isn't assigned a value.
getProperty(llvm::StringRef Name)65   Value *getProperty(llvm::StringRef Name) const {
66     auto It = Properties.find(Name);
67     return It == Properties.end() ? nullptr : It->second;
68   }
69 
70   /// Assigns `Val` as the value of the synthetic property with the given
71   /// `Name`.
setProperty(llvm::StringRef Name,Value & Val)72   void setProperty(llvm::StringRef Name, Value &Val) {
73     Properties.insert_or_assign(Name, &Val);
74   }
75 
76 private:
77   Kind ValKind;
78   llvm::StringMap<Value *> Properties;
79 };
80 
81 /// An equivalence relation for values. It obeys reflexivity, symmetry and
82 /// transitivity. It does *not* include comparison of `Properties`.
83 ///
84 /// Computes equivalence for these subclasses:
85 /// * ReferenceValue, PointerValue -- pointee locations are equal. Does not
86 ///   compute deep equality of `Value` at said location.
87 /// * TopBoolValue -- both are `TopBoolValue`s.
88 ///
89 /// Otherwise, falls back to pointer equality.
90 bool areEquivalentValues(const Value &Val1, const Value &Val2);
91 
92 /// Models a boolean.
93 class BoolValue : public Value {
94 public:
BoolValue(Kind ValueKind)95   explicit BoolValue(Kind ValueKind) : Value(ValueKind) {}
96 
classof(const Value * Val)97   static bool classof(const Value *Val) {
98     return Val->getKind() == Kind::TopBool ||
99            Val->getKind() == Kind::AtomicBool ||
100            Val->getKind() == Kind::Conjunction ||
101            Val->getKind() == Kind::Disjunction ||
102            Val->getKind() == Kind::Negation ||
103            Val->getKind() == Kind::Implication ||
104            Val->getKind() == Kind::Biconditional;
105   }
106 };
107 
108 /// Models the trivially true formula, which is Top in the lattice of boolean
109 /// formulas.
110 class TopBoolValue final : public BoolValue {
111 public:
TopBoolValue()112   TopBoolValue() : BoolValue(Kind::TopBool) {}
113 
classof(const Value * Val)114   static bool classof(const Value *Val) {
115     return Val->getKind() == Kind::TopBool;
116   }
117 };
118 
119 /// Models an atomic boolean.
120 class AtomicBoolValue : public BoolValue {
121 public:
AtomicBoolValue()122   explicit AtomicBoolValue() : BoolValue(Kind::AtomicBool) {}
123 
classof(const Value * Val)124   static bool classof(const Value *Val) {
125     return Val->getKind() == Kind::AtomicBool;
126   }
127 };
128 
129 /// Models a boolean conjunction.
130 // FIXME: Consider representing binary and unary boolean operations similar
131 // to how they are represented in the AST. This might become more pressing
132 // when such operations need to be added for other data types.
133 class ConjunctionValue : public BoolValue {
134 public:
ConjunctionValue(BoolValue & LeftSubVal,BoolValue & RightSubVal)135   explicit ConjunctionValue(BoolValue &LeftSubVal, BoolValue &RightSubVal)
136       : BoolValue(Kind::Conjunction), LeftSubVal(LeftSubVal),
137         RightSubVal(RightSubVal) {}
138 
classof(const Value * Val)139   static bool classof(const Value *Val) {
140     return Val->getKind() == Kind::Conjunction;
141   }
142 
143   /// Returns the left sub-value of the conjunction.
getLeftSubValue()144   BoolValue &getLeftSubValue() const { return LeftSubVal; }
145 
146   /// Returns the right sub-value of the conjunction.
getRightSubValue()147   BoolValue &getRightSubValue() const { return RightSubVal; }
148 
149 private:
150   BoolValue &LeftSubVal;
151   BoolValue &RightSubVal;
152 };
153 
154 /// Models a boolean disjunction.
155 class DisjunctionValue : public BoolValue {
156 public:
DisjunctionValue(BoolValue & LeftSubVal,BoolValue & RightSubVal)157   explicit DisjunctionValue(BoolValue &LeftSubVal, BoolValue &RightSubVal)
158       : BoolValue(Kind::Disjunction), LeftSubVal(LeftSubVal),
159         RightSubVal(RightSubVal) {}
160 
classof(const Value * Val)161   static bool classof(const Value *Val) {
162     return Val->getKind() == Kind::Disjunction;
163   }
164 
165   /// Returns the left sub-value of the disjunction.
getLeftSubValue()166   BoolValue &getLeftSubValue() const { return LeftSubVal; }
167 
168   /// Returns the right sub-value of the disjunction.
getRightSubValue()169   BoolValue &getRightSubValue() const { return RightSubVal; }
170 
171 private:
172   BoolValue &LeftSubVal;
173   BoolValue &RightSubVal;
174 };
175 
176 /// Models a boolean negation.
177 class NegationValue : public BoolValue {
178 public:
NegationValue(BoolValue & SubVal)179   explicit NegationValue(BoolValue &SubVal)
180       : BoolValue(Kind::Negation), SubVal(SubVal) {}
181 
classof(const Value * Val)182   static bool classof(const Value *Val) {
183     return Val->getKind() == Kind::Negation;
184   }
185 
186   /// Returns the sub-value of the negation.
getSubVal()187   BoolValue &getSubVal() const { return SubVal; }
188 
189 private:
190   BoolValue &SubVal;
191 };
192 
193 /// Models a boolean implication.
194 ///
195 /// Equivalent to `!LHS v RHS`.
196 class ImplicationValue : public BoolValue {
197 public:
ImplicationValue(BoolValue & LeftSubVal,BoolValue & RightSubVal)198   explicit ImplicationValue(BoolValue &LeftSubVal, BoolValue &RightSubVal)
199       : BoolValue(Kind::Implication), LeftSubVal(LeftSubVal),
200         RightSubVal(RightSubVal) {}
201 
classof(const Value * Val)202   static bool classof(const Value *Val) {
203     return Val->getKind() == Kind::Implication;
204   }
205 
206   /// Returns the left sub-value of the implication.
getLeftSubValue()207   BoolValue &getLeftSubValue() const { return LeftSubVal; }
208 
209   /// Returns the right sub-value of the implication.
getRightSubValue()210   BoolValue &getRightSubValue() const { return RightSubVal; }
211 
212 private:
213   BoolValue &LeftSubVal;
214   BoolValue &RightSubVal;
215 };
216 
217 /// Models a boolean biconditional.
218 ///
219 /// Equivalent to `(LHS ^ RHS) v (!LHS ^ !RHS)`.
220 class BiconditionalValue : public BoolValue {
221 public:
BiconditionalValue(BoolValue & LeftSubVal,BoolValue & RightSubVal)222   explicit BiconditionalValue(BoolValue &LeftSubVal, BoolValue &RightSubVal)
223       : BoolValue(Kind::Biconditional), LeftSubVal(LeftSubVal),
224         RightSubVal(RightSubVal) {}
225 
classof(const Value * Val)226   static bool classof(const Value *Val) {
227     return Val->getKind() == Kind::Biconditional;
228   }
229 
230   /// Returns the left sub-value of the biconditional.
getLeftSubValue()231   BoolValue &getLeftSubValue() const { return LeftSubVal; }
232 
233   /// Returns the right sub-value of the biconditional.
getRightSubValue()234   BoolValue &getRightSubValue() const { return RightSubVal; }
235 
236 private:
237   BoolValue &LeftSubVal;
238   BoolValue &RightSubVal;
239 };
240 
241 /// Models an integer.
242 class IntegerValue : public Value {
243 public:
IntegerValue()244   explicit IntegerValue() : Value(Kind::Integer) {}
245 
classof(const Value * Val)246   static bool classof(const Value *Val) {
247     return Val->getKind() == Kind::Integer;
248   }
249 };
250 
251 /// Models a dereferenced pointer. For example, a reference in C++ or an lvalue
252 /// in C.
253 class ReferenceValue final : public Value {
254 public:
ReferenceValue(StorageLocation & ReferentLoc)255   explicit ReferenceValue(StorageLocation &ReferentLoc)
256       : Value(Kind::Reference), ReferentLoc(ReferentLoc) {}
257 
classof(const Value * Val)258   static bool classof(const Value *Val) {
259     return Val->getKind() == Kind::Reference;
260   }
261 
getReferentLoc()262   StorageLocation &getReferentLoc() const { return ReferentLoc; }
263 
264 private:
265   StorageLocation &ReferentLoc;
266 };
267 
268 /// Models a symbolic pointer. Specifically, any value of type `T*`.
269 class PointerValue final : public Value {
270 public:
PointerValue(StorageLocation & PointeeLoc)271   explicit PointerValue(StorageLocation &PointeeLoc)
272       : Value(Kind::Pointer), PointeeLoc(PointeeLoc) {}
273 
classof(const Value * Val)274   static bool classof(const Value *Val) {
275     return Val->getKind() == Kind::Pointer;
276   }
277 
getPointeeLoc()278   StorageLocation &getPointeeLoc() const { return PointeeLoc; }
279 
280 private:
281   StorageLocation &PointeeLoc;
282 };
283 
284 /// Models a value of `struct` or `class` type, with a flat map of fields to
285 /// child storage locations, containing all accessible members of base struct
286 /// and class types.
287 class StructValue final : public Value {
288 public:
StructValue()289   StructValue() : StructValue(llvm::DenseMap<const ValueDecl *, Value *>()) {}
290 
StructValue(llvm::DenseMap<const ValueDecl *,Value * > Children)291   explicit StructValue(llvm::DenseMap<const ValueDecl *, Value *> Children)
292       : Value(Kind::Struct), Children(std::move(Children)) {}
293 
classof(const Value * Val)294   static bool classof(const Value *Val) {
295     return Val->getKind() == Kind::Struct;
296   }
297 
298   /// Returns the child value that is assigned for `D` or null if the child is
299   /// not initialized.
getChild(const ValueDecl & D)300   Value *getChild(const ValueDecl &D) const {
301     auto It = Children.find(&D);
302     if (It == Children.end())
303       return nullptr;
304     return It->second;
305   }
306 
307   /// Assigns `Val` as the child value for `D`.
setChild(const ValueDecl & D,Value & Val)308   void setChild(const ValueDecl &D, Value &Val) { Children[&D] = &Val; }
309 
310 private:
311   llvm::DenseMap<const ValueDecl *, Value *> Children;
312 };
313 
314 raw_ostream &operator<<(raw_ostream &OS, const Value &Val);
315 
316 } // namespace dataflow
317 } // namespace clang
318 
319 #endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_VALUE_H
320