1259701Sdim//===--- VariantValue.h - Polymorphic value type -*- C++ -*-===/ 2353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 3353358Sdim// See https://llvm.org/LICENSE.txt for license information. 4353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 5259701Sdim// 6259701Sdim//===----------------------------------------------------------------------===// 7259701Sdim/// 8259701Sdim/// \file 9341825Sdim/// Polymorphic value type. 10259701Sdim/// 11259701Sdim/// Supports all the types required for dynamic Matcher construction. 12259701Sdim/// Used by the registry to construct matchers in a generic way. 13259701Sdim/// 14259701Sdim//===----------------------------------------------------------------------===// 15259701Sdim 16280031Sdim#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H 17280031Sdim#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H 18259701Sdim 19259701Sdim#include "clang/ASTMatchers/ASTMatchers.h" 20259701Sdim#include "clang/ASTMatchers/ASTMatchersInternal.h" 21259701Sdim#include "llvm/ADT/IntrusiveRefCntPtr.h" 22259701Sdim#include "llvm/ADT/Optional.h" 23276479Sdim#include <memory> 24276479Sdim#include <vector> 25259701Sdim 26259701Sdimnamespace clang { 27259701Sdimnamespace ast_matchers { 28259701Sdimnamespace dynamic { 29259701Sdim 30341825Sdim/// Kind identifier. 31280031Sdim/// 32280031Sdim/// It supports all types that VariantValue can contain. 33280031Sdimclass ArgKind { 34280031Sdim public: 35280031Sdim enum Kind { 36280031Sdim AK_Matcher, 37321369Sdim AK_Boolean, 38321369Sdim AK_Double, 39280031Sdim AK_Unsigned, 40280031Sdim AK_String 41280031Sdim }; 42341825Sdim /// Constructor for non-matcher types. 43280031Sdim ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); } 44280031Sdim 45341825Sdim /// Constructor for matcher types. 46280031Sdim ArgKind(ast_type_traits::ASTNodeKind MatcherKind) 47280031Sdim : K(AK_Matcher), MatcherKind(MatcherKind) {} 48280031Sdim 49280031Sdim Kind getArgKind() const { return K; } 50280031Sdim ast_type_traits::ASTNodeKind getMatcherKind() const { 51280031Sdim assert(K == AK_Matcher); 52280031Sdim return MatcherKind; 53280031Sdim } 54280031Sdim 55341825Sdim /// Determines if this type can be converted to \p To. 56280031Sdim /// 57280031Sdim /// \param To the requested destination type. 58280031Sdim /// 59280031Sdim /// \param Specificity value corresponding to the "specificity" of the 60321369Sdim /// conversion. 61280031Sdim bool isConvertibleTo(ArgKind To, unsigned *Specificity) const; 62280031Sdim 63280031Sdim bool operator<(const ArgKind &Other) const { 64280031Sdim if (K == AK_Matcher && Other.K == AK_Matcher) 65280031Sdim return MatcherKind < Other.MatcherKind; 66280031Sdim return K < Other.K; 67280031Sdim } 68280031Sdim 69341825Sdim /// String representation of the type. 70280031Sdim std::string asString() const; 71280031Sdim 72280031Sdimprivate: 73280031Sdim Kind K; 74280031Sdim ast_type_traits::ASTNodeKind MatcherKind; 75280031Sdim}; 76280031Sdim 77259701Sdimusing ast_matchers::internal::DynTypedMatcher; 78259701Sdim 79341825Sdim/// A variant matcher object. 80259701Sdim/// 81259701Sdim/// The purpose of this object is to abstract simple and polymorphic matchers 82259701Sdim/// into a single object type. 83259701Sdim/// Polymorphic matchers might be implemented as a list of all the possible 84259701Sdim/// overloads of the matcher. \c VariantMatcher knows how to select the 85259701Sdim/// appropriate overload when needed. 86259701Sdim/// To get a real matcher object out of a \c VariantMatcher you can do: 87259701Sdim/// - getSingleMatcher() which returns a matcher, only if it is not ambiguous 88259701Sdim/// to decide which matcher to return. Eg. it contains only a single 89259701Sdim/// matcher, or a polymorphic one with only one overload. 90259701Sdim/// - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if 91259701Sdim/// the underlying matcher(s) can unambiguously return a Matcher<T>. 92259701Sdimclass VariantMatcher { 93341825Sdim /// Methods that depend on T from hasTypedMatcher/getTypedMatcher. 94259701Sdim class MatcherOps { 95259701Sdim public: 96280031Sdim MatcherOps(ast_type_traits::ASTNodeKind NodeKind) : NodeKind(NodeKind) {} 97280031Sdim 98280031Sdim bool canConstructFrom(const DynTypedMatcher &Matcher, 99280031Sdim bool &IsExactMatch) const; 100280031Sdim 101341825Sdim /// Convert \p Matcher the destination type and return it as a new 102280031Sdim /// DynTypedMatcher. 103280031Sdim virtual DynTypedMatcher 104280031Sdim convertMatcher(const DynTypedMatcher &Matcher) const = 0; 105280031Sdim 106341825Sdim /// Constructs a variadic typed matcher from \p InnerMatchers. 107280031Sdim /// Will try to convert each inner matcher to the destination type and 108280031Sdim /// return llvm::None if it fails to do so. 109280031Sdim llvm::Optional<DynTypedMatcher> 110280031Sdim constructVariadicOperator(DynTypedMatcher::VariadicOperator Op, 111280031Sdim ArrayRef<VariantMatcher> InnerMatchers) const; 112280031Sdim 113280031Sdim protected: 114288943Sdim ~MatcherOps() = default; 115280031Sdim 116280031Sdim private: 117280031Sdim ast_type_traits::ASTNodeKind NodeKind; 118259701Sdim }; 119259701Sdim 120341825Sdim /// Payload interface to be specialized by each matcher type. 121259701Sdim /// 122259701Sdim /// It follows a similar interface as VariantMatcher itself. 123314564Sdim class Payload { 124259701Sdim public: 125314564Sdim virtual ~Payload(); 126259701Sdim virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0; 127259701Sdim virtual std::string getTypeAsString() const = 0; 128280031Sdim virtual llvm::Optional<DynTypedMatcher> 129280031Sdim getTypedMatcher(const MatcherOps &Ops) const = 0; 130280031Sdim virtual bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, 131280031Sdim unsigned *Specificity) const = 0; 132259701Sdim }; 133259701Sdim 134259701Sdimpublic: 135341825Sdim /// A null matcher. 136259701Sdim VariantMatcher(); 137259701Sdim 138341825Sdim /// Clones the provided matcher. 139259701Sdim static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher); 140259701Sdim 141341825Sdim /// Clones the provided matchers. 142259701Sdim /// 143259701Sdim /// They should be the result of a polymorphic matcher. 144276479Sdim static VariantMatcher 145276479Sdim PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers); 146259701Sdim 147341825Sdim /// Creates a 'variadic' operator matcher. 148259701Sdim /// 149259701Sdim /// It will bind to the appropriate type on getTypedMatcher<T>(). 150280031Sdim static VariantMatcher 151280031Sdim VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, 152280031Sdim std::vector<VariantMatcher> Args); 153259701Sdim 154341825Sdim /// Makes the matcher the "null" matcher. 155259701Sdim void reset(); 156259701Sdim 157341825Sdim /// Whether the matcher is null. 158259701Sdim bool isNull() const { return !Value; } 159259701Sdim 160341825Sdim /// Return a single matcher, if there is no ambiguity. 161259701Sdim /// 162259701Sdim /// \returns the matcher, if there is only one matcher. An empty Optional, if 163259701Sdim /// the underlying matcher is a polymorphic matcher with more than one 164259701Sdim /// representation. 165259701Sdim llvm::Optional<DynTypedMatcher> getSingleMatcher() const; 166259701Sdim 167341825Sdim /// Determines if the contained matcher can be converted to 168259701Sdim /// \c Matcher<T>. 169259701Sdim /// 170259701Sdim /// For the Single case, it returns true if it can be converted to 171259701Sdim /// \c Matcher<T>. 172259701Sdim /// For the Polymorphic case, it returns true if one, and only one, of the 173259701Sdim /// overloads can be converted to \c Matcher<T>. If there are more than one 174259701Sdim /// that can, the result would be ambiguous and false is returned. 175259701Sdim template <class T> 176259701Sdim bool hasTypedMatcher() const { 177280031Sdim if (!Value) return false; 178280031Sdim return Value->getTypedMatcher(TypedMatcherOps<T>()).hasValue(); 179259701Sdim } 180259701Sdim 181341825Sdim /// Determines if the contained matcher can be converted to \p Kind. 182280031Sdim /// 183280031Sdim /// \param Kind the requested destination type. 184280031Sdim /// 185280031Sdim /// \param Specificity value corresponding to the "specificity" of the 186321369Sdim /// conversion. 187280031Sdim bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, 188280031Sdim unsigned *Specificity) const { 189280031Sdim if (Value) 190280031Sdim return Value->isConvertibleTo(Kind, Specificity); 191280031Sdim return false; 192280031Sdim } 193280031Sdim 194341825Sdim /// Return this matcher as a \c Matcher<T>. 195259701Sdim /// 196259701Sdim /// Handles the different types (Single, Polymorphic) accordingly. 197259701Sdim /// Asserts that \c hasTypedMatcher<T>() is true. 198259701Sdim template <class T> 199259701Sdim ast_matchers::internal::Matcher<T> getTypedMatcher() const { 200280031Sdim assert(hasTypedMatcher<T>() && "hasTypedMatcher<T>() == false"); 201280031Sdim return Value->getTypedMatcher(TypedMatcherOps<T>()) 202280031Sdim ->template convertTo<T>(); 203259701Sdim } 204259701Sdim 205341825Sdim /// String representation of the type of the value. 206259701Sdim /// 207259701Sdim /// If the underlying matcher is a polymorphic one, the string will show all 208259701Sdim /// the types. 209259701Sdim std::string getTypeAsString() const; 210259701Sdim 211259701Sdimprivate: 212314564Sdim explicit VariantMatcher(std::shared_ptr<Payload> Value) 213314564Sdim : Value(std::move(Value)) {} 214259701Sdim 215280031Sdim template <typename T> struct TypedMatcherOps; 216280031Sdim 217259701Sdim class SinglePayload; 218259701Sdim class PolymorphicPayload; 219259701Sdim class VariadicOpPayload; 220259701Sdim 221314564Sdim std::shared_ptr<const Payload> Value; 222280031Sdim}; 223259701Sdim 224280031Sdimtemplate <typename T> 225280031Sdimstruct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps { 226280031Sdim TypedMatcherOps() 227280031Sdim : MatcherOps(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()) {} 228280031Sdim typedef ast_matchers::internal::Matcher<T> MatcherT; 229259701Sdim 230280031Sdim DynTypedMatcher 231280031Sdim convertMatcher(const DynTypedMatcher &Matcher) const override { 232280031Sdim return DynTypedMatcher(Matcher.convertTo<T>()); 233280031Sdim } 234259701Sdim}; 235259701Sdim 236341825Sdim/// Variant value class. 237259701Sdim/// 238259701Sdim/// Basically, a tagged union with value type semantics. 239259701Sdim/// It is used by the registry as the return value and argument type for the 240259701Sdim/// matcher factory methods. 241259701Sdim/// It can be constructed from any of the supported types. It supports 242259701Sdim/// copy/assignment. 243259701Sdim/// 244259701Sdim/// Supported types: 245321369Sdim/// - \c bool 246321369Sdim// - \c double 247259701Sdim/// - \c unsigned 248288943Sdim/// - \c llvm::StringRef 249259701Sdim/// - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>) 250259701Sdimclass VariantValue { 251259701Sdimpublic: 252259701Sdim VariantValue() : Type(VT_Nothing) {} 253259701Sdim 254259701Sdim VariantValue(const VariantValue &Other); 255259701Sdim ~VariantValue(); 256259701Sdim VariantValue &operator=(const VariantValue &Other); 257259701Sdim 258341825Sdim /// Specific constructors for each supported type. 259321369Sdim VariantValue(bool Boolean); 260321369Sdim VariantValue(double Double); 261259701Sdim VariantValue(unsigned Unsigned); 262288943Sdim VariantValue(StringRef String); 263259701Sdim VariantValue(const VariantMatcher &Matchers); 264259701Sdim 265341825Sdim /// Constructs an \c unsigned value (disambiguation from bool). 266321369Sdim VariantValue(int Signed) : VariantValue(static_cast<unsigned>(Signed)) {} 267321369Sdim 268341825Sdim /// Returns true iff this is not an empty value. 269288943Sdim explicit operator bool() const { return hasValue(); } 270276479Sdim bool hasValue() const { return Type != VT_Nothing; } 271276479Sdim 272341825Sdim /// Boolean value functions. 273321369Sdim bool isBoolean() const; 274321369Sdim bool getBoolean() const; 275321369Sdim void setBoolean(bool Boolean); 276321369Sdim 277341825Sdim /// Double value functions. 278321369Sdim bool isDouble() const; 279321369Sdim double getDouble() const; 280321369Sdim void setDouble(double Double); 281321369Sdim 282341825Sdim /// Unsigned value functions. 283259701Sdim bool isUnsigned() const; 284259701Sdim unsigned getUnsigned() const; 285259701Sdim void setUnsigned(unsigned Unsigned); 286259701Sdim 287341825Sdim /// String value functions. 288259701Sdim bool isString() const; 289259701Sdim const std::string &getString() const; 290288943Sdim void setString(StringRef String); 291259701Sdim 292341825Sdim /// Matcher value functions. 293259701Sdim bool isMatcher() const; 294259701Sdim const VariantMatcher &getMatcher() const; 295259701Sdim void setMatcher(const VariantMatcher &Matcher); 296259701Sdim 297341825Sdim /// Determines if the contained value can be converted to \p Kind. 298280031Sdim /// 299280031Sdim /// \param Kind the requested destination type. 300280031Sdim /// 301280031Sdim /// \param Specificity value corresponding to the "specificity" of the 302321369Sdim /// conversion. 303280031Sdim bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const; 304280031Sdim 305341825Sdim /// Determines if the contained value can be converted to any kind 306280031Sdim /// in \p Kinds. 307280031Sdim /// 308280031Sdim /// \param Kinds the requested destination types. 309280031Sdim /// 310280031Sdim /// \param Specificity value corresponding to the "specificity" of the 311321369Sdim /// conversion. It is the maximum specificity of all the possible 312280031Sdim /// conversions. 313280031Sdim bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const; 314280031Sdim 315341825Sdim /// String representation of the type of the value. 316259701Sdim std::string getTypeAsString() const; 317259701Sdim 318259701Sdimprivate: 319259701Sdim void reset(); 320259701Sdim 321341825Sdim /// All supported value types. 322259701Sdim enum ValueType { 323259701Sdim VT_Nothing, 324321369Sdim VT_Boolean, 325321369Sdim VT_Double, 326259701Sdim VT_Unsigned, 327259701Sdim VT_String, 328259701Sdim VT_Matcher 329259701Sdim }; 330259701Sdim 331341825Sdim /// All supported value types. 332259701Sdim union AllValues { 333259701Sdim unsigned Unsigned; 334321369Sdim double Double; 335321369Sdim bool Boolean; 336259701Sdim std::string *String; 337259701Sdim VariantMatcher *Matcher; 338259701Sdim }; 339259701Sdim 340259701Sdim ValueType Type; 341259701Sdim AllValues Value; 342259701Sdim}; 343259701Sdim 344259701Sdim} // end namespace dynamic 345259701Sdim} // end namespace ast_matchers 346259701Sdim} // end namespace clang 347259701Sdim 348259701Sdim#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H 349