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 "clang/ASTMatchers/ASTMatchers.h" 21 #include "clang/ASTMatchers/ASTMatchersInternal.h" 22 #include "llvm/ADT/IntrusiveRefCntPtr.h" 23 #include "llvm/ADT/Optional.h" 24 #include "llvm/ADT/Twine.h" 25 #include <memory> 26 #include <vector> 27 28 namespace clang { 29 namespace ast_matchers { 30 namespace dynamic { 31 32 using ast_matchers::internal::DynTypedMatcher; 33 34 /// \brief A variant matcher object. 35 /// 36 /// The purpose of this object is to abstract simple and polymorphic matchers 37 /// into a single object type. 38 /// Polymorphic matchers might be implemented as a list of all the possible 39 /// overloads of the matcher. \c VariantMatcher knows how to select the 40 /// appropriate overload when needed. 41 /// To get a real matcher object out of a \c VariantMatcher you can do: 42 /// - getSingleMatcher() which returns a matcher, only if it is not ambiguous 43 /// to decide which matcher to return. Eg. it contains only a single 44 /// matcher, or a polymorphic one with only one overload. 45 /// - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if 46 /// the underlying matcher(s) can unambiguously return a Matcher<T>. 47 class VariantMatcher { 48 /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher. 49 class MatcherOps { 50 public: 51 virtual ~MatcherOps(); 52 virtual bool canConstructFrom(const DynTypedMatcher &Matcher, 53 bool &IsExactMatch) const = 0; 54 virtual void constructFrom(const DynTypedMatcher &Matcher) = 0; 55 virtual void constructVariadicOperator( 56 ast_matchers::internal::VariadicOperatorFunction Func, 57 ArrayRef<VariantMatcher> InnerMatchers) = 0; 58 }; 59 60 /// \brief Payload interface to be specialized by each matcher type. 61 /// 62 /// It follows a similar interface as VariantMatcher itself. 63 class Payload : public RefCountedBaseVPTR { 64 public: 65 virtual ~Payload(); 66 virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0; 67 virtual std::string getTypeAsString() const = 0; 68 virtual void makeTypedMatcher(MatcherOps &Ops) const = 0; 69 }; 70 71 public: 72 /// \brief A null matcher. 73 VariantMatcher(); 74 75 /// \brief Clones the provided matcher. 76 static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher); 77 78 /// \brief Clones the provided matchers. 79 /// 80 /// They should be the result of a polymorphic matcher. 81 static VariantMatcher 82 PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers); 83 84 /// \brief Creates a 'variadic' operator matcher. 85 /// 86 /// It will bind to the appropriate type on getTypedMatcher<T>(). 87 static VariantMatcher VariadicOperatorMatcher( 88 ast_matchers::internal::VariadicOperatorFunction Func, 89 std::vector<VariantMatcher> Args); 90 91 /// \brief Makes the matcher the "null" matcher. 92 void reset(); 93 94 /// \brief Whether the matcher is null. 95 bool isNull() const { return !Value; } 96 97 /// \brief Return a single matcher, if there is no ambiguity. 98 /// 99 /// \returns the matcher, if there is only one matcher. An empty Optional, if 100 /// the underlying matcher is a polymorphic matcher with more than one 101 /// representation. 102 llvm::Optional<DynTypedMatcher> getSingleMatcher() const; 103 104 /// \brief Determines if the contained matcher can be converted to 105 /// \c Matcher<T>. 106 /// 107 /// For the Single case, it returns true if it can be converted to 108 /// \c Matcher<T>. 109 /// For the Polymorphic case, it returns true if one, and only one, of the 110 /// overloads can be converted to \c Matcher<T>. If there are more than one 111 /// that can, the result would be ambiguous and false is returned. 112 template <class T> 113 bool hasTypedMatcher() const { 114 TypedMatcherOps<T> Ops; 115 if (Value) Value->makeTypedMatcher(Ops); 116 return Ops.hasMatcher(); 117 } 118 119 /// \brief Return this matcher as a \c Matcher<T>. 120 /// 121 /// Handles the different types (Single, Polymorphic) accordingly. 122 /// Asserts that \c hasTypedMatcher<T>() is true. 123 template <class T> 124 ast_matchers::internal::Matcher<T> getTypedMatcher() const { 125 TypedMatcherOps<T> Ops; 126 Value->makeTypedMatcher(Ops); 127 assert(Ops.hasMatcher() && "hasTypedMatcher<T>() == false"); 128 return Ops.matcher(); 129 } 130 131 /// \brief String representation of the type of the value. 132 /// 133 /// If the underlying matcher is a polymorphic one, the string will show all 134 /// the types. 135 std::string getTypeAsString() const; 136 137 private: 138 explicit VariantMatcher(Payload *Value) : Value(Value) {} 139 140 class SinglePayload; 141 class PolymorphicPayload; 142 class VariadicOpPayload; 143 144 template <typename T> 145 class TypedMatcherOps : public MatcherOps { 146 public: 147 typedef ast_matchers::internal::Matcher<T> MatcherT; 148 149 virtual bool canConstructFrom(const DynTypedMatcher &Matcher, 150 bool &IsExactMatch) const { 151 IsExactMatch = Matcher.getSupportedKind().isSame( 152 ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); 153 return Matcher.canConvertTo<T>(); 154 } 155 156 virtual void constructFrom(const DynTypedMatcher& Matcher) { 157 Out.reset(new MatcherT(Matcher.convertTo<T>())); 158 } 159 160 virtual void constructVariadicOperator( 161 ast_matchers::internal::VariadicOperatorFunction Func, 162 ArrayRef<VariantMatcher> InnerMatchers) { 163 std::vector<DynTypedMatcher> DynMatchers; 164 for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) { 165 // Abort if any of the inner matchers can't be converted to 166 // Matcher<T>. 167 if (!InnerMatchers[i].hasTypedMatcher<T>()) { 168 return; 169 } 170 DynMatchers.push_back(InnerMatchers[i].getTypedMatcher<T>()); 171 } 172 Out.reset(new MatcherT( 173 new ast_matchers::internal::VariadicOperatorMatcherInterface<T>( 174 Func, DynMatchers))); 175 } 176 177 bool hasMatcher() const { return Out.get() != nullptr; } 178 const MatcherT &matcher() const { return *Out; } 179 180 private: 181 std::unique_ptr<MatcherT> Out; 182 }; 183 184 IntrusiveRefCntPtr<const Payload> Value; 185 }; 186 187 /// \brief Variant value class. 188 /// 189 /// Basically, a tagged union with value type semantics. 190 /// It is used by the registry as the return value and argument type for the 191 /// matcher factory methods. 192 /// It can be constructed from any of the supported types. It supports 193 /// copy/assignment. 194 /// 195 /// Supported types: 196 /// - \c unsigned 197 /// - \c std::string 198 /// - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>) 199 class VariantValue { 200 public: 201 VariantValue() : Type(VT_Nothing) {} 202 203 VariantValue(const VariantValue &Other); 204 ~VariantValue(); 205 VariantValue &operator=(const VariantValue &Other); 206 207 /// \brief Specific constructors for each supported type. 208 VariantValue(unsigned Unsigned); 209 VariantValue(const std::string &String); 210 VariantValue(const VariantMatcher &Matchers); 211 212 /// \brief Returns true iff this is not an empty value. 213 LLVM_EXPLICIT operator bool() const { return hasValue(); } 214 bool hasValue() const { return Type != VT_Nothing; } 215 216 /// \brief Unsigned value functions. 217 bool isUnsigned() const; 218 unsigned getUnsigned() const; 219 void setUnsigned(unsigned Unsigned); 220 221 /// \brief String value functions. 222 bool isString() const; 223 const std::string &getString() const; 224 void setString(const std::string &String); 225 226 /// \brief Matcher value functions. 227 bool isMatcher() const; 228 const VariantMatcher &getMatcher() const; 229 void setMatcher(const VariantMatcher &Matcher); 230 231 /// \brief String representation of the type of the value. 232 std::string getTypeAsString() const; 233 234 private: 235 void reset(); 236 237 /// \brief All supported value types. 238 enum ValueType { 239 VT_Nothing, 240 VT_Unsigned, 241 VT_String, 242 VT_Matcher 243 }; 244 245 /// \brief All supported value types. 246 union AllValues { 247 unsigned Unsigned; 248 std::string *String; 249 VariantMatcher *Matcher; 250 }; 251 252 ValueType Type; 253 AllValues Value; 254 }; 255 256 } // end namespace dynamic 257 } // end namespace ast_matchers 258 } // end namespace clang 259 260 #endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H 261