Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:25

0001 //===-- Value.h -------------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file defines classes for values computed by abstract interpretation
0010 // during dataflow analysis.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_VALUE_H
0015 #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_VALUE_H
0016 
0017 #include "clang/AST/Decl.h"
0018 #include "clang/Analysis/FlowSensitive/Formula.h"
0019 #include "clang/Analysis/FlowSensitive/StorageLocation.h"
0020 #include "llvm/ADT/DenseMap.h"
0021 #include "llvm/ADT/StringMap.h"
0022 #include "llvm/ADT/StringRef.h"
0023 #include <cassert>
0024 #include <utility>
0025 
0026 namespace clang {
0027 namespace dataflow {
0028 
0029 /// Base class for all values computed by abstract interpretation.
0030 ///
0031 /// Don't use `Value` instances by value. All `Value` instances are allocated
0032 /// and owned by `DataflowAnalysisContext`.
0033 class Value {
0034 public:
0035   enum class Kind {
0036     Integer,
0037     Pointer,
0038 
0039     // TODO: Top values should not be need to be type-specific.
0040     TopBool,
0041     AtomicBool,
0042     FormulaBool,
0043   };
0044 
0045   explicit Value(Kind ValKind) : ValKind(ValKind) {}
0046 
0047   // Non-copyable because addresses of values are used as their identities
0048   // throughout framework and user code. The framework is responsible for
0049   // construction and destruction of values.
0050   Value(const Value &) = delete;
0051   Value &operator=(const Value &) = delete;
0052 
0053   virtual ~Value() = default;
0054 
0055   Kind getKind() const { return ValKind; }
0056 
0057   /// Returns the value of the synthetic property with the given `Name` or null
0058   /// if the property isn't assigned a value.
0059   Value *getProperty(llvm::StringRef Name) const {
0060     return Properties.lookup(Name);
0061   }
0062 
0063   /// Assigns `Val` as the value of the synthetic property with the given
0064   /// `Name`.
0065   ///
0066   /// Properties may not be set on `RecordValue`s; use synthetic fields instead
0067   /// (for details, see documentation for `RecordStorageLocation`).
0068   void setProperty(llvm::StringRef Name, Value &Val) {
0069     Properties.insert_or_assign(Name, &Val);
0070   }
0071 
0072   llvm::iterator_range<llvm::StringMap<Value *>::const_iterator>
0073   properties() const {
0074     return {Properties.begin(), Properties.end()};
0075   }
0076 
0077 private:
0078   Kind ValKind;
0079   llvm::StringMap<Value *> Properties;
0080 };
0081 
0082 /// An equivalence relation for values. It obeys reflexivity, symmetry and
0083 /// transitivity. It does *not* include comparison of `Properties`.
0084 ///
0085 /// Computes equivalence for these subclasses:
0086 /// * PointerValue -- pointee locations are equal. Does not compute deep
0087 ///   equality of `Value` at said location.
0088 /// * TopBoolValue -- both are `TopBoolValue`s.
0089 ///
0090 /// Otherwise, falls back to pointer equality.
0091 bool areEquivalentValues(const Value &Val1, const Value &Val2);
0092 
0093 /// Models a boolean.
0094 class BoolValue : public Value {
0095   const Formula *F;
0096 
0097 public:
0098   explicit BoolValue(Kind ValueKind, const Formula &F)
0099       : Value(ValueKind), F(&F) {}
0100 
0101   static bool classof(const Value *Val) {
0102     return Val->getKind() == Kind::TopBool ||
0103            Val->getKind() == Kind::AtomicBool ||
0104            Val->getKind() == Kind::FormulaBool;
0105   }
0106 
0107   const Formula &formula() const { return *F; }
0108 };
0109 
0110 /// A TopBoolValue represents a boolean that is explicitly unconstrained.
0111 ///
0112 /// This is equivalent to an AtomicBoolValue that does not appear anywhere
0113 /// else in a system of formula.
0114 /// Knowing the value is unconstrained is useful when e.g. reasoning about
0115 /// convergence.
0116 class TopBoolValue final : public BoolValue {
0117 public:
0118   TopBoolValue(const Formula &F) : BoolValue(Kind::TopBool, F) {
0119     assert(F.kind() == Formula::AtomRef);
0120   }
0121 
0122   static bool classof(const Value *Val) {
0123     return Val->getKind() == Kind::TopBool;
0124   }
0125 
0126   Atom getAtom() const { return formula().getAtom(); }
0127 };
0128 
0129 /// Models an atomic boolean.
0130 ///
0131 /// FIXME: Merge this class into FormulaBoolValue.
0132 ///        When we want to specify atom identity, use Atom.
0133 class AtomicBoolValue final : public BoolValue {
0134 public:
0135   explicit AtomicBoolValue(const Formula &F) : BoolValue(Kind::AtomicBool, F) {
0136     assert(F.kind() == Formula::AtomRef);
0137   }
0138 
0139   static bool classof(const Value *Val) {
0140     return Val->getKind() == Kind::AtomicBool;
0141   }
0142 
0143   Atom getAtom() const { return formula().getAtom(); }
0144 };
0145 
0146 /// Models a compound boolean formula.
0147 class FormulaBoolValue final : public BoolValue {
0148 public:
0149   explicit FormulaBoolValue(const Formula &F)
0150       : BoolValue(Kind::FormulaBool, F) {
0151     assert(F.kind() != Formula::AtomRef && "For now, use AtomicBoolValue");
0152   }
0153 
0154   static bool classof(const Value *Val) {
0155     return Val->getKind() == Kind::FormulaBool;
0156   }
0157 };
0158 
0159 /// Models an integer.
0160 class IntegerValue : public Value {
0161 public:
0162   explicit IntegerValue() : Value(Kind::Integer) {}
0163 
0164   static bool classof(const Value *Val) {
0165     return Val->getKind() == Kind::Integer;
0166   }
0167 };
0168 
0169 /// Models a symbolic pointer. Specifically, any value of type `T*`.
0170 class PointerValue final : public Value {
0171 public:
0172   explicit PointerValue(StorageLocation &PointeeLoc)
0173       : Value(Kind::Pointer), PointeeLoc(PointeeLoc) {}
0174 
0175   static bool classof(const Value *Val) {
0176     return Val->getKind() == Kind::Pointer;
0177   }
0178 
0179   StorageLocation &getPointeeLoc() const { return PointeeLoc; }
0180 
0181 private:
0182   StorageLocation &PointeeLoc;
0183 };
0184 
0185 raw_ostream &operator<<(raw_ostream &OS, const Value &Val);
0186 
0187 } // namespace dataflow
0188 } // namespace clang
0189 
0190 #endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_VALUE_H