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