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