blob: 9f1cfe3443fee5f8acf162169703984546d8071e [file] [log] [blame]
Manuel Klimek24db0f02013-05-14 09:13:00 +00001//===--- Marshallers.h - Generic matcher function marshallers -*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief Functions templates and classes to wrap matcher construct functions.
12///
13/// A collection of template function and classes that provide a generic
14/// marshalling layer on top of matcher construct functions.
15/// These are used by the registry to export all marshaller constructors with
16/// the same generic interface.
17///
18//===----------------------------------------------------------------------===//
19
20#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H
21#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H
22
Manuel Klimek24db0f02013-05-14 09:13:00 +000023#include <string>
Manuel Klimek24db0f02013-05-14 09:13:00 +000024
25#include "clang/ASTMatchers/ASTMatchers.h"
26#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
27#include "clang/ASTMatchers/Dynamic/VariantValue.h"
28#include "clang/Basic/LLVM.h"
29#include "llvm/Support/type_traits.h"
30
31namespace clang {
32namespace ast_matchers {
33namespace dynamic {
34
35namespace internal {
36
37/// \brief Helper template class to just from argument type to the right is/get
38/// functions in VariantValue.
39/// Used to verify and extract the matcher arguments below.
40template <class T> struct ArgTypeTraits;
41template <class T> struct ArgTypeTraits<const T &> : public ArgTypeTraits<T> {
42};
43
44template <> struct ArgTypeTraits<std::string> {
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000045 static StringRef asString() { return "String"; }
Manuel Klimek24db0f02013-05-14 09:13:00 +000046 static bool is(const VariantValue &Value) { return Value.isString(); }
47 static const std::string &get(const VariantValue &Value) {
48 return Value.getString();
49 }
50};
51
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +000052template <>
53struct ArgTypeTraits<StringRef> : public ArgTypeTraits<std::string> {
54};
55
Manuel Klimek24db0f02013-05-14 09:13:00 +000056template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > {
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000057 static std::string asString() {
58 return (Twine("Matcher<") +
59 ast_type_traits::ASTNodeKind::getFromNodeKind<T>().asStringRef() +
60 ">").str();
61 }
62 static bool is(const VariantValue &Value) {
63 return Value.hasTypedMatcher<T>();
64 }
Manuel Klimek24db0f02013-05-14 09:13:00 +000065 static ast_matchers::internal::Matcher<T> get(const VariantValue &Value) {
66 return Value.getTypedMatcher<T>();
67 }
Samuel Benzaquenc31b3522013-06-04 15:46:22 +000068};
Manuel Klimek24db0f02013-05-14 09:13:00 +000069
Samuel Benzaquenc31b3522013-06-04 15:46:22 +000070template <> struct ArgTypeTraits<unsigned> {
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000071 static std::string asString() { return "Unsigned"; }
Samuel Benzaquenc31b3522013-06-04 15:46:22 +000072 static bool is(const VariantValue &Value) { return Value.isUnsigned(); }
73 static unsigned get(const VariantValue &Value) {
74 return Value.getUnsigned();
75 }
Manuel Klimek24db0f02013-05-14 09:13:00 +000076};
77
78/// \brief Generic MatcherCreate interface.
79///
80/// Provides a \c run() method that constructs the matcher from the provided
81/// arguments.
82class MatcherCreateCallback {
83public:
84 virtual ~MatcherCreateCallback() {}
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +000085 virtual MatcherList run(const SourceRange &NameRange,
86 ArrayRef<ParserValue> Args,
87 Diagnostics *Error) const = 0;
Manuel Klimek24db0f02013-05-14 09:13:00 +000088};
89
90/// \brief Simple callback implementation. Marshaller and function are provided.
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +000091///
92/// This class wraps a function of arbitrary signature and a marshaller
93/// function into a MatcherCreateCallback.
94/// The marshaller is in charge of taking the VariantValue arguments, checking
95/// their types, unpacking them and calling the underlying function.
96template <typename FuncType>
Manuel Klimek24db0f02013-05-14 09:13:00 +000097class FixedArgCountMatcherCreateCallback : public MatcherCreateCallback {
98public:
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +000099 /// FIXME: Use void(*)() as FuncType on this interface to remove the template
100 /// argument of this class. The marshaller can cast the function pointer back
101 /// to the original type.
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000102 typedef MatcherList (*MarshallerType)(FuncType, StringRef,
103 const SourceRange &,
104 ArrayRef<ParserValue>,
105 Diagnostics *);
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000106
Dmitri Gribenkocb63baf2013-05-17 17:50:16 +0000107 /// \param Marshaller Function to unpack the arguments and call \c Func
108 /// \param Func Matcher construct function. This is the function that
109 /// compile-time matcher expressions would use to create the matcher.
Manuel Klimek24db0f02013-05-14 09:13:00 +0000110 FixedArgCountMatcherCreateCallback(MarshallerType Marshaller, FuncType Func,
111 StringRef MatcherName)
112 : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName.str()) {}
113
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000114 MatcherList run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
115 Diagnostics *Error) const {
Manuel Klimek24db0f02013-05-14 09:13:00 +0000116 return Marshaller(Func, MatcherName, NameRange, Args, Error);
117 }
118
119private:
120 const MarshallerType Marshaller;
121 const FuncType Func;
122 const std::string MatcherName;
123};
124
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000125/// \brief Simple callback implementation. Free function is wrapped.
126///
127/// This class simply wraps a free function with the right signature to export
128/// it as a MatcherCreateCallback.
129/// This allows us to have one implementation of the interface for as many free
130/// functions as we want, reducing the number of symbols and size of the
131/// object file.
132class FreeFuncMatcherCreateCallback : public MatcherCreateCallback {
133public:
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000134 typedef MatcherList (*RunFunc)(StringRef MatcherName,
135 const SourceRange &NameRange,
136 ArrayRef<ParserValue> Args,
137 Diagnostics *Error);
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000138
139 FreeFuncMatcherCreateCallback(RunFunc Func, StringRef MatcherName)
140 : Func(Func), MatcherName(MatcherName.str()) {}
141
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000142 MatcherList run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
143 Diagnostics *Error) const {
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000144 return Func(MatcherName, NameRange, Args, Error);
145 }
146
147private:
148 const RunFunc Func;
149 const std::string MatcherName;
150};
Manuel Klimek24db0f02013-05-14 09:13:00 +0000151
152/// \brief Helper macros to check the arguments on all marshaller functions.
153#define CHECK_ARG_COUNT(count) \
154 if (Args.size() != count) { \
Samuel Benzaquena37bb8c2013-07-18 19:47:59 +0000155 Error->addError(NameRange, Error->ET_RegistryWrongArgCount) \
Manuel Klimek24db0f02013-05-14 09:13:00 +0000156 << count << Args.size(); \
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000157 return MatcherList(); \
Manuel Klimek24db0f02013-05-14 09:13:00 +0000158 }
159
160#define CHECK_ARG_TYPE(index, type) \
161 if (!ArgTypeTraits<type>::is(Args[index].Value)) { \
Samuel Benzaquena37bb8c2013-07-18 19:47:59 +0000162 Error->addError(Args[index].Range, Error->ET_RegistryWrongArgType) \
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000163 << (index + 1) << ArgTypeTraits<type>::asString() \
164 << Args[index].Value.getTypeAsString(); \
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000165 return MatcherList(); \
Manuel Klimek24db0f02013-05-14 09:13:00 +0000166 }
167
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000168/// \brief Helper methods to extract and merge all possible typed matchers
169/// out of the polymorphic object.
170template <class PolyMatcher>
171static void mergePolyMatchers(const PolyMatcher &Poly, MatcherList *Out,
172 ast_matchers::internal::EmptyTypeList) {}
173
174template <class PolyMatcher, class TypeList>
175static void mergePolyMatchers(const PolyMatcher &Poly, MatcherList *Out,
176 TypeList) {
177 Out->add(ast_matchers::internal::Matcher<typename TypeList::head>(Poly));
178 mergePolyMatchers(Poly, Out, typename TypeList::tail());
179}
180
181/// \brief Convert the return values of the functions into a MatcherList.
182///
183/// There are 2 cases right now: The return value is a Matcher<T> or is a
184/// polymorphic matcher. For the former, we just construct the MatcherList. For
185/// the latter, we instantiate all the possible Matcher<T> of the poly matcher.
186template <typename T>
187static MatcherList
188outvalueToMatcherList(const ast_matchers::internal::Matcher<T> &Matcher) {
189 return MatcherList(Matcher);
190}
191
192template <typename T>
193static MatcherList
194outvalueToMatcherList(const T& PolyMatcher, typename T::ReturnTypes* = NULL) {
195 MatcherList Matchers;
196 mergePolyMatchers(PolyMatcher, &Matchers, typename T::ReturnTypes());
197 return Matchers;
198}
199
Manuel Klimek24db0f02013-05-14 09:13:00 +0000200/// \brief 0-arg marshaller function.
201template <typename ReturnType>
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000202static MatcherList matcherMarshall0(ReturnType (*Func)(),
203 StringRef MatcherName,
204 const SourceRange &NameRange,
205 ArrayRef<ParserValue> Args,
206 Diagnostics *Error) {
Manuel Klimek24db0f02013-05-14 09:13:00 +0000207 CHECK_ARG_COUNT(0);
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000208 return outvalueToMatcherList(Func());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000209}
210
211/// \brief 1-arg marshaller function.
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000212template <typename ReturnType, typename ArgType1>
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000213static MatcherList matcherMarshall1(ReturnType (*Func)(ArgType1),
214 StringRef MatcherName,
215 const SourceRange &NameRange,
216 ArrayRef<ParserValue> Args,
217 Diagnostics *Error) {
Manuel Klimek24db0f02013-05-14 09:13:00 +0000218 CHECK_ARG_COUNT(1);
219 CHECK_ARG_TYPE(0, ArgType1);
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000220 return outvalueToMatcherList(
221 Func(ArgTypeTraits<ArgType1>::get(Args[0].Value)));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000222}
223
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000224/// \brief 2-arg marshaller function.
225template <typename ReturnType, typename ArgType1, typename ArgType2>
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000226static MatcherList matcherMarshall2(ReturnType (*Func)(ArgType1, ArgType2),
227 StringRef MatcherName,
228 const SourceRange &NameRange,
229 ArrayRef<ParserValue> Args,
230 Diagnostics *Error) {
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000231 CHECK_ARG_COUNT(2);
232 CHECK_ARG_TYPE(0, ArgType1);
233 CHECK_ARG_TYPE(1, ArgType2);
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000234 return outvalueToMatcherList(
235 Func(ArgTypeTraits<ArgType1>::get(Args[0].Value),
236 ArgTypeTraits<ArgType2>::get(Args[1].Value)));
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000237}
238
Manuel Klimek24db0f02013-05-14 09:13:00 +0000239#undef CHECK_ARG_COUNT
240#undef CHECK_ARG_TYPE
241
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000242/// \brief Variadic marshaller function.
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000243template <typename ResultT, typename ArgT,
244 ResultT (*Func)(ArrayRef<const ArgT *>)>
245MatcherList variadicMatcherCreateCallback(StringRef MatcherName,
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000246 const SourceRange &NameRange,
247 ArrayRef<ParserValue> Args,
248 Diagnostics *Error) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000249 ArgT **InnerArgs = new ArgT *[Args.size()]();
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000250
251 bool HasError = false;
252 for (size_t i = 0, e = Args.size(); i != e; ++i) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000253 typedef ArgTypeTraits<ArgT> ArgTraits;
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000254 const ParserValue &Arg = Args[i];
255 const VariantValue &Value = Arg.Value;
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000256 if (!ArgTraits::is(Value)) {
Samuel Benzaquena37bb8c2013-07-18 19:47:59 +0000257 Error->addError(Arg.Range, Error->ET_RegistryWrongArgType)
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000258 << (i + 1) << ArgTraits::asString() << Value.getTypeAsString();
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000259 HasError = true;
260 break;
261 }
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000262 InnerArgs[i] = new ArgT(ArgTraits::get(Value));
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000263 }
264
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000265 MatcherList Out;
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000266 if (!HasError) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000267 Out = outvalueToMatcherList(
268 Func(ArrayRef<const ArgT *>(InnerArgs, Args.size())));
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000269 }
270
271 for (size_t i = 0, e = Args.size(); i != e; ++i) {
272 delete InnerArgs[i];
273 }
274 delete[] InnerArgs;
275 return Out;
276}
277
Manuel Klimek24db0f02013-05-14 09:13:00 +0000278/// Helper functions to select the appropriate marshaller functions.
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000279/// They detect the number of arguments, arguments types and return type.
Manuel Klimek24db0f02013-05-14 09:13:00 +0000280
281/// \brief 0-arg overload
282template <typename ReturnType>
283MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(),
284 StringRef MatcherName) {
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000285 return new FixedArgCountMatcherCreateCallback<ReturnType (*)()>(
286 matcherMarshall0, Func, MatcherName);
Manuel Klimek24db0f02013-05-14 09:13:00 +0000287}
288
289/// \brief 1-arg overload
290template <typename ReturnType, typename ArgType1>
291MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1),
292 StringRef MatcherName) {
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000293 return new FixedArgCountMatcherCreateCallback<ReturnType (*)(ArgType1)>(
294 matcherMarshall1, Func, MatcherName);
Manuel Klimek24db0f02013-05-14 09:13:00 +0000295}
296
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000297/// \brief 2-arg overload
298template <typename ReturnType, typename ArgType1, typename ArgType2>
299MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1,
300 ArgType2),
301 StringRef MatcherName) {
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000302 return new FixedArgCountMatcherCreateCallback<
303 ReturnType (*)(ArgType1, ArgType2)>(matcherMarshall2, Func, MatcherName);
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000304}
305
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000306/// \brief Variadic overload.
307template <typename ResultT, typename ArgT,
308 ResultT (*Func)(ArrayRef<const ArgT *>)>
Manuel Klimek24db0f02013-05-14 09:13:00 +0000309MatcherCreateCallback *
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000310makeMatcherAutoMarshall(llvm::VariadicFunction<ResultT, ArgT, Func> VarFunc,
Manuel Klimek24db0f02013-05-14 09:13:00 +0000311 StringRef MatcherName) {
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000312 return new FreeFuncMatcherCreateCallback(
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000313 &variadicMatcherCreateCallback<ResultT, ArgT, Func>, MatcherName);
Manuel Klimek24db0f02013-05-14 09:13:00 +0000314}
315
316} // namespace internal
317} // namespace dynamic
318} // namespace ast_matchers
319} // namespace clang
320
321#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H