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