VariantValue.h revision 314564
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" 24276479Sdim#include <memory> 25276479Sdim#include <vector> 26259701Sdim 27259701Sdimnamespace clang { 28259701Sdimnamespace ast_matchers { 29259701Sdimnamespace dynamic { 30259701Sdim 31280031Sdim/// \brief Kind identifier. 32280031Sdim/// 33280031Sdim/// It supports all types that VariantValue can contain. 34280031Sdimclass ArgKind { 35280031Sdim public: 36280031Sdim enum Kind { 37280031Sdim AK_Matcher, 38280031Sdim AK_Unsigned, 39280031Sdim AK_String 40280031Sdim }; 41280031Sdim /// \brief Constructor for non-matcher types. 42280031Sdim ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); } 43280031Sdim 44280031Sdim /// \brief Constructor for matcher types. 45280031Sdim ArgKind(ast_type_traits::ASTNodeKind MatcherKind) 46280031Sdim : K(AK_Matcher), MatcherKind(MatcherKind) {} 47280031Sdim 48280031Sdim Kind getArgKind() const { return K; } 49280031Sdim ast_type_traits::ASTNodeKind getMatcherKind() const { 50280031Sdim assert(K == AK_Matcher); 51280031Sdim return MatcherKind; 52280031Sdim } 53280031Sdim 54280031Sdim /// \brief Determines if this type can be converted to \p To. 55280031Sdim /// 56280031Sdim /// \param To the requested destination type. 57280031Sdim /// 58280031Sdim /// \param Specificity value corresponding to the "specificity" of the 59280031Sdim /// convertion. 60280031Sdim bool isConvertibleTo(ArgKind To, unsigned *Specificity) const; 61280031Sdim 62280031Sdim bool operator<(const ArgKind &Other) const { 63280031Sdim if (K == AK_Matcher && Other.K == AK_Matcher) 64280031Sdim return MatcherKind < Other.MatcherKind; 65280031Sdim return K < Other.K; 66280031Sdim } 67280031Sdim 68280031Sdim /// \brief String representation of the type. 69280031Sdim std::string asString() const; 70280031Sdim 71280031Sdimprivate: 72280031Sdim Kind K; 73280031Sdim ast_type_traits::ASTNodeKind MatcherKind; 74280031Sdim}; 75280031Sdim 76259701Sdimusing ast_matchers::internal::DynTypedMatcher; 77259701Sdim 78259701Sdim/// \brief A variant matcher object. 79259701Sdim/// 80259701Sdim/// The purpose of this object is to abstract simple and polymorphic matchers 81259701Sdim/// into a single object type. 82259701Sdim/// Polymorphic matchers might be implemented as a list of all the possible 83259701Sdim/// overloads of the matcher. \c VariantMatcher knows how to select the 84259701Sdim/// appropriate overload when needed. 85259701Sdim/// To get a real matcher object out of a \c VariantMatcher you can do: 86259701Sdim/// - getSingleMatcher() which returns a matcher, only if it is not ambiguous 87259701Sdim/// to decide which matcher to return. Eg. it contains only a single 88259701Sdim/// matcher, or a polymorphic one with only one overload. 89259701Sdim/// - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if 90259701Sdim/// the underlying matcher(s) can unambiguously return a Matcher<T>. 91259701Sdimclass VariantMatcher { 92259701Sdim /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher. 93259701Sdim class MatcherOps { 94259701Sdim public: 95280031Sdim MatcherOps(ast_type_traits::ASTNodeKind NodeKind) : NodeKind(NodeKind) {} 96280031Sdim 97280031Sdim bool canConstructFrom(const DynTypedMatcher &Matcher, 98280031Sdim bool &IsExactMatch) const; 99280031Sdim 100280031Sdim /// \brief Convert \p Matcher the destination type and return it as a new 101280031Sdim /// DynTypedMatcher. 102280031Sdim virtual DynTypedMatcher 103280031Sdim convertMatcher(const DynTypedMatcher &Matcher) const = 0; 104280031Sdim 105280031Sdim /// \brief Constructs a variadic typed matcher from \p InnerMatchers. 106280031Sdim /// Will try to convert each inner matcher to the destination type and 107280031Sdim /// return llvm::None if it fails to do so. 108280031Sdim llvm::Optional<DynTypedMatcher> 109280031Sdim constructVariadicOperator(DynTypedMatcher::VariadicOperator Op, 110280031Sdim ArrayRef<VariantMatcher> InnerMatchers) const; 111280031Sdim 112280031Sdim protected: 113288943Sdim ~MatcherOps() = default; 114280031Sdim 115280031Sdim private: 116280031Sdim ast_type_traits::ASTNodeKind NodeKind; 117259701Sdim }; 118259701Sdim 119259701Sdim /// \brief Payload interface to be specialized by each matcher type. 120259701Sdim /// 121259701Sdim /// It follows a similar interface as VariantMatcher itself. 122314564Sdim class Payload { 123259701Sdim public: 124314564Sdim virtual ~Payload(); 125259701Sdim virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0; 126259701Sdim virtual std::string getTypeAsString() const = 0; 127280031Sdim virtual llvm::Optional<DynTypedMatcher> 128280031Sdim getTypedMatcher(const MatcherOps &Ops) const = 0; 129280031Sdim virtual bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, 130280031Sdim unsigned *Specificity) const = 0; 131259701Sdim }; 132259701Sdim 133259701Sdimpublic: 134259701Sdim /// \brief A null matcher. 135259701Sdim VariantMatcher(); 136259701Sdim 137259701Sdim /// \brief Clones the provided matcher. 138259701Sdim static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher); 139259701Sdim 140259701Sdim /// \brief Clones the provided matchers. 141259701Sdim /// 142259701Sdim /// They should be the result of a polymorphic matcher. 143276479Sdim static VariantMatcher 144276479Sdim PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers); 145259701Sdim 146259701Sdim /// \brief Creates a 'variadic' operator matcher. 147259701Sdim /// 148259701Sdim /// It will bind to the appropriate type on getTypedMatcher<T>(). 149280031Sdim static VariantMatcher 150280031Sdim VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, 151280031Sdim std::vector<VariantMatcher> Args); 152259701Sdim 153259701Sdim /// \brief Makes the matcher the "null" matcher. 154259701Sdim void reset(); 155259701Sdim 156259701Sdim /// \brief Whether the matcher is null. 157259701Sdim bool isNull() const { return !Value; } 158259701Sdim 159259701Sdim /// \brief Return a single matcher, if there is no ambiguity. 160259701Sdim /// 161259701Sdim /// \returns the matcher, if there is only one matcher. An empty Optional, if 162259701Sdim /// the underlying matcher is a polymorphic matcher with more than one 163259701Sdim /// representation. 164259701Sdim llvm::Optional<DynTypedMatcher> getSingleMatcher() const; 165259701Sdim 166259701Sdim /// \brief Determines if the contained matcher can be converted to 167259701Sdim /// \c Matcher<T>. 168259701Sdim /// 169259701Sdim /// For the Single case, it returns true if it can be converted to 170259701Sdim /// \c Matcher<T>. 171259701Sdim /// For the Polymorphic case, it returns true if one, and only one, of the 172259701Sdim /// overloads can be converted to \c Matcher<T>. If there are more than one 173259701Sdim /// that can, the result would be ambiguous and false is returned. 174259701Sdim template <class T> 175259701Sdim bool hasTypedMatcher() const { 176280031Sdim if (!Value) return false; 177280031Sdim return Value->getTypedMatcher(TypedMatcherOps<T>()).hasValue(); 178259701Sdim } 179259701Sdim 180280031Sdim /// \brief Determines if the contained matcher can be converted to \p Kind. 181280031Sdim /// 182280031Sdim /// \param Kind the requested destination type. 183280031Sdim /// 184280031Sdim /// \param Specificity value corresponding to the "specificity" of the 185280031Sdim /// convertion. 186280031Sdim bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, 187280031Sdim unsigned *Specificity) const { 188280031Sdim if (Value) 189280031Sdim return Value->isConvertibleTo(Kind, Specificity); 190280031Sdim return false; 191280031Sdim } 192280031Sdim 193259701Sdim /// \brief Return this matcher as a \c Matcher<T>. 194259701Sdim /// 195259701Sdim /// Handles the different types (Single, Polymorphic) accordingly. 196259701Sdim /// Asserts that \c hasTypedMatcher<T>() is true. 197259701Sdim template <class T> 198259701Sdim ast_matchers::internal::Matcher<T> getTypedMatcher() const { 199280031Sdim assert(hasTypedMatcher<T>() && "hasTypedMatcher<T>() == false"); 200280031Sdim return Value->getTypedMatcher(TypedMatcherOps<T>()) 201280031Sdim ->template convertTo<T>(); 202259701Sdim } 203259701Sdim 204259701Sdim /// \brief String representation of the type of the value. 205259701Sdim /// 206259701Sdim /// If the underlying matcher is a polymorphic one, the string will show all 207259701Sdim /// the types. 208259701Sdim std::string getTypeAsString() const; 209259701Sdim 210259701Sdimprivate: 211314564Sdim explicit VariantMatcher(std::shared_ptr<Payload> Value) 212314564Sdim : Value(std::move(Value)) {} 213259701Sdim 214280031Sdim template <typename T> struct TypedMatcherOps; 215280031Sdim 216259701Sdim class SinglePayload; 217259701Sdim class PolymorphicPayload; 218259701Sdim class VariadicOpPayload; 219259701Sdim 220314564Sdim std::shared_ptr<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