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_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
     18 #define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
     19 
     20 #include <vector>
     21 
     22 #include "clang/ASTMatchers/ASTMatchers.h"
     23 #include "clang/ASTMatchers/ASTMatchersInternal.h"
     24 #include "llvm/ADT/Twine.h"
     25 #include "llvm/Support/type_traits.h"
     26 
     27 namespace clang {
     28 namespace ast_matchers {
     29 namespace dynamic {
     30 
     31 using ast_matchers::internal::DynTypedMatcher;
     32 
     33 /// \brief A list of \c DynTypedMatcher objects.
     34 ///
     35 /// The purpose of this list is to wrap multiple different matchers and
     36 /// provide the right one when calling \c hasTypedMatcher/getTypedMatcher.
     37 class MatcherList {
     38 public:
     39   /// \brief An empty list.
     40   MatcherList();
     41   /// \brief Clones the matcher objects.
     42   MatcherList(const MatcherList &Other);
     43   /// \brief Clones the provided matcher.
     44   MatcherList(const DynTypedMatcher &Matcher);
     45   ~MatcherList();
     46 
     47   MatcherList &operator=(const MatcherList &Other);
     48 
     49   /// \brief Add a matcher to this list. The matcher is cloned.
     50   void add(const DynTypedMatcher &Matcher);
     51 
     52   /// \brief Empties the list.
     53   void reset();
     54 
     55   /// \brief Whether the list is empty.
     56   bool empty() const { return List.empty(); }
     57 
     58   ArrayRef<const DynTypedMatcher *> matchers() const { return List; }
     59 
     60   /// \brief Determines if any of the contained matchers can be converted
     61   ///   to \c Matcher<T>.
     62   ///
     63   /// Returns true if one, and only one, of the contained matchers can be
     64   /// converted to \c Matcher<T>. If there are more than one that can, the
     65   /// result would be ambigous and false is returned.
     66   template <class T>
     67   bool hasTypedMatcher() const {
     68     size_t Matches = 0;
     69     for (size_t I = 0, E = List.size(); I != E; ++I) {
     70       Matches += ast_matchers::internal::Matcher<T>::canConstructFrom(*List[I]);
     71     }
     72     return Matches == 1;
     73   }
     74 
     75   /// \brief Wrap the correct matcher as a \c Matcher<T>.
     76   ///
     77   /// Selects the appropriate matcher from the list and returns it as a
     78   /// \c Matcher<T>.
     79   /// Asserts that \c hasTypedMatcher<T>() is true.
     80   template <class T>
     81   ast_matchers::internal::Matcher<T> getTypedMatcher() const {
     82     assert(hasTypedMatcher<T>());
     83     for (size_t I = 0, E = List.size(); I != E; ++I) {
     84       if (ast_matchers::internal::Matcher<T>::canConstructFrom(*List[I]))
     85         return ast_matchers::internal::Matcher<T>::constructFrom(*List[I]);
     86     }
     87     llvm_unreachable("!hasTypedMatcher<T>()");
     88   }
     89 
     90   /// \brief String representation of the type of the value.
     91   ///
     92   /// If there are more than one matcher on the list, the string will show all
     93   /// the types.
     94   std::string getTypeAsString() const;
     95 
     96 private:
     97   std::vector<const DynTypedMatcher *> List;
     98 };
     99 
    100 /// \brief Variant value class.
    101 ///
    102 /// Basically, a tagged union with value type semantics.
    103 /// It is used by the registry as the return value and argument type for the
    104 /// matcher factory methods.
    105 /// It can be constructed from any of the supported types. It supports
    106 /// copy/assignment.
    107 ///
    108 /// Supported types:
    109 ///  - \c unsigned
    110 ///  - \c std::string
    111 ///  - \c MatcherList (\c DynTypedMatcher / \c Matcher<T>)
    112 class VariantValue {
    113 public:
    114   VariantValue() : Type(VT_Nothing) {}
    115 
    116   VariantValue(const VariantValue &Other);
    117   ~VariantValue();
    118   VariantValue &operator=(const VariantValue &Other);
    119 
    120   /// \brief Specific constructors for each supported type.
    121   VariantValue(unsigned Unsigned);
    122   VariantValue(const std::string &String);
    123   VariantValue(const DynTypedMatcher &Matcher);
    124   VariantValue(const MatcherList &Matchers);
    125 
    126   /// \brief Unsigned value functions.
    127   bool isUnsigned() const;
    128   unsigned getUnsigned() const;
    129   void setUnsigned(unsigned Unsigned);
    130 
    131   /// \brief String value functions.
    132   bool isString() const;
    133   const std::string &getString() const;
    134   void setString(const std::string &String);
    135 
    136   /// \brief Matcher value functions.
    137   bool isMatchers() const;
    138   const MatcherList &getMatchers() const;
    139   void setMatchers(const MatcherList &Matchers);
    140 
    141   /// \brief Shortcut functions.
    142   template <class T>
    143   bool hasTypedMatcher() const {
    144     return isMatchers() && getMatchers().hasTypedMatcher<T>();
    145   }
    146 
    147   template <class T>
    148   ast_matchers::internal::Matcher<T> getTypedMatcher() const {
    149     return getMatchers().getTypedMatcher<T>();
    150   }
    151 
    152   /// \brief String representation of the type of the value.
    153   std::string getTypeAsString() const;
    154 
    155 private:
    156   void reset();
    157 
    158   /// \brief All supported value types.
    159   enum ValueType {
    160     VT_Nothing,
    161     VT_Unsigned,
    162     VT_String,
    163     VT_Matchers
    164   };
    165 
    166   /// \brief All supported value types.
    167   union AllValues {
    168     unsigned Unsigned;
    169     std::string *String;
    170     MatcherList *Matchers;
    171   };
    172 
    173   ValueType Type;
    174   AllValues Value;
    175 };
    176 
    177 } // end namespace dynamic
    178 } // end namespace ast_matchers
    179 } // end namespace clang
    180 
    181 #endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
    182