1 //===--- VariantValue.h - Polymorphic value type -*- C++ -*-===/
2 // The LLVM Compiler Infrastructure
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
7 //===----------------------------------------------------------------------===//
10 /// \brief Polymorphic value type.
12 /// Supports all the types required for dynamic Matcher construction.
13 /// Used by the registry to construct matchers in a generic way.
15 //===----------------------------------------------------------------------===//
17 #ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
18 #define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
22 #include "clang/ASTMatchers/ASTMatchers.h"
23 #include "clang/ASTMatchers/ASTMatchersInternal.h"
24 #include "llvm/ADT/IntrusiveRefCntPtr.h"
25 #include "llvm/ADT/Optional.h"
26 #include "llvm/ADT/Twine.h"
27 #include "llvm/Support/type_traits.h"
30 namespace ast_matchers {
33 using ast_matchers::internal::DynTypedMatcher;
35 /// \brief A variant matcher object.
37 /// The purpose of this object is to abstract simple and polymorphic matchers
38 /// into a single object type.
39 /// Polymorphic matchers might be implemented as a list of all the possible
40 /// overloads of the matcher. \c VariantMatcher knows how to select the
41 /// appropriate overload when needed.
42 /// To get a real matcher object out of a \c VariantMatcher you can do:
43 /// - getSingleMatcher() which returns a matcher, only if it is not ambiguous
44 /// to decide which matcher to return. Eg. it contains only a single
45 /// matcher, or a polymorphic one with only one overload.
46 /// - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if
47 /// the underlying matcher(s) can unambiguously return a Matcher<T>.
48 class VariantMatcher {
49 /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher.
52 virtual ~MatcherOps();
53 virtual bool canConstructFrom(const DynTypedMatcher &Matcher) const = 0;
54 virtual void constructFrom(const DynTypedMatcher &Matcher) = 0;
55 virtual void constructVariadicOperator(
56 ast_matchers::internal::VariadicOperatorFunction Func,
57 ArrayRef<VariantMatcher> InnerMatchers) = 0;
60 /// \brief Payload interface to be specialized by each matcher type.
62 /// It follows a similar interface as VariantMatcher itself.
63 class Payload : public RefCountedBaseVPTR {
66 virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
67 virtual std::string getTypeAsString() const = 0;
68 virtual void makeTypedMatcher(MatcherOps &Ops) const = 0;
72 /// \brief A null matcher.
75 /// \brief Clones the provided matcher.
76 static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher);
78 /// \brief Clones the provided matchers.
80 /// They should be the result of a polymorphic matcher.
81 static VariantMatcher PolymorphicMatcher(ArrayRef<DynTypedMatcher> Matchers);
83 /// \brief Creates a 'variadic' operator matcher.
85 /// It will bind to the appropriate type on getTypedMatcher<T>().
86 static VariantMatcher VariadicOperatorMatcher(
87 ast_matchers::internal::VariadicOperatorFunction Func,
88 ArrayRef<VariantMatcher> Args);
90 /// \brief Makes the matcher the "null" matcher.
93 /// \brief Whether the matcher is null.
94 bool isNull() const { return !Value; }
96 /// \brief Return a single matcher, if there is no ambiguity.
98 /// \returns the matcher, if there is only one matcher. An empty Optional, if
99 /// the underlying matcher is a polymorphic matcher with more than one
101 llvm::Optional<DynTypedMatcher> getSingleMatcher() const;
103 /// \brief Determines if the contained matcher can be converted to
106 /// For the Single case, it returns true if it can be converted to
108 /// For the Polymorphic case, it returns true if one, and only one, of the
109 /// overloads can be converted to \c Matcher<T>. If there are more than one
110 /// that can, the result would be ambiguous and false is returned.
112 bool hasTypedMatcher() const {
113 TypedMatcherOps<T> Ops;
114 if (Value) Value->makeTypedMatcher(Ops);
115 return Ops.hasMatcher();
118 /// \brief Return this matcher as a \c Matcher<T>.
120 /// Handles the different types (Single, Polymorphic) accordingly.
121 /// Asserts that \c hasTypedMatcher<T>() is true.
123 ast_matchers::internal::Matcher<T> getTypedMatcher() const {
124 TypedMatcherOps<T> Ops;
125 Value->makeTypedMatcher(Ops);
126 assert(Ops.hasMatcher() && "hasTypedMatcher<T>() == false");
127 return Ops.matcher();
130 /// \brief String representation of the type of the value.
132 /// If the underlying matcher is a polymorphic one, the string will show all
134 std::string getTypeAsString() const;
137 explicit VariantMatcher(Payload *Value) : Value(Value) {}
140 class PolymorphicPayload;
141 class VariadicOpPayload;
143 template <typename T>
144 class TypedMatcherOps : public MatcherOps {
146 typedef ast_matchers::internal::Matcher<T> MatcherT;
148 virtual bool canConstructFrom(const DynTypedMatcher &Matcher) const {
149 return Matcher.canConvertTo<T>();
152 virtual void constructFrom(const DynTypedMatcher& Matcher) {
153 Out.reset(new MatcherT(Matcher.convertTo<T>()));
156 virtual void constructVariadicOperator(
157 ast_matchers::internal::VariadicOperatorFunction Func,
158 ArrayRef<VariantMatcher> InnerMatchers) {
159 const size_t NumArgs = InnerMatchers.size();
160 MatcherT **InnerArgs = new MatcherT *[NumArgs]();
161 bool HasError = false;
162 for (size_t i = 0; i != NumArgs; ++i) {
163 // Abort if any of the inner matchers can't be converted to
165 if (!InnerMatchers[i].hasTypedMatcher<T>()) {
169 InnerArgs[i] = new MatcherT(InnerMatchers[i].getTypedMatcher<T>());
172 Out.reset(new MatcherT(
173 new ast_matchers::internal::VariadicOperatorMatcherInterface<T>(
174 Func, ArrayRef<const MatcherT *>(InnerArgs, NumArgs))));
176 for (size_t i = 0; i != NumArgs; ++i) {
182 bool hasMatcher() const { return Out.get() != NULL; }
183 const MatcherT &matcher() const { return *Out; }
186 OwningPtr<MatcherT> Out;
189 IntrusiveRefCntPtr<const Payload> Value;
192 /// \brief Variant value class.
194 /// Basically, a tagged union with value type semantics.
195 /// It is used by the registry as the return value and argument type for the
196 /// matcher factory methods.
197 /// It can be constructed from any of the supported types. It supports
203 /// - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
206 VariantValue() : Type(VT_Nothing) {}
208 VariantValue(const VariantValue &Other);
210 VariantValue &operator=(const VariantValue &Other);
212 /// \brief Specific constructors for each supported type.
213 VariantValue(unsigned Unsigned);
214 VariantValue(const std::string &String);
215 VariantValue(const VariantMatcher &Matchers);
217 /// \brief Unsigned value functions.
218 bool isUnsigned() const;
219 unsigned getUnsigned() const;
220 void setUnsigned(unsigned Unsigned);
222 /// \brief String value functions.
223 bool isString() const;
224 const std::string &getString() const;
225 void setString(const std::string &String);
227 /// \brief Matcher value functions.
228 bool isMatcher() const;
229 const VariantMatcher &getMatcher() const;
230 void setMatcher(const VariantMatcher &Matcher);
232 /// \brief String representation of the type of the value.
233 std::string getTypeAsString() const;
238 /// \brief All supported value types.
246 /// \brief All supported value types.
250 VariantMatcher *Matcher;
257 } // end namespace dynamic
258 } // end namespace ast_matchers
259 } // end namespace clang
261 #endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H