1 //===--- VariantValue.h - Polymorphic value type -*- C++ -*-===/
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //===----------------------------------------------------------------------===//
9 /// Polymorphic value type.
11 /// Supports all the types required for dynamic Matcher construction.
12 /// Used by the registry to construct matchers in a generic way.
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
17 #define LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
19 #include "clang/ASTMatchers/ASTMatchers.h"
20 #include "clang/ASTMatchers/ASTMatchersInternal.h"
21 #include "llvm/ADT/IntrusiveRefCntPtr.h"
22 #include "llvm/ADT/Optional.h"
27 namespace ast_matchers {
32 /// It supports all types that VariantValue can contain.
42 /// Constructor for non-matcher types.
43 ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); }
45 /// 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 /// 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 /// String representation of the type.
70 std::string asString() const;
74 ast_type_traits::ASTNodeKind MatcherKind;
77 using ast_matchers::internal::DynTypedMatcher;
79 /// 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 /// Methods that depend on T from hasTypedMatcher/getTypedMatcher.
96 MatcherOps(ast_type_traits::ASTNodeKind NodeKind) : NodeKind(NodeKind) {}
98 bool canConstructFrom(const DynTypedMatcher &Matcher,
99 bool &IsExactMatch) const;
101 /// Convert \p Matcher the destination type and return it as a new
103 virtual DynTypedMatcher
104 convertMatcher(const DynTypedMatcher &Matcher) const = 0;
106 /// Constructs a variadic typed matcher from \p InnerMatchers.
107 /// Will try to convert each inner matcher to the destination type and
108 /// return llvm::None if it fails to do so.
109 llvm::Optional<DynTypedMatcher>
110 constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,
111 ArrayRef<VariantMatcher> InnerMatchers) const;
114 ~MatcherOps() = default;
117 ast_type_traits::ASTNodeKind NodeKind;
120 /// Payload interface to be specialized by each matcher type.
122 /// It follows a similar interface as VariantMatcher itself.
126 virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
127 virtual std::string getTypeAsString() const = 0;
128 virtual llvm::Optional<DynTypedMatcher>
129 getTypedMatcher(const MatcherOps &Ops) const = 0;
130 virtual bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
131 unsigned *Specificity) const = 0;
138 /// Clones the provided matcher.
139 static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher);
141 /// Clones the provided matchers.
143 /// They should be the result of a polymorphic matcher.
144 static VariantMatcher
145 PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers);
147 /// Creates a 'variadic' operator matcher.
149 /// It will bind to the appropriate type on getTypedMatcher<T>().
150 static VariantMatcher
151 VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,
152 std::vector<VariantMatcher> Args);
154 /// Makes the matcher the "null" matcher.
157 /// Whether the matcher is null.
158 bool isNull() const { return !Value; }
160 /// Return a single matcher, if there is no ambiguity.
162 /// \returns the matcher, if there is only one matcher. An empty Optional, if
163 /// the underlying matcher is a polymorphic matcher with more than one
165 llvm::Optional<DynTypedMatcher> getSingleMatcher() const;
167 /// Determines if the contained matcher can be converted to
170 /// For the Single case, it returns true if it can be converted to
172 /// For the Polymorphic case, it returns true if one, and only one, of the
173 /// overloads can be converted to \c Matcher<T>. If there are more than one
174 /// that can, the result would be ambiguous and false is returned.
176 bool hasTypedMatcher() const {
177 if (!Value) return false;
178 return Value->getTypedMatcher(TypedMatcherOps<T>()).hasValue();
181 /// Determines if the contained matcher can be converted to \p Kind.
183 /// \param Kind the requested destination type.
185 /// \param Specificity value corresponding to the "specificity" of the
187 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
188 unsigned *Specificity) const {
190 return Value->isConvertibleTo(Kind, Specificity);
194 /// Return this matcher as a \c Matcher<T>.
196 /// Handles the different types (Single, Polymorphic) accordingly.
197 /// Asserts that \c hasTypedMatcher<T>() is true.
199 ast_matchers::internal::Matcher<T> getTypedMatcher() const {
200 assert(hasTypedMatcher<T>() && "hasTypedMatcher<T>() == false");
201 return Value->getTypedMatcher(TypedMatcherOps<T>())
202 ->template convertTo<T>();
205 /// String representation of the type of the value.
207 /// If the underlying matcher is a polymorphic one, the string will show all
209 std::string getTypeAsString() const;
212 explicit VariantMatcher(std::shared_ptr<Payload> Value)
213 : Value(std::move(Value)) {}
215 template <typename T> struct TypedMatcherOps;
218 class PolymorphicPayload;
219 class VariadicOpPayload;
221 std::shared_ptr<const Payload> Value;
224 template <typename T>
225 struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps {
227 : MatcherOps(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()) {}
228 typedef ast_matchers::internal::Matcher<T> MatcherT;
231 convertMatcher(const DynTypedMatcher &Matcher) const override {
232 return DynTypedMatcher(Matcher.convertTo<T>());
236 /// Variant value class.
238 /// Basically, a tagged union with value type semantics.
239 /// It is used by the registry as the return value and argument type for the
240 /// matcher factory methods.
241 /// It can be constructed from any of the supported types. It supports
248 /// - \c llvm::StringRef
249 /// - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
252 VariantValue() : Type(VT_Nothing) {}
254 VariantValue(const VariantValue &Other);
256 VariantValue &operator=(const VariantValue &Other);
258 /// Specific constructors for each supported type.
259 VariantValue(bool Boolean);
260 VariantValue(double Double);
261 VariantValue(unsigned Unsigned);
262 VariantValue(StringRef String);
263 VariantValue(const VariantMatcher &Matchers);
265 /// Constructs an \c unsigned value (disambiguation from bool).
266 VariantValue(int Signed) : VariantValue(static_cast<unsigned>(Signed)) {}
268 /// Returns true iff this is not an empty value.
269 explicit operator bool() const { return hasValue(); }
270 bool hasValue() const { return Type != VT_Nothing; }
272 /// Boolean value functions.
273 bool isBoolean() const;
274 bool getBoolean() const;
275 void setBoolean(bool Boolean);
277 /// Double value functions.
278 bool isDouble() const;
279 double getDouble() const;
280 void setDouble(double Double);
282 /// Unsigned value functions.
283 bool isUnsigned() const;
284 unsigned getUnsigned() const;
285 void setUnsigned(unsigned Unsigned);
287 /// String value functions.
288 bool isString() const;
289 const std::string &getString() const;
290 void setString(StringRef String);
292 /// Matcher value functions.
293 bool isMatcher() const;
294 const VariantMatcher &getMatcher() const;
295 void setMatcher(const VariantMatcher &Matcher);
297 /// Determines if the contained value can be converted to \p Kind.
299 /// \param Kind the requested destination type.
301 /// \param Specificity value corresponding to the "specificity" of the
303 bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const;
305 /// Determines if the contained value can be converted to any kind
308 /// \param Kinds the requested destination types.
310 /// \param Specificity value corresponding to the "specificity" of the
311 /// conversion. It is the maximum specificity of all the possible
313 bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const;
315 /// String representation of the type of the value.
316 std::string getTypeAsString() const;
321 /// All supported value types.
331 /// All supported value types.
337 VariantMatcher *Matcher;
344 } // end namespace dynamic
345 } // end namespace ast_matchers
346 } // end namespace clang
348 #endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H