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
20 #include "clang/ASTMatchers/ASTMatchers.h"
21 #include "clang/ASTMatchers/ASTMatchersInternal.h"
22 #include "llvm/ADT/IntrusiveRefCntPtr.h"
23 #include "llvm/ADT/Optional.h"
24 #include "llvm/ADT/Twine.h"
29 namespace ast_matchers {
32 /// \brief Kind identifier.
34 /// It supports all types that VariantValue can contain.
42 /// \brief Constructor for non-matcher types.
43 ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); }
45 /// \brief Constructor for matcher types.
46 ArgKind(ast_type_traits::ASTNodeKind MatcherKind)
47 : K(AK_Matcher), MatcherKind(MatcherKind) {}
49 Kind getArgKind() const { return K; }
50 ast_type_traits::ASTNodeKind getMatcherKind() const {
51 assert(K == AK_Matcher);
55 /// \brief Determines if this type can be converted to \p To.
57 /// \param To the requested destination type.
59 /// \param Specificity value corresponding to the "specificity" of the
61 bool isConvertibleTo(ArgKind To, unsigned *Specificity) const;
63 bool operator<(const ArgKind &Other) const {
64 if (K == AK_Matcher && Other.K == AK_Matcher)
65 return MatcherKind < Other.MatcherKind;
69 /// \brief String representation of the type.
70 std::string asString() const;
74 ast_type_traits::ASTNodeKind MatcherKind;
77 using ast_matchers::internal::DynTypedMatcher;
79 /// \brief A variant matcher object.
81 /// The purpose of this object is to abstract simple and polymorphic matchers
82 /// into a single object type.
83 /// Polymorphic matchers might be implemented as a list of all the possible
84 /// overloads of the matcher. \c VariantMatcher knows how to select the
85 /// appropriate overload when needed.
86 /// To get a real matcher object out of a \c VariantMatcher you can do:
87 /// - getSingleMatcher() which returns a matcher, only if it is not ambiguous
88 /// to decide which matcher to return. Eg. it contains only a single
89 /// matcher, or a polymorphic one with only one overload.
90 /// - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if
91 /// the underlying matcher(s) can unambiguously return a Matcher<T>.
92 class VariantMatcher {
93 /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher.
96 virtual ~MatcherOps();
97 virtual bool canConstructFrom(const DynTypedMatcher &Matcher,
98 bool &IsExactMatch) const = 0;
99 virtual void constructFrom(const DynTypedMatcher &Matcher) = 0;
100 virtual void constructVariadicOperator(
101 ast_matchers::internal::VariadicOperatorFunction Func,
102 ArrayRef<VariantMatcher> InnerMatchers) = 0;
105 /// \brief Payload interface to be specialized by each matcher type.
107 /// It follows a similar interface as VariantMatcher itself.
108 class Payload : public RefCountedBaseVPTR {
111 virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
112 virtual std::string getTypeAsString() const = 0;
113 virtual void makeTypedMatcher(MatcherOps &Ops) const = 0;
114 virtual bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
115 unsigned *Specificity) const = 0;
119 /// \brief A null matcher.
122 /// \brief Clones the provided matcher.
123 static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher);
125 /// \brief Clones the provided matchers.
127 /// They should be the result of a polymorphic matcher.
128 static VariantMatcher
129 PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers);
131 /// \brief Creates a 'variadic' operator matcher.
133 /// It will bind to the appropriate type on getTypedMatcher<T>().
134 static VariantMatcher VariadicOperatorMatcher(
135 ast_matchers::internal::VariadicOperatorFunction Func,
136 std::vector<VariantMatcher> Args);
138 /// \brief Makes the matcher the "null" matcher.
141 /// \brief Whether the matcher is null.
142 bool isNull() const { return !Value; }
144 /// \brief Return a single matcher, if there is no ambiguity.
146 /// \returns the matcher, if there is only one matcher. An empty Optional, if
147 /// the underlying matcher is a polymorphic matcher with more than one
149 llvm::Optional<DynTypedMatcher> getSingleMatcher() const;
151 /// \brief Determines if the contained matcher can be converted to
154 /// For the Single case, it returns true if it can be converted to
156 /// For the Polymorphic case, it returns true if one, and only one, of the
157 /// overloads can be converted to \c Matcher<T>. If there are more than one
158 /// that can, the result would be ambiguous and false is returned.
160 bool hasTypedMatcher() const {
161 TypedMatcherOps<T> Ops;
162 if (Value) Value->makeTypedMatcher(Ops);
163 return Ops.hasMatcher();
166 /// \brief Determines if the contained matcher can be converted to \p Kind.
168 /// \param Kind the requested destination type.
170 /// \param Specificity value corresponding to the "specificity" of the
172 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
173 unsigned *Specificity) const {
175 return Value->isConvertibleTo(Kind, Specificity);
179 /// \brief Return this matcher as a \c Matcher<T>.
181 /// Handles the different types (Single, Polymorphic) accordingly.
182 /// Asserts that \c hasTypedMatcher<T>() is true.
184 ast_matchers::internal::Matcher<T> getTypedMatcher() const {
185 TypedMatcherOps<T> Ops;
186 Value->makeTypedMatcher(Ops);
187 assert(Ops.hasMatcher() && "hasTypedMatcher<T>() == false");
188 return Ops.matcher();
191 /// \brief String representation of the type of the value.
193 /// If the underlying matcher is a polymorphic one, the string will show all
195 std::string getTypeAsString() const;
198 explicit VariantMatcher(Payload *Value) : Value(Value) {}
201 class PolymorphicPayload;
202 class VariadicOpPayload;
204 template <typename T>
205 class TypedMatcherOps : public MatcherOps {
207 typedef ast_matchers::internal::Matcher<T> MatcherT;
209 virtual bool canConstructFrom(const DynTypedMatcher &Matcher,
210 bool &IsExactMatch) const {
211 IsExactMatch = Matcher.getSupportedKind().isSame(
212 ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
213 return Matcher.canConvertTo<T>();
216 virtual void constructFrom(const DynTypedMatcher& Matcher) {
217 Out.reset(new MatcherT(Matcher.convertTo<T>()));
220 virtual void constructVariadicOperator(
221 ast_matchers::internal::VariadicOperatorFunction Func,
222 ArrayRef<VariantMatcher> InnerMatchers) {
223 std::vector<DynTypedMatcher> DynMatchers;
224 for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
225 // Abort if any of the inner matchers can't be converted to
227 if (!InnerMatchers[i].hasTypedMatcher<T>()) {
230 DynMatchers.push_back(InnerMatchers[i].getTypedMatcher<T>());
232 Out.reset(new MatcherT(
233 new ast_matchers::internal::VariadicOperatorMatcherInterface<T>(
234 Func, DynMatchers)));
237 bool hasMatcher() const { return Out.get() != nullptr; }
238 const MatcherT &matcher() const { return *Out; }
241 std::unique_ptr<MatcherT> Out;
244 IntrusiveRefCntPtr<const Payload> Value;
247 /// \brief Variant value class.
249 /// Basically, a tagged union with value type semantics.
250 /// It is used by the registry as the return value and argument type for the
251 /// matcher factory methods.
252 /// It can be constructed from any of the supported types. It supports
258 /// - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
261 VariantValue() : Type(VT_Nothing) {}
263 VariantValue(const VariantValue &Other);
265 VariantValue &operator=(const VariantValue &Other);
267 /// \brief Specific constructors for each supported type.
268 VariantValue(unsigned Unsigned);
269 VariantValue(const std::string &String);
270 VariantValue(const VariantMatcher &Matchers);
272 /// \brief Returns true iff this is not an empty value.
273 LLVM_EXPLICIT operator bool() const { return hasValue(); }
274 bool hasValue() const { return Type != VT_Nothing; }
276 /// \brief Unsigned value functions.
277 bool isUnsigned() const;
278 unsigned getUnsigned() const;
279 void setUnsigned(unsigned Unsigned);
281 /// \brief String value functions.
282 bool isString() const;
283 const std::string &getString() const;
284 void setString(const std::string &String);
286 /// \brief Matcher value functions.
287 bool isMatcher() const;
288 const VariantMatcher &getMatcher() const;
289 void setMatcher(const VariantMatcher &Matcher);
291 /// \brief Determines if the contained value can be converted to \p Kind.
293 /// \param Kind the requested destination type.
295 /// \param Specificity value corresponding to the "specificity" of the
297 bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const;
299 /// \brief Determines if the contained value can be converted to any kind
302 /// \param Kinds the requested destination types.
304 /// \param Specificity value corresponding to the "specificity" of the
305 /// convertion. It is the maximum specificity of all the possible
307 bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const;
309 /// \brief String representation of the type of the value.
310 std::string getTypeAsString() const;
315 /// \brief All supported value types.
323 /// \brief All supported value types.
327 VariantMatcher *Matcher;
334 } // end namespace dynamic
335 } // end namespace ast_matchers
336 } // end namespace clang
338 #endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H