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