Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  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.  
  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.  
  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.
  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`.
  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:
  95.   explicit BoolValue(Kind ValueKind) : Value(ValueKind) {}
  96.  
  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:
  112.   TopBoolValue() : BoolValue(Kind::TopBool) {}
  113.  
  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:
  122.   explicit AtomicBoolValue() : BoolValue(Kind::AtomicBool) {}
  123.  
  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:
  135.   explicit ConjunctionValue(BoolValue &LeftSubVal, BoolValue &RightSubVal)
  136.       : BoolValue(Kind::Conjunction), LeftSubVal(LeftSubVal),
  137.         RightSubVal(RightSubVal) {}
  138.  
  139.   static bool classof(const Value *Val) {
  140.     return Val->getKind() == Kind::Conjunction;
  141.   }
  142.  
  143.   /// Returns the left sub-value of the conjunction.
  144.   BoolValue &getLeftSubValue() const { return LeftSubVal; }
  145.  
  146.   /// Returns the right sub-value of the conjunction.
  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:
  157.   explicit DisjunctionValue(BoolValue &LeftSubVal, BoolValue &RightSubVal)
  158.       : BoolValue(Kind::Disjunction), LeftSubVal(LeftSubVal),
  159.         RightSubVal(RightSubVal) {}
  160.  
  161.   static bool classof(const Value *Val) {
  162.     return Val->getKind() == Kind::Disjunction;
  163.   }
  164.  
  165.   /// Returns the left sub-value of the disjunction.
  166.   BoolValue &getLeftSubValue() const { return LeftSubVal; }
  167.  
  168.   /// Returns the right sub-value of the disjunction.
  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:
  179.   explicit NegationValue(BoolValue &SubVal)
  180.       : BoolValue(Kind::Negation), SubVal(SubVal) {}
  181.  
  182.   static bool classof(const Value *Val) {
  183.     return Val->getKind() == Kind::Negation;
  184.   }
  185.  
  186.   /// Returns the sub-value of the negation.
  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:
  198.   explicit ImplicationValue(BoolValue &LeftSubVal, BoolValue &RightSubVal)
  199.       : BoolValue(Kind::Implication), LeftSubVal(LeftSubVal),
  200.         RightSubVal(RightSubVal) {}
  201.  
  202.   static bool classof(const Value *Val) {
  203.     return Val->getKind() == Kind::Implication;
  204.   }
  205.  
  206.   /// Returns the left sub-value of the implication.
  207.   BoolValue &getLeftSubValue() const { return LeftSubVal; }
  208.  
  209.   /// Returns the right sub-value of the implication.
  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:
  222.   explicit BiconditionalValue(BoolValue &LeftSubVal, BoolValue &RightSubVal)
  223.       : BoolValue(Kind::Biconditional), LeftSubVal(LeftSubVal),
  224.         RightSubVal(RightSubVal) {}
  225.  
  226.   static bool classof(const Value *Val) {
  227.     return Val->getKind() == Kind::Biconditional;
  228.   }
  229.  
  230.   /// Returns the left sub-value of the biconditional.
  231.   BoolValue &getLeftSubValue() const { return LeftSubVal; }
  232.  
  233.   /// Returns the right sub-value of the biconditional.
  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:
  244.   explicit IntegerValue() : Value(Kind::Integer) {}
  245.  
  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:
  255.   explicit ReferenceValue(StorageLocation &ReferentLoc)
  256.       : Value(Kind::Reference), ReferentLoc(ReferentLoc) {}
  257.  
  258.   static bool classof(const Value *Val) {
  259.     return Val->getKind() == Kind::Reference;
  260.   }
  261.  
  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:
  271.   explicit PointerValue(StorageLocation &PointeeLoc)
  272.       : Value(Kind::Pointer), PointeeLoc(PointeeLoc) {}
  273.  
  274.   static bool classof(const Value *Val) {
  275.     return Val->getKind() == Kind::Pointer;
  276.   }
  277.  
  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:
  289.   StructValue() : StructValue(llvm::DenseMap<const ValueDecl *, Value *>()) {}
  290.  
  291.   explicit StructValue(llvm::DenseMap<const ValueDecl *, Value *> Children)
  292.       : Value(Kind::Struct), Children(std::move(Children)) {}
  293.  
  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.
  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`.
  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.