VariantValue.h revision 259701
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 17259701Sdim#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H 18259701Sdim#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H 19259701Sdim 20259701Sdim#include <vector> 21259701Sdim 22259701Sdim#include "clang/ASTMatchers/ASTMatchers.h" 23259701Sdim#include "clang/ASTMatchers/ASTMatchersInternal.h" 24259701Sdim#include "llvm/ADT/IntrusiveRefCntPtr.h" 25259701Sdim#include "llvm/ADT/Optional.h" 26259701Sdim#include "llvm/ADT/Twine.h" 27259701Sdim#include "llvm/Support/type_traits.h" 28259701Sdim 29259701Sdimnamespace clang { 30259701Sdimnamespace ast_matchers { 31259701Sdimnamespace dynamic { 32259701Sdim 33259701Sdimusing ast_matchers::internal::DynTypedMatcher; 34259701Sdim 35259701Sdim/// \brief A variant matcher object. 36259701Sdim/// 37259701Sdim/// The purpose of this object is to abstract simple and polymorphic matchers 38259701Sdim/// into a single object type. 39259701Sdim/// Polymorphic matchers might be implemented as a list of all the possible 40259701Sdim/// overloads of the matcher. \c VariantMatcher knows how to select the 41259701Sdim/// appropriate overload when needed. 42259701Sdim/// To get a real matcher object out of a \c VariantMatcher you can do: 43259701Sdim/// - getSingleMatcher() which returns a matcher, only if it is not ambiguous 44259701Sdim/// to decide which matcher to return. Eg. it contains only a single 45259701Sdim/// matcher, or a polymorphic one with only one overload. 46259701Sdim/// - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if 47259701Sdim/// the underlying matcher(s) can unambiguously return a Matcher<T>. 48259701Sdimclass VariantMatcher { 49259701Sdim /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher. 50259701Sdim class MatcherOps { 51259701Sdim public: 52259701Sdim virtual ~MatcherOps(); 53259701Sdim virtual bool canConstructFrom(const DynTypedMatcher &Matcher) const = 0; 54259701Sdim virtual void constructFrom(const DynTypedMatcher &Matcher) = 0; 55259701Sdim virtual void constructVariadicOperator( 56259701Sdim ast_matchers::internal::VariadicOperatorFunction Func, 57259701Sdim ArrayRef<VariantMatcher> InnerMatchers) = 0; 58259701Sdim }; 59259701Sdim 60259701Sdim /// \brief Payload interface to be specialized by each matcher type. 61259701Sdim /// 62259701Sdim /// It follows a similar interface as VariantMatcher itself. 63259701Sdim class Payload : public RefCountedBaseVPTR { 64259701Sdim public: 65259701Sdim virtual ~Payload(); 66259701Sdim virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0; 67259701Sdim virtual std::string getTypeAsString() const = 0; 68259701Sdim virtual void makeTypedMatcher(MatcherOps &Ops) const = 0; 69259701Sdim }; 70259701Sdim 71259701Sdimpublic: 72259701Sdim /// \brief A null matcher. 73259701Sdim VariantMatcher(); 74259701Sdim 75259701Sdim /// \brief Clones the provided matcher. 76259701Sdim static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher); 77259701Sdim 78259701Sdim /// \brief Clones the provided matchers. 79259701Sdim /// 80259701Sdim /// They should be the result of a polymorphic matcher. 81259701Sdim static VariantMatcher PolymorphicMatcher(ArrayRef<DynTypedMatcher> Matchers); 82259701Sdim 83259701Sdim /// \brief Creates a 'variadic' operator matcher. 84259701Sdim /// 85259701Sdim /// It will bind to the appropriate type on getTypedMatcher<T>(). 86259701Sdim static VariantMatcher VariadicOperatorMatcher( 87259701Sdim ast_matchers::internal::VariadicOperatorFunction Func, 88259701Sdim ArrayRef<VariantMatcher> Args); 89259701Sdim 90259701Sdim /// \brief Makes the matcher the "null" matcher. 91259701Sdim void reset(); 92259701Sdim 93259701Sdim /// \brief Whether the matcher is null. 94259701Sdim bool isNull() const { return !Value; } 95259701Sdim 96259701Sdim /// \brief Return a single matcher, if there is no ambiguity. 97259701Sdim /// 98259701Sdim /// \returns the matcher, if there is only one matcher. An empty Optional, if 99259701Sdim /// the underlying matcher is a polymorphic matcher with more than one 100259701Sdim /// representation. 101259701Sdim llvm::Optional<DynTypedMatcher> getSingleMatcher() const; 102259701Sdim 103259701Sdim /// \brief Determines if the contained matcher can be converted to 104259701Sdim /// \c Matcher<T>. 105259701Sdim /// 106259701Sdim /// For the Single case, it returns true if it can be converted to 107259701Sdim /// \c Matcher<T>. 108259701Sdim /// For the Polymorphic case, it returns true if one, and only one, of the 109259701Sdim /// overloads can be converted to \c Matcher<T>. If there are more than one 110259701Sdim /// that can, the result would be ambiguous and false is returned. 111259701Sdim template <class T> 112259701Sdim bool hasTypedMatcher() const { 113259701Sdim TypedMatcherOps<T> Ops; 114259701Sdim if (Value) Value->makeTypedMatcher(Ops); 115259701Sdim return Ops.hasMatcher(); 116259701Sdim } 117259701Sdim 118259701Sdim /// \brief Return this matcher as a \c Matcher<T>. 119259701Sdim /// 120259701Sdim /// Handles the different types (Single, Polymorphic) accordingly. 121259701Sdim /// Asserts that \c hasTypedMatcher<T>() is true. 122259701Sdim template <class T> 123259701Sdim ast_matchers::internal::Matcher<T> getTypedMatcher() const { 124259701Sdim TypedMatcherOps<T> Ops; 125259701Sdim Value->makeTypedMatcher(Ops); 126259701Sdim assert(Ops.hasMatcher() && "hasTypedMatcher<T>() == false"); 127259701Sdim return Ops.matcher(); 128259701Sdim } 129259701Sdim 130259701Sdim /// \brief String representation of the type of the value. 131259701Sdim /// 132259701Sdim /// If the underlying matcher is a polymorphic one, the string will show all 133259701Sdim /// the types. 134259701Sdim std::string getTypeAsString() const; 135259701Sdim 136259701Sdimprivate: 137259701Sdim explicit VariantMatcher(Payload *Value) : Value(Value) {} 138259701Sdim 139259701Sdim class SinglePayload; 140259701Sdim class PolymorphicPayload; 141259701Sdim class VariadicOpPayload; 142259701Sdim 143259701Sdim template <typename T> 144259701Sdim class TypedMatcherOps : public MatcherOps { 145259701Sdim public: 146259701Sdim typedef ast_matchers::internal::Matcher<T> MatcherT; 147259701Sdim 148259701Sdim virtual bool canConstructFrom(const DynTypedMatcher &Matcher) const { 149259701Sdim return Matcher.canConvertTo<T>(); 150259701Sdim } 151259701Sdim 152259701Sdim virtual void constructFrom(const DynTypedMatcher& Matcher) { 153259701Sdim Out.reset(new MatcherT(Matcher.convertTo<T>())); 154259701Sdim } 155259701Sdim 156259701Sdim virtual void constructVariadicOperator( 157259701Sdim ast_matchers::internal::VariadicOperatorFunction Func, 158259701Sdim ArrayRef<VariantMatcher> InnerMatchers) { 159259701Sdim const size_t NumArgs = InnerMatchers.size(); 160259701Sdim MatcherT **InnerArgs = new MatcherT *[NumArgs](); 161259701Sdim bool HasError = false; 162259701Sdim for (size_t i = 0; i != NumArgs; ++i) { 163259701Sdim // Abort if any of the inner matchers can't be converted to 164259701Sdim // Matcher<T>. 165259701Sdim if (!InnerMatchers[i].hasTypedMatcher<T>()) { 166259701Sdim HasError = true; 167259701Sdim break; 168259701Sdim } 169259701Sdim InnerArgs[i] = new MatcherT(InnerMatchers[i].getTypedMatcher<T>()); 170259701Sdim } 171259701Sdim if (!HasError) { 172259701Sdim Out.reset(new MatcherT( 173259701Sdim new ast_matchers::internal::VariadicOperatorMatcherInterface<T>( 174259701Sdim Func, ArrayRef<const MatcherT *>(InnerArgs, NumArgs)))); 175259701Sdim } 176259701Sdim for (size_t i = 0; i != NumArgs; ++i) { 177259701Sdim delete InnerArgs[i]; 178259701Sdim } 179259701Sdim delete[] InnerArgs; 180259701Sdim } 181259701Sdim 182259701Sdim bool hasMatcher() const { return Out.get() != NULL; } 183259701Sdim const MatcherT &matcher() const { return *Out; } 184259701Sdim 185259701Sdim private: 186259701Sdim OwningPtr<MatcherT> Out; 187259701Sdim }; 188259701Sdim 189259701Sdim IntrusiveRefCntPtr<const Payload> Value; 190259701Sdim}; 191259701Sdim 192259701Sdim/// \brief Variant value class. 193259701Sdim/// 194259701Sdim/// Basically, a tagged union with value type semantics. 195259701Sdim/// It is used by the registry as the return value and argument type for the 196259701Sdim/// matcher factory methods. 197259701Sdim/// It can be constructed from any of the supported types. It supports 198259701Sdim/// copy/assignment. 199259701Sdim/// 200259701Sdim/// Supported types: 201259701Sdim/// - \c unsigned 202259701Sdim/// - \c std::string 203259701Sdim/// - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>) 204259701Sdimclass VariantValue { 205259701Sdimpublic: 206259701Sdim VariantValue() : Type(VT_Nothing) {} 207259701Sdim 208259701Sdim VariantValue(const VariantValue &Other); 209259701Sdim ~VariantValue(); 210259701Sdim VariantValue &operator=(const VariantValue &Other); 211259701Sdim 212259701Sdim /// \brief Specific constructors for each supported type. 213259701Sdim VariantValue(unsigned Unsigned); 214259701Sdim VariantValue(const std::string &String); 215259701Sdim VariantValue(const VariantMatcher &Matchers); 216259701Sdim 217259701Sdim /// \brief Unsigned value functions. 218259701Sdim bool isUnsigned() const; 219259701Sdim unsigned getUnsigned() const; 220259701Sdim void setUnsigned(unsigned Unsigned); 221259701Sdim 222259701Sdim /// \brief String value functions. 223259701Sdim bool isString() const; 224259701Sdim const std::string &getString() const; 225259701Sdim void setString(const std::string &String); 226259701Sdim 227259701Sdim /// \brief Matcher value functions. 228259701Sdim bool isMatcher() const; 229259701Sdim const VariantMatcher &getMatcher() const; 230259701Sdim void setMatcher(const VariantMatcher &Matcher); 231259701Sdim 232259701Sdim /// \brief String representation of the type of the value. 233259701Sdim std::string getTypeAsString() const; 234259701Sdim 235259701Sdimprivate: 236259701Sdim void reset(); 237259701Sdim 238259701Sdim /// \brief All supported value types. 239259701Sdim enum ValueType { 240259701Sdim VT_Nothing, 241259701Sdim VT_Unsigned, 242259701Sdim VT_String, 243259701Sdim VT_Matcher 244259701Sdim }; 245259701Sdim 246259701Sdim /// \brief All supported value types. 247259701Sdim union AllValues { 248259701Sdim unsigned Unsigned; 249259701Sdim std::string *String; 250259701Sdim VariantMatcher *Matcher; 251259701Sdim }; 252259701Sdim 253259701Sdim ValueType Type; 254259701Sdim AllValues Value; 255259701Sdim}; 256259701Sdim 257259701Sdim} // end namespace dynamic 258259701Sdim} // end namespace ast_matchers 259259701Sdim} // end namespace clang 260259701Sdim 261259701Sdim#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H 262