blob: ae22e37d8ec7846f77a1afafaa8f6c2535efb72f [file] [log] [blame]
Manuel Klimekf7f295f2013-05-14 09:13:00 +00001//===--- VariantValue.h - Polymorphic value type -*- C++ -*-===/
2// The LLVM Compiler Infrastructure
3//
4// This file is distributed under the University of Illinois Open Source
5// License. See LICENSE.TXT for details.
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// \brief Polymorphic value type.
11///
12/// Supports all the types required for dynamic Matcher construction.
13/// Used by the registry to construct matchers in a generic way.
14///
15//===----------------------------------------------------------------------===//
16
Stephen Hines176edba2014-12-01 14:53:08 -080017#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
18#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
Manuel Klimekf7f295f2013-05-14 09:13:00 +000019
20#include "clang/ASTMatchers/ASTMatchers.h"
21#include "clang/ASTMatchers/ASTMatchersInternal.h"
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000022#include "llvm/ADT/IntrusiveRefCntPtr.h"
Samuel Benzaquenb7488d72013-10-29 14:37:15 +000023#include "llvm/ADT/Optional.h"
Manuel Klimekf7f295f2013-05-14 09:13:00 +000024#include "llvm/ADT/Twine.h"
Stephen Hines651f13c2014-04-23 16:59:28 -070025#include <memory>
26#include <vector>
Manuel Klimekf7f295f2013-05-14 09:13:00 +000027
28namespace clang {
29namespace ast_matchers {
30namespace dynamic {
31
Stephen Hines176edba2014-12-01 14:53:08 -080032/// \brief Kind identifier.
33///
34/// It supports all types that VariantValue can contain.
35class ArgKind {
36 public:
37 enum Kind {
38 AK_Matcher,
39 AK_Unsigned,
40 AK_String
41 };
42 /// \brief Constructor for non-matcher types.
43 ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); }
44
45 /// \brief Constructor for matcher types.
46 ArgKind(ast_type_traits::ASTNodeKind MatcherKind)
47 : K(AK_Matcher), MatcherKind(MatcherKind) {}
48
49 Kind getArgKind() const { return K; }
50 ast_type_traits::ASTNodeKind getMatcherKind() const {
51 assert(K == AK_Matcher);
52 return MatcherKind;
53 }
54
55 /// \brief Determines if this type can be converted to \p To.
56 ///
57 /// \param To the requested destination type.
58 ///
59 /// \param Specificity value corresponding to the "specificity" of the
60 /// convertion.
61 bool isConvertibleTo(ArgKind To, unsigned *Specificity) const;
62
63 bool operator<(const ArgKind &Other) const {
64 if (K == AK_Matcher && Other.K == AK_Matcher)
65 return MatcherKind < Other.MatcherKind;
66 return K < Other.K;
67 }
68
69 /// \brief String representation of the type.
70 std::string asString() const;
71
72private:
73 Kind K;
74 ast_type_traits::ASTNodeKind MatcherKind;
75};
76
Reid Kleckner6e019942013-05-14 20:30:49 +000077using ast_matchers::internal::DynTypedMatcher;
Manuel Klimekf7f295f2013-05-14 09:13:00 +000078
Samuel Benzaquen9d028072013-08-13 14:54:51 +000079/// \brief A variant matcher object.
Samuel Benzaquenef7eb022013-06-21 15:51:31 +000080///
Samuel Benzaquen9d028072013-08-13 14:54:51 +000081/// 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>.
92class VariantMatcher {
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000093 /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher.
94 class MatcherOps {
95 public:
Stephen Hines176edba2014-12-01 14:53:08 -080096 MatcherOps(ast_type_traits::ASTNodeKind NodeKind) : NodeKind(NodeKind) {}
97
98 bool canConstructFrom(const DynTypedMatcher &Matcher,
99 bool &IsExactMatch) const;
100
101 /// \brief Convert \p Matcher the destination type and return it as a new
102 /// DynTypedMatcher.
103 virtual DynTypedMatcher
104 convertMatcher(const DynTypedMatcher &Matcher) const = 0;
105
106 /// \brief 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;
112
113 protected:
114 ~MatcherOps() {}
115
116 private:
117 ast_type_traits::ASTNodeKind NodeKind;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000118 };
119
120 /// \brief Payload interface to be specialized by each matcher type.
121 ///
122 /// It follows a similar interface as VariantMatcher itself.
123 class Payload : public RefCountedBaseVPTR {
124 public:
125 virtual ~Payload();
Samuel Benzaquenb7488d72013-10-29 14:37:15 +0000126 virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000127 virtual std::string getTypeAsString() const = 0;
Stephen Hines176edba2014-12-01 14:53:08 -0800128 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;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000132 };
133
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000134public:
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000135 /// \brief A null matcher.
136 VariantMatcher();
137
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000138 /// \brief Clones the provided matcher.
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000139 static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher);
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000140
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000141 /// \brief Clones the provided matchers.
142 ///
143 /// They should be the result of a polymorphic matcher.
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700144 static VariantMatcher
145 PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers);
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000146
Samuel Benzaquena7350902013-08-28 18:42:04 +0000147 /// \brief Creates a 'variadic' operator matcher.
148 ///
149 /// It will bind to the appropriate type on getTypedMatcher<T>().
Stephen Hines176edba2014-12-01 14:53:08 -0800150 static VariantMatcher
151 VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,
152 std::vector<VariantMatcher> Args);
Samuel Benzaquena7350902013-08-28 18:42:04 +0000153
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000154 /// \brief Makes the matcher the "null" matcher.
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000155 void reset();
156
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000157 /// \brief Whether the matcher is null.
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000158 bool isNull() const { return !Value; }
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000159
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000160 /// \brief Return a single matcher, if there is no ambiguity.
161 ///
Samuel Benzaquenb7488d72013-10-29 14:37:15 +0000162 /// \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
164 /// representation.
165 llvm::Optional<DynTypedMatcher> getSingleMatcher() const;
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000166
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000167 /// \brief Determines if the contained matcher can be converted to
168 /// \c Matcher<T>.
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000169 ///
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000170 /// For the Single case, it returns true if it can be converted to
171 /// \c Matcher<T>.
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.
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000175 template <class T>
176 bool hasTypedMatcher() const {
Stephen Hines176edba2014-12-01 14:53:08 -0800177 if (!Value) return false;
178 return Value->getTypedMatcher(TypedMatcherOps<T>()).hasValue();
179 }
180
181 /// \brief Determines if the contained matcher can be converted to \p Kind.
182 ///
183 /// \param Kind the requested destination type.
184 ///
185 /// \param Specificity value corresponding to the "specificity" of the
186 /// convertion.
187 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
188 unsigned *Specificity) const {
189 if (Value)
190 return Value->isConvertibleTo(Kind, Specificity);
191 return false;
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000192 }
193
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000194 /// \brief Return this matcher as a \c Matcher<T>.
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000195 ///
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000196 /// Handles the different types (Single, Polymorphic) accordingly.
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000197 /// Asserts that \c hasTypedMatcher<T>() is true.
198 template <class T>
199 ast_matchers::internal::Matcher<T> getTypedMatcher() const {
Stephen Hines176edba2014-12-01 14:53:08 -0800200 assert(hasTypedMatcher<T>() && "hasTypedMatcher<T>() == false");
201 return Value->getTypedMatcher(TypedMatcherOps<T>())
202 ->template convertTo<T>();
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000203 }
204
205 /// \brief String representation of the type of the value.
206 ///
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000207 /// If the underlying matcher is a polymorphic one, the string will show all
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000208 /// the types.
209 std::string getTypeAsString() const;
210
211private:
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000212 explicit VariantMatcher(Payload *Value) : Value(Value) {}
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000213
Stephen Hines176edba2014-12-01 14:53:08 -0800214 template <typename T> struct TypedMatcherOps;
215
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000216 class SinglePayload;
217 class PolymorphicPayload;
Samuel Benzaquena7350902013-08-28 18:42:04 +0000218 class VariadicOpPayload;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000219
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000220 IntrusiveRefCntPtr<const Payload> Value;
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000221};
222
Stephen Hines176edba2014-12-01 14:53:08 -0800223template <typename T>
224struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps {
225 TypedMatcherOps()
226 : MatcherOps(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()) {}
227 typedef ast_matchers::internal::Matcher<T> MatcherT;
228
229 DynTypedMatcher
230 convertMatcher(const DynTypedMatcher &Matcher) const override {
231 return DynTypedMatcher(Matcher.convertTo<T>());
232 }
233};
234
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000235/// \brief Variant value class.
236///
237/// Basically, a tagged union with value type semantics.
238/// It is used by the registry as the return value and argument type for the
239/// matcher factory methods.
240/// It can be constructed from any of the supported types. It supports
241/// copy/assignment.
242///
243/// Supported types:
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000244/// - \c unsigned
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000245/// - \c std::string
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000246/// - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000247class VariantValue {
248public:
249 VariantValue() : Type(VT_Nothing) {}
250
251 VariantValue(const VariantValue &Other);
252 ~VariantValue();
253 VariantValue &operator=(const VariantValue &Other);
254
255 /// \brief Specific constructors for each supported type.
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000256 VariantValue(unsigned Unsigned);
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000257 VariantValue(const std::string &String);
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000258 VariantValue(const VariantMatcher &Matchers);
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000259
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700260 /// \brief Returns true iff this is not an empty value.
Stephen Hines0e2c34f2015-03-23 12:09:02 -0700261 explicit operator bool() const { return hasValue(); }
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700262 bool hasValue() const { return Type != VT_Nothing; }
263
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000264 /// \brief Unsigned value functions.
265 bool isUnsigned() const;
266 unsigned getUnsigned() const;
267 void setUnsigned(unsigned Unsigned);
268
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000269 /// \brief String value functions.
270 bool isString() const;
271 const std::string &getString() const;
272 void setString(const std::string &String);
273
274 /// \brief Matcher value functions.
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000275 bool isMatcher() const;
276 const VariantMatcher &getMatcher() const;
277 void setMatcher(const VariantMatcher &Matcher);
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000278
Stephen Hines176edba2014-12-01 14:53:08 -0800279 /// \brief Determines if the contained value can be converted to \p Kind.
280 ///
281 /// \param Kind the requested destination type.
282 ///
283 /// \param Specificity value corresponding to the "specificity" of the
284 /// convertion.
285 bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const;
286
287 /// \brief Determines if the contained value can be converted to any kind
288 /// in \p Kinds.
289 ///
290 /// \param Kinds the requested destination types.
291 ///
292 /// \param Specificity value corresponding to the "specificity" of the
293 /// convertion. It is the maximum specificity of all the possible
294 /// conversions.
295 bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const;
296
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000297 /// \brief String representation of the type of the value.
298 std::string getTypeAsString() const;
299
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000300private:
301 void reset();
302
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000303 /// \brief All supported value types.
304 enum ValueType {
305 VT_Nothing,
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000306 VT_Unsigned,
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000307 VT_String,
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000308 VT_Matcher
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000309 };
310
311 /// \brief All supported value types.
312 union AllValues {
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000313 unsigned Unsigned;
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000314 std::string *String;
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000315 VariantMatcher *Matcher;
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000316 };
317
318 ValueType Type;
319 AllValues Value;
320};
321
322} // end namespace dynamic
323} // end namespace ast_matchers
324} // end namespace clang
325
326#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H