1 //===--- VariantValue.h - Polymorphic value type ----------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// 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 27 namespace clang { 28 namespace ast_matchers { 29 namespace dynamic { 30 31 /// Kind identifier. 32 /// 33 /// It supports all types that VariantValue can contain. 34 class ArgKind { 35 public: 36 enum Kind { 37 AK_Matcher, 38 AK_Boolean, 39 AK_Double, 40 AK_Unsigned, 41 AK_String 42 }; 43 /// Constructor for non-matcher types. ArgKind(Kind K)44 ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); } 45 46 /// Constructor for matcher types. ArgKind(ASTNodeKind MatcherKind)47 ArgKind(ASTNodeKind MatcherKind) : K(AK_Matcher), MatcherKind(MatcherKind) {} 48 getArgKind()49 Kind getArgKind() const { return K; } getMatcherKind()50 ASTNodeKind getMatcherKind() const { 51 assert(K == AK_Matcher); 52 return MatcherKind; 53 } 54 55 /// Determines if this type can be converted to \p To. 56 /// 57 /// \param To the requested destination type. 58 /// 59 /// \param Specificity value corresponding to the "specificity" of the 60 /// conversion. 61 bool isConvertibleTo(ArgKind To, unsigned *Specificity) const; 62 63 bool operator<(const ArgKind &Other) const { 64 if (K == AK_Matcher && Other.K == AK_Matcher) 65 return MatcherKind < Other.MatcherKind; 66 return K < Other.K; 67 } 68 69 /// String representation of the type. 70 std::string asString() const; 71 72 private: 73 Kind K; 74 ASTNodeKind MatcherKind; 75 }; 76 77 using ast_matchers::internal::DynTypedMatcher; 78 79 /// A variant matcher object. 80 /// 81 /// The purpose of this object is to abstract simple and polymorphic matchers 82 /// into a single object type. 83 /// Polymorphic matchers might be implemented as a list of all the possible 84 /// overloads of the matcher. \c VariantMatcher knows how to select the 85 /// appropriate overload when needed. 86 /// To get a real matcher object out of a \c VariantMatcher you can do: 87 /// - getSingleMatcher() which returns a matcher, only if it is not ambiguous 88 /// to decide which matcher to return. Eg. it contains only a single 89 /// matcher, or a polymorphic one with only one overload. 90 /// - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if 91 /// the underlying matcher(s) can unambiguously return a Matcher<T>. 92 class VariantMatcher { 93 /// Methods that depend on T from hasTypedMatcher/getTypedMatcher. 94 class MatcherOps { 95 public: MatcherOps(ASTNodeKind NodeKind)96 MatcherOps(ASTNodeKind NodeKind) : NodeKind(NodeKind) {} 97 98 bool canConstructFrom(const DynTypedMatcher &Matcher, 99 bool &IsExactMatch) const; 100 101 /// Convert \p Matcher the destination type and return it as a new 102 /// DynTypedMatcher. 103 virtual DynTypedMatcher 104 convertMatcher(const DynTypedMatcher &Matcher) const = 0; 105 106 /// Constructs a variadic typed matcher from \p InnerMatchers. 107 /// Will try to convert each inner matcher to the destination type and 108 /// return llvm::None if it fails to do so. 109 llvm::Optional<DynTypedMatcher> 110 constructVariadicOperator(DynTypedMatcher::VariadicOperator Op, 111 ArrayRef<VariantMatcher> InnerMatchers) const; 112 113 protected: 114 ~MatcherOps() = default; 115 116 private: 117 ASTNodeKind NodeKind; 118 }; 119 120 /// Payload interface to be specialized by each matcher type. 121 /// 122 /// It follows a similar interface as VariantMatcher itself. 123 class Payload { 124 public: 125 virtual ~Payload(); 126 virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0; 127 virtual std::string getTypeAsString() const = 0; 128 virtual llvm::Optional<DynTypedMatcher> 129 getTypedMatcher(const MatcherOps &Ops) const = 0; 130 virtual bool isConvertibleTo(ASTNodeKind Kind, 131 unsigned *Specificity) const = 0; 132 }; 133 134 public: 135 /// A null matcher. 136 VariantMatcher(); 137 138 /// Clones the provided matcher. 139 static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher); 140 141 /// Clones the provided matchers. 142 /// 143 /// They should be the result of a polymorphic matcher. 144 static VariantMatcher 145 PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers); 146 147 /// Creates a 'variadic' operator matcher. 148 /// 149 /// It will bind to the appropriate type on getTypedMatcher<T>(). 150 static VariantMatcher 151 VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, 152 std::vector<VariantMatcher> Args); 153 154 /// Makes the matcher the "null" matcher. 155 void reset(); 156 157 /// Whether the matcher is null. isNull()158 bool isNull() const { return !Value; } 159 160 /// Return a single matcher, if there is no ambiguity. 161 /// 162 /// \returns the matcher, if there is only one matcher. An empty Optional, if 163 /// the underlying matcher is a polymorphic matcher with more than one 164 /// representation. 165 llvm::Optional<DynTypedMatcher> getSingleMatcher() const; 166 167 /// Determines if the contained matcher can be converted to 168 /// \c Matcher<T>. 169 /// 170 /// For the Single case, it returns true if it can be converted to 171 /// \c Matcher<T>. 172 /// For the Polymorphic case, it returns true if one, and only one, of the 173 /// overloads can be converted to \c Matcher<T>. If there are more than one 174 /// that can, the result would be ambiguous and false is returned. 175 template <class T> hasTypedMatcher()176 bool hasTypedMatcher() const { 177 if (!Value) return false; 178 return Value->getTypedMatcher(TypedMatcherOps<T>()).hasValue(); 179 } 180 181 /// Determines if the contained matcher can be converted to \p Kind. 182 /// 183 /// \param Kind the requested destination type. 184 /// 185 /// \param Specificity value corresponding to the "specificity" of the 186 /// conversion. isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity)187 bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const { 188 if (Value) 189 return Value->isConvertibleTo(Kind, Specificity); 190 return false; 191 } 192 193 /// Return this matcher as a \c Matcher<T>. 194 /// 195 /// Handles the different types (Single, Polymorphic) accordingly. 196 /// Asserts that \c hasTypedMatcher<T>() is true. 197 template <class T> getTypedMatcher()198 ast_matchers::internal::Matcher<T> getTypedMatcher() const { 199 assert(hasTypedMatcher<T>() && "hasTypedMatcher<T>() == false"); 200 return Value->getTypedMatcher(TypedMatcherOps<T>()) 201 ->template convertTo<T>(); 202 } 203 204 /// String representation of the type of the value. 205 /// 206 /// If the underlying matcher is a polymorphic one, the string will show all 207 /// the types. 208 std::string getTypeAsString() const; 209 210 private: VariantMatcher(std::shared_ptr<Payload> Value)211 explicit VariantMatcher(std::shared_ptr<Payload> Value) 212 : Value(std::move(Value)) {} 213 214 template <typename T> struct TypedMatcherOps; 215 216 class SinglePayload; 217 class PolymorphicPayload; 218 class VariadicOpPayload; 219 220 std::shared_ptr<const Payload> Value; 221 }; 222 223 template <typename T> 224 struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps { TypedMatcherOpsfinal225 TypedMatcherOps() : MatcherOps(ASTNodeKind::getFromNodeKind<T>()) {} 226 typedef ast_matchers::internal::Matcher<T> MatcherT; 227 228 DynTypedMatcher convertMatcherfinal229 convertMatcher(const DynTypedMatcher &Matcher) const override { 230 return DynTypedMatcher(Matcher.convertTo<T>()); 231 } 232 }; 233 234 /// Variant value class. 235 /// 236 /// Basically, a tagged union with value type semantics. 237 /// It is used by the registry as the return value and argument type for the 238 /// matcher factory methods. 239 /// It can be constructed from any of the supported types. It supports 240 /// copy/assignment. 241 /// 242 /// Supported types: 243 /// - \c bool 244 // - \c double 245 /// - \c unsigned 246 /// - \c llvm::StringRef 247 /// - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>) 248 class VariantValue { 249 public: VariantValue()250 VariantValue() : Type(VT_Nothing) {} 251 252 VariantValue(const VariantValue &Other); 253 ~VariantValue(); 254 VariantValue &operator=(const VariantValue &Other); 255 256 /// Specific constructors for each supported type. 257 VariantValue(bool Boolean); 258 VariantValue(double Double); 259 VariantValue(unsigned Unsigned); 260 VariantValue(StringRef String); 261 VariantValue(const VariantMatcher &Matchers); 262 263 /// Constructs an \c unsigned value (disambiguation from bool). VariantValue(int Signed)264 VariantValue(int Signed) : VariantValue(static_cast<unsigned>(Signed)) {} 265 266 /// Returns true iff this is not an empty value. 267 explicit operator bool() const { return hasValue(); } hasValue()268 bool hasValue() const { return Type != VT_Nothing; } 269 270 /// Boolean value functions. 271 bool isBoolean() const; 272 bool getBoolean() const; 273 void setBoolean(bool Boolean); 274 275 /// Double value functions. 276 bool isDouble() const; 277 double getDouble() const; 278 void setDouble(double Double); 279 280 /// Unsigned value functions. 281 bool isUnsigned() const; 282 unsigned getUnsigned() const; 283 void setUnsigned(unsigned Unsigned); 284 285 /// String value functions. 286 bool isString() const; 287 const std::string &getString() const; 288 void setString(StringRef String); 289 290 /// Matcher value functions. 291 bool isMatcher() const; 292 const VariantMatcher &getMatcher() const; 293 void setMatcher(const VariantMatcher &Matcher); 294 295 /// Determines if the contained value can be converted to \p Kind. 296 /// 297 /// \param Kind the requested destination type. 298 /// 299 /// \param Specificity value corresponding to the "specificity" of the 300 /// conversion. 301 bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const; 302 303 /// Determines if the contained value can be converted to any kind 304 /// in \p Kinds. 305 /// 306 /// \param Kinds the requested destination types. 307 /// 308 /// \param Specificity value corresponding to the "specificity" of the 309 /// conversion. It is the maximum specificity of all the possible 310 /// conversions. 311 bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const; 312 313 /// String representation of the type of the value. 314 std::string getTypeAsString() const; 315 316 private: 317 void reset(); 318 319 /// All supported value types. 320 enum ValueType { 321 VT_Nothing, 322 VT_Boolean, 323 VT_Double, 324 VT_Unsigned, 325 VT_String, 326 VT_Matcher 327 }; 328 329 /// All supported value types. 330 union AllValues { 331 unsigned Unsigned; 332 double Double; 333 bool Boolean; 334 std::string *String; 335 VariantMatcher *Matcher; 336 }; 337 338 ValueType Type; 339 AllValues Value; 340 }; 341 342 } // end namespace dynamic 343 } // end namespace ast_matchers 344 } // end namespace clang 345 346 #endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H 347