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