VariantValue.h revision 288943
1259701Sdim//===--- VariantValue.h - Polymorphic value type -*- C++ -*-===/ 2259701Sdim// The LLVM Compiler Infrastructure 3259701Sdim// 4259701Sdim// This file is distributed under the University of Illinois Open Source 5259701Sdim// License. See LICENSE.TXT for details. 6259701Sdim// 7259701Sdim//===----------------------------------------------------------------------===// 8259701Sdim/// 9259701Sdim/// \file 10259701Sdim/// \brief Polymorphic value type. 11259701Sdim/// 12259701Sdim/// Supports all the types required for dynamic Matcher construction. 13259701Sdim/// Used by the registry to construct matchers in a generic way. 14259701Sdim/// 15259701Sdim//===----------------------------------------------------------------------===// 16259701Sdim 17280031Sdim#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H 18280031Sdim#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H 19259701Sdim 20259701Sdim#include "clang/ASTMatchers/ASTMatchers.h" 21259701Sdim#include "clang/ASTMatchers/ASTMatchersInternal.h" 22259701Sdim#include "llvm/ADT/IntrusiveRefCntPtr.h" 23259701Sdim#include "llvm/ADT/Optional.h" 24259701Sdim#include "llvm/ADT/Twine.h" 25276479Sdim#include <memory> 26276479Sdim#include <vector> 27259701Sdim 28259701Sdimnamespace clang { 29259701Sdimnamespace ast_matchers { 30259701Sdimnamespace dynamic { 31259701Sdim 32280031Sdim/// \brief Kind identifier. 33280031Sdim/// 34280031Sdim/// It supports all types that VariantValue can contain. 35280031Sdimclass ArgKind { 36280031Sdim public: 37280031Sdim enum Kind { 38280031Sdim AK_Matcher, 39280031Sdim AK_Unsigned, 40280031Sdim AK_String 41280031Sdim }; 42280031Sdim /// \brief Constructor for non-matcher types. 43280031Sdim ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); } 44280031Sdim 45280031Sdim /// \brief 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 55280031Sdim /// \brief 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 60280031Sdim /// convertion. 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 69280031Sdim /// \brief 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 79259701Sdim/// \brief 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 { 93259701Sdim /// \brief 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 101280031Sdim /// \brief 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 106280031Sdim /// \brief 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 120259701Sdim /// \brief Payload interface to be specialized by each matcher type. 121259701Sdim /// 122259701Sdim /// It follows a similar interface as VariantMatcher itself. 123259701Sdim class Payload : public RefCountedBaseVPTR { 124259701Sdim public: 125288943Sdim ~Payload() override; 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: 135259701Sdim /// \brief A null matcher. 136259701Sdim VariantMatcher(); 137259701Sdim 138259701Sdim /// \brief Clones the provided matcher. 139259701Sdim static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher); 140259701Sdim 141259701Sdim /// \brief 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 147259701Sdim /// \brief 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 154259701Sdim /// \brief Makes the matcher the "null" matcher. 155259701Sdim void reset(); 156259701Sdim 157259701Sdim /// \brief Whether the matcher is null. 158259701Sdim bool isNull() const { return !Value; } 159259701Sdim 160259701Sdim /// \brief 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 167259701Sdim /// \brief 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 181280031Sdim /// \brief 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 186280031Sdim /// convertion. 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 194259701Sdim /// \brief 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 205259701Sdim /// \brief 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: 212259701Sdim explicit VariantMatcher(Payload *Value) : Value(Value) {} 213259701Sdim 214280031Sdim template <typename T> struct TypedMatcherOps; 215280031Sdim 216259701Sdim class SinglePayload; 217259701Sdim class PolymorphicPayload; 218259701Sdim class VariadicOpPayload; 219259701Sdim 220280031Sdim IntrusiveRefCntPtr<const Payload> Value; 221280031Sdim}; 222259701Sdim 223280031Sdimtemplate <typename T> 224280031Sdimstruct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps { 225280031Sdim TypedMatcherOps() 226280031Sdim : MatcherOps(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()) {} 227280031Sdim typedef ast_matchers::internal::Matcher<T> MatcherT; 228259701Sdim 229280031Sdim DynTypedMatcher 230280031Sdim convertMatcher(const DynTypedMatcher &Matcher) const override { 231280031Sdim return DynTypedMatcher(Matcher.convertTo<T>()); 232280031Sdim } 233259701Sdim}; 234259701Sdim 235259701Sdim/// \brief Variant value class. 236259701Sdim/// 237259701Sdim/// Basically, a tagged union with value type semantics. 238259701Sdim/// It is used by the registry as the return value and argument type for the 239259701Sdim/// matcher factory methods. 240259701Sdim/// It can be constructed from any of the supported types. It supports 241259701Sdim/// copy/assignment. 242259701Sdim/// 243259701Sdim/// Supported types: 244259701Sdim/// - \c unsigned 245288943Sdim/// - \c llvm::StringRef 246259701Sdim/// - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>) 247259701Sdimclass VariantValue { 248259701Sdimpublic: 249259701Sdim VariantValue() : Type(VT_Nothing) {} 250259701Sdim 251259701Sdim VariantValue(const VariantValue &Other); 252259701Sdim ~VariantValue(); 253259701Sdim VariantValue &operator=(const VariantValue &Other); 254259701Sdim 255259701Sdim /// \brief Specific constructors for each supported type. 256259701Sdim VariantValue(unsigned Unsigned); 257288943Sdim VariantValue(StringRef String); 258259701Sdim VariantValue(const VariantMatcher &Matchers); 259259701Sdim 260276479Sdim /// \brief Returns true iff this is not an empty value. 261288943Sdim explicit operator bool() const { return hasValue(); } 262276479Sdim bool hasValue() const { return Type != VT_Nothing; } 263276479Sdim 264259701Sdim /// \brief Unsigned value functions. 265259701Sdim bool isUnsigned() const; 266259701Sdim unsigned getUnsigned() const; 267259701Sdim void setUnsigned(unsigned Unsigned); 268259701Sdim 269259701Sdim /// \brief String value functions. 270259701Sdim bool isString() const; 271259701Sdim const std::string &getString() const; 272288943Sdim void setString(StringRef String); 273259701Sdim 274259701Sdim /// \brief Matcher value functions. 275259701Sdim bool isMatcher() const; 276259701Sdim const VariantMatcher &getMatcher() const; 277259701Sdim void setMatcher(const VariantMatcher &Matcher); 278259701Sdim 279280031Sdim /// \brief Determines if the contained value can be converted to \p Kind. 280280031Sdim /// 281280031Sdim /// \param Kind the requested destination type. 282280031Sdim /// 283280031Sdim /// \param Specificity value corresponding to the "specificity" of the 284280031Sdim /// convertion. 285280031Sdim bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const; 286280031Sdim 287280031Sdim /// \brief Determines if the contained value can be converted to any kind 288280031Sdim /// in \p Kinds. 289280031Sdim /// 290280031Sdim /// \param Kinds the requested destination types. 291280031Sdim /// 292280031Sdim /// \param Specificity value corresponding to the "specificity" of the 293280031Sdim /// convertion. It is the maximum specificity of all the possible 294280031Sdim /// conversions. 295280031Sdim bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const; 296280031Sdim 297259701Sdim /// \brief String representation of the type of the value. 298259701Sdim std::string getTypeAsString() const; 299259701Sdim 300259701Sdimprivate: 301259701Sdim void reset(); 302259701Sdim 303259701Sdim /// \brief All supported value types. 304259701Sdim enum ValueType { 305259701Sdim VT_Nothing, 306259701Sdim VT_Unsigned, 307259701Sdim VT_String, 308259701Sdim VT_Matcher 309259701Sdim }; 310259701Sdim 311259701Sdim /// \brief All supported value types. 312259701Sdim union AllValues { 313259701Sdim unsigned Unsigned; 314259701Sdim std::string *String; 315259701Sdim VariantMatcher *Matcher; 316259701Sdim }; 317259701Sdim 318259701Sdim ValueType Type; 319259701Sdim AllValues Value; 320259701Sdim}; 321259701Sdim 322259701Sdim} // end namespace dynamic 323259701Sdim} // end namespace ast_matchers 324259701Sdim} // end namespace clang 325259701Sdim 326259701Sdim#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H 327