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 27namespace clang { 28namespace ast_matchers { 29namespace dynamic { 30 31/// \brief Kind identifier. 32/// 33/// It supports all types that VariantValue can contain. 34class 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 73private: 74 Kind K; 75 ast_type_traits::ASTNodeKind MatcherKind; 76}; 77 78using 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>. 93class 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 135public: 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 212private: 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 225template <typename T> 226struct 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>) 251class VariantValue { 252public: 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 319private: 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