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