Home | History | Annotate | Line # | Download | only in Dynamic
      1 //===--- VariantValue.h - Polymorphic value type ----------------*- 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 /// \file
     10 /// Polymorphic value type.
     11 ///
     12 /// Supports all the types required for dynamic Matcher construction.
     13 ///  Used by the registry to construct matchers in a generic way.
     14 ///
     15 //===----------------------------------------------------------------------===//
     16 
     17 #ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
     18 #define LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
     19 
     20 #include "clang/ASTMatchers/ASTMatchers.h"
     21 #include "clang/ASTMatchers/ASTMatchersInternal.h"
     22 #include "llvm/ADT/IntrusiveRefCntPtr.h"
     23 #include "llvm/ADT/Optional.h"
     24 #include <memory>
     25 #include <vector>
     26 
     27 namespace clang {
     28 namespace ast_matchers {
     29 namespace dynamic {
     30 
     31 /// Kind identifier.
     32 ///
     33 /// It supports all types that VariantValue can contain.
     34 class ArgKind {
     35  public:
     36   enum Kind {
     37     AK_Matcher,
     38     AK_Node,
     39     AK_Boolean,
     40     AK_Double,
     41     AK_Unsigned,
     42     AK_String
     43   };
     44   /// Constructor for non-matcher types.
     45   ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); }
     46 
     47   /// Constructor for matcher types.
     48   static ArgKind MakeMatcherArg(ASTNodeKind MatcherKind) {
     49     return ArgKind{AK_Matcher, MatcherKind};
     50   }
     51 
     52   static ArgKind MakeNodeArg(ASTNodeKind MatcherKind) {
     53     return ArgKind{AK_Node, MatcherKind};
     54   }
     55 
     56   Kind getArgKind() const { return K; }
     57   ASTNodeKind getMatcherKind() const {
     58     assert(K == AK_Matcher);
     59     return NodeKind;
     60   }
     61   ASTNodeKind getNodeKind() const {
     62     assert(K == AK_Node);
     63     return NodeKind;
     64   }
     65 
     66   /// Determines if this type can be converted to \p To.
     67   ///
     68   /// \param To the requested destination type.
     69   ///
     70   /// \param Specificity value corresponding to the "specificity" of the
     71   ///   conversion.
     72   bool isConvertibleTo(ArgKind To, unsigned *Specificity) const;
     73 
     74   bool operator<(const ArgKind &Other) const {
     75     if ((K == AK_Matcher && Other.K == AK_Matcher) ||
     76         (K == AK_Node && Other.K == AK_Node))
     77       return NodeKind < Other.NodeKind;
     78     return K < Other.K;
     79   }
     80 
     81   /// String representation of the type.
     82   std::string asString() const;
     83 
     84 private:
     85   ArgKind(Kind K, ASTNodeKind NK) : K(K), NodeKind(NK) {}
     86   Kind K;
     87   ASTNodeKind NodeKind;
     88 };
     89 
     90 using ast_matchers::internal::DynTypedMatcher;
     91 
     92 /// A variant matcher object.
     93 ///
     94 /// The purpose of this object is to abstract simple and polymorphic matchers
     95 /// into a single object type.
     96 /// Polymorphic matchers might be implemented as a list of all the possible
     97 /// overloads of the matcher. \c VariantMatcher knows how to select the
     98 /// appropriate overload when needed.
     99 /// To get a real matcher object out of a \c VariantMatcher you can do:
    100 ///  - getSingleMatcher() which returns a matcher, only if it is not ambiguous
    101 ///    to decide which matcher to return. Eg. it contains only a single
    102 ///    matcher, or a polymorphic one with only one overload.
    103 ///  - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if
    104 ///    the underlying matcher(s) can unambiguously return a Matcher<T>.
    105 class VariantMatcher {
    106   /// Methods that depend on T from hasTypedMatcher/getTypedMatcher.
    107   class MatcherOps {
    108   public:
    109     MatcherOps(ASTNodeKind NodeKind) : NodeKind(NodeKind) {}
    110 
    111     bool canConstructFrom(const DynTypedMatcher &Matcher,
    112                           bool &IsExactMatch) const;
    113 
    114     /// Convert \p Matcher the destination type and return it as a new
    115     /// DynTypedMatcher.
    116     DynTypedMatcher convertMatcher(const DynTypedMatcher &Matcher) const;
    117 
    118     /// Constructs a variadic typed matcher from \p InnerMatchers.
    119     /// Will try to convert each inner matcher to the destination type and
    120     /// return llvm::None if it fails to do so.
    121     llvm::Optional<DynTypedMatcher>
    122     constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,
    123                               ArrayRef<VariantMatcher> InnerMatchers) const;
    124 
    125   private:
    126     ASTNodeKind NodeKind;
    127   };
    128 
    129   /// Payload interface to be specialized by each matcher type.
    130   ///
    131   /// It follows a similar interface as VariantMatcher itself.
    132   class Payload {
    133   public:
    134     virtual ~Payload();
    135     virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
    136     virtual std::string getTypeAsString() const = 0;
    137     virtual llvm::Optional<DynTypedMatcher>
    138     getTypedMatcher(const MatcherOps &Ops) const = 0;
    139     virtual bool isConvertibleTo(ASTNodeKind Kind,
    140                                  unsigned *Specificity) const = 0;
    141   };
    142 
    143 public:
    144   /// A null matcher.
    145   VariantMatcher();
    146 
    147   /// Clones the provided matcher.
    148   static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher);
    149 
    150   /// Clones the provided matchers.
    151   ///
    152   /// They should be the result of a polymorphic matcher.
    153   static VariantMatcher
    154   PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers);
    155 
    156   /// Creates a 'variadic' operator matcher.
    157   ///
    158   /// It will bind to the appropriate type on getTypedMatcher<T>().
    159   static VariantMatcher
    160   VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,
    161                           std::vector<VariantMatcher> Args);
    162 
    163   /// Makes the matcher the "null" matcher.
    164   void reset();
    165 
    166   /// Whether the matcher is null.
    167   bool isNull() const { return !Value; }
    168 
    169   /// Return a single matcher, if there is no ambiguity.
    170   ///
    171   /// \returns the matcher, if there is only one matcher. An empty Optional, if
    172   /// the underlying matcher is a polymorphic matcher with more than one
    173   /// representation.
    174   llvm::Optional<DynTypedMatcher> getSingleMatcher() const;
    175 
    176   /// Determines if the contained matcher can be converted to
    177   ///   \c Matcher<T>.
    178   ///
    179   /// For the Single case, it returns true if it can be converted to
    180   /// \c Matcher<T>.
    181   /// For the Polymorphic case, it returns true if one, and only one, of the
    182   /// overloads can be converted to \c Matcher<T>. If there are more than one
    183   /// that can, the result would be ambiguous and false is returned.
    184   template <class T>
    185   bool hasTypedMatcher() const {
    186     return hasTypedMatcher(ASTNodeKind::getFromNodeKind<T>());
    187   }
    188 
    189   bool hasTypedMatcher(ASTNodeKind NK) const {
    190     if (!Value) return false;
    191     return Value->getTypedMatcher(MatcherOps(NK)).hasValue();
    192   }
    193 
    194   /// Determines if the contained matcher can be converted to \p Kind.
    195   ///
    196   /// \param Kind the requested destination type.
    197   ///
    198   /// \param Specificity value corresponding to the "specificity" of the
    199   ///   conversion.
    200   bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const {
    201     if (Value)
    202       return Value->isConvertibleTo(Kind, Specificity);
    203     return false;
    204   }
    205 
    206   /// Return this matcher as a \c Matcher<T>.
    207   ///
    208   /// Handles the different types (Single, Polymorphic) accordingly.
    209   /// Asserts that \c hasTypedMatcher<T>() is true.
    210   template <class T>
    211   ast_matchers::internal::Matcher<T> getTypedMatcher() const {
    212     assert(hasTypedMatcher<T>() && "hasTypedMatcher<T>() == false");
    213     return Value->getTypedMatcher(MatcherOps(ASTNodeKind::getFromNodeKind<T>()))
    214         ->template convertTo<T>();
    215   }
    216 
    217   DynTypedMatcher getTypedMatcher(ASTNodeKind NK) const {
    218     assert(hasTypedMatcher(NK) && "hasTypedMatcher(NK) == false");
    219     return *Value->getTypedMatcher(MatcherOps(NK));
    220   }
    221 
    222   /// String representation of the type of the value.
    223   ///
    224   /// If the underlying matcher is a polymorphic one, the string will show all
    225   /// the types.
    226   std::string getTypeAsString() const;
    227 
    228 private:
    229   explicit VariantMatcher(std::shared_ptr<Payload> Value)
    230       : Value(std::move(Value)) {}
    231 
    232 
    233   class SinglePayload;
    234   class PolymorphicPayload;
    235   class VariadicOpPayload;
    236 
    237   std::shared_ptr<const Payload> Value;
    238 };
    239 
    240 /// Variant value class.
    241 ///
    242 /// Basically, a tagged union with value type semantics.
    243 /// It is used by the registry as the return value and argument type for the
    244 /// matcher factory methods.
    245 /// It can be constructed from any of the supported types. It supports
    246 /// copy/assignment.
    247 ///
    248 /// Supported types:
    249 ///  - \c bool
    250 //   - \c double
    251 ///  - \c unsigned
    252 ///  - \c llvm::StringRef
    253 ///  - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
    254 class VariantValue {
    255 public:
    256   VariantValue() : Type(VT_Nothing) {}
    257 
    258   VariantValue(const VariantValue &Other);
    259   ~VariantValue();
    260   VariantValue &operator=(const VariantValue &Other);
    261 
    262   /// Specific constructors for each supported type.
    263   VariantValue(bool Boolean);
    264   VariantValue(double Double);
    265   VariantValue(unsigned Unsigned);
    266   VariantValue(StringRef String);
    267   VariantValue(ASTNodeKind NodeKind);
    268   VariantValue(const VariantMatcher &Matchers);
    269 
    270   /// Constructs an \c unsigned value (disambiguation from bool).
    271   VariantValue(int Signed) : VariantValue(static_cast<unsigned>(Signed)) {}
    272 
    273   /// Returns true iff this is not an empty value.
    274   explicit operator bool() const { return hasValue(); }
    275   bool hasValue() const { return Type != VT_Nothing; }
    276 
    277   /// Boolean value functions.
    278   bool isBoolean() const;
    279   bool getBoolean() const;
    280   void setBoolean(bool Boolean);
    281 
    282   /// Double value functions.
    283   bool isDouble() const;
    284   double getDouble() const;
    285   void setDouble(double Double);
    286 
    287   /// Unsigned value functions.
    288   bool isUnsigned() const;
    289   unsigned getUnsigned() const;
    290   void setUnsigned(unsigned Unsigned);
    291 
    292   /// String value functions.
    293   bool isString() const;
    294   const std::string &getString() const;
    295   void setString(StringRef String);
    296 
    297   bool isNodeKind() const;
    298   const ASTNodeKind &getNodeKind() const;
    299   void setNodeKind(ASTNodeKind NodeKind);
    300 
    301   /// Matcher value functions.
    302   bool isMatcher() const;
    303   const VariantMatcher &getMatcher() const;
    304   void setMatcher(const VariantMatcher &Matcher);
    305 
    306   /// Determines if the contained value can be converted to \p Kind.
    307   ///
    308   /// \param Kind the requested destination type.
    309   ///
    310   /// \param Specificity value corresponding to the "specificity" of the
    311   ///   conversion.
    312   bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const;
    313 
    314   /// Determines if the contained value can be converted to any kind
    315   /// in \p Kinds.
    316   ///
    317   /// \param Kinds the requested destination types.
    318   ///
    319   /// \param Specificity value corresponding to the "specificity" of the
    320   ///   conversion. It is the maximum specificity of all the possible
    321   ///   conversions.
    322   bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const;
    323 
    324   /// String representation of the type of the value.
    325   std::string getTypeAsString() const;
    326 
    327 private:
    328   void reset();
    329 
    330   /// All supported value types.
    331   enum ValueType {
    332     VT_Nothing,
    333     VT_Boolean,
    334     VT_Double,
    335     VT_Unsigned,
    336     VT_String,
    337     VT_Matcher,
    338     VT_NodeKind
    339   };
    340 
    341   /// All supported value types.
    342   union AllValues {
    343     unsigned Unsigned;
    344     double Double;
    345     bool Boolean;
    346     std::string *String;
    347     VariantMatcher *Matcher;
    348     ASTNodeKind *NodeKind;
    349   };
    350 
    351   ValueType Type;
    352   AllValues Value;
    353 };
    354 
    355 } // end namespace dynamic
    356 } // end namespace ast_matchers
    357 } // end namespace clang
    358 
    359 #endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
    360