blob: 4ba33b8d2d9d712117f9f06ef4b478b8bcfd21eb [file] [log] [blame]
Manuel Klimekf7f295f2013-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 Klimekf7f295f2013-05-14 09:13:00 +000023#include <string>
Manuel Klimekf7f295f2013-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> {
45 static bool is(const VariantValue &Value) { return Value.isString(); }
46 static const std::string &get(const VariantValue &Value) {
47 return Value.getString();
48 }
49};
50
51template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > {
52 static bool is(const VariantValue &Value) { return Value.isMatcher(); }
53 static ast_matchers::internal::Matcher<T> get(const VariantValue &Value) {
54 return Value.getTypedMatcher<T>();
55 }
Samuel Benzaquen7a337af2013-06-04 15:46:22 +000056};
Manuel Klimekf7f295f2013-05-14 09:13:00 +000057
Samuel Benzaquen7a337af2013-06-04 15:46:22 +000058template <> struct ArgTypeTraits<unsigned> {
59 static bool is(const VariantValue &Value) { return Value.isUnsigned(); }
60 static unsigned get(const VariantValue &Value) {
61 return Value.getUnsigned();
62 }
Manuel Klimekf7f295f2013-05-14 09:13:00 +000063};
64
65/// \brief Generic MatcherCreate interface.
66///
67/// Provides a \c run() method that constructs the matcher from the provided
68/// arguments.
69class MatcherCreateCallback {
70public:
71 virtual ~MatcherCreateCallback() {}
72 virtual DynTypedMatcher *run(const SourceRange &NameRange,
73 ArrayRef<ParserValue> Args,
74 Diagnostics *Error) const = 0;
75};
76
77/// \brief Simple callback implementation. Marshaller and function are provided.
Samuel Benzaquencf695902013-06-11 18:51:07 +000078///
79/// This class wraps a function of arbitrary signature and a marshaller
80/// function into a MatcherCreateCallback.
81/// The marshaller is in charge of taking the VariantValue arguments, checking
82/// their types, unpacking them and calling the underlying function.
83template <typename FuncType>
Manuel Klimekf7f295f2013-05-14 09:13:00 +000084class FixedArgCountMatcherCreateCallback : public MatcherCreateCallback {
85public:
Samuel Benzaquencf695902013-06-11 18:51:07 +000086 /// FIXME: Use void(*)() as FuncType on this interface to remove the template
87 /// argument of this class. The marshaller can cast the function pointer back
88 /// to the original type.
89 typedef DynTypedMatcher *(*MarshallerType)(FuncType, StringRef,
90 const SourceRange &,
91 ArrayRef<ParserValue>,
92 Diagnostics *);
93
Dmitri Gribenkoe3c63fc2013-05-17 17:50:16 +000094 /// \param Marshaller Function to unpack the arguments and call \c Func
95 /// \param Func Matcher construct function. This is the function that
96 /// compile-time matcher expressions would use to create the matcher.
Manuel Klimekf7f295f2013-05-14 09:13:00 +000097 FixedArgCountMatcherCreateCallback(MarshallerType Marshaller, FuncType Func,
98 StringRef MatcherName)
99 : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName.str()) {}
100
101 DynTypedMatcher *run(const SourceRange &NameRange,
102 ArrayRef<ParserValue> Args, Diagnostics *Error) const {
103 return Marshaller(Func, MatcherName, NameRange, Args, Error);
104 }
105
106private:
107 const MarshallerType Marshaller;
108 const FuncType Func;
109 const std::string MatcherName;
110};
111
Samuel Benzaquencf695902013-06-11 18:51:07 +0000112/// \brief Simple callback implementation. Free function is wrapped.
113///
114/// This class simply wraps a free function with the right signature to export
115/// it as a MatcherCreateCallback.
116/// This allows us to have one implementation of the interface for as many free
117/// functions as we want, reducing the number of symbols and size of the
118/// object file.
119class FreeFuncMatcherCreateCallback : public MatcherCreateCallback {
120public:
121 typedef DynTypedMatcher *(*RunFunc)(StringRef MatcherName,
122 const SourceRange &NameRange,
123 ArrayRef<ParserValue> Args,
124 Diagnostics *Error);
125
126 FreeFuncMatcherCreateCallback(RunFunc Func, StringRef MatcherName)
127 : Func(Func), MatcherName(MatcherName.str()) {}
128
129 DynTypedMatcher *run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
130 Diagnostics *Error) const {
131 return Func(MatcherName, NameRange, Args, Error);
132 }
133
134private:
135 const RunFunc Func;
136 const std::string MatcherName;
137};
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000138
139/// \brief Helper macros to check the arguments on all marshaller functions.
140#define CHECK_ARG_COUNT(count) \
141 if (Args.size() != count) { \
142 Error->pushErrorFrame(NameRange, Error->ET_RegistryWrongArgCount) \
143 << count << Args.size(); \
144 return NULL; \
145 }
146
147#define CHECK_ARG_TYPE(index, type) \
148 if (!ArgTypeTraits<type>::is(Args[index].Value)) { \
149 Error->pushErrorFrame(Args[index].Range, Error->ET_RegistryWrongArgType) \
150 << MatcherName << (index + 1); \
151 return NULL; \
152 }
153
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000154/// \brief 0-arg marshaller function.
155template <typename ReturnType>
156DynTypedMatcher *matcherMarshall0(ReturnType (*Func)(), StringRef MatcherName,
157 const SourceRange &NameRange,
158 ArrayRef<ParserValue> Args,
159 Diagnostics *Error) {
160 CHECK_ARG_COUNT(0);
161 return Func().clone();
162}
163
164/// \brief 1-arg marshaller function.
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000165template <typename ReturnType, typename ArgType1>
166DynTypedMatcher *matcherMarshall1(ReturnType (*Func)(ArgType1),
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000167 StringRef MatcherName,
168 const SourceRange &NameRange,
169 ArrayRef<ParserValue> Args,
170 Diagnostics *Error) {
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000171 CHECK_ARG_COUNT(1);
172 CHECK_ARG_TYPE(0, ArgType1);
173 return Func(ArgTypeTraits<ArgType1>::get(Args[0].Value)).clone();
174}
175
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000176/// \brief 2-arg marshaller function.
177template <typename ReturnType, typename ArgType1, typename ArgType2>
178DynTypedMatcher *matcherMarshall2(ReturnType (*Func)(ArgType1, ArgType2),
179 StringRef MatcherName,
180 const SourceRange &NameRange,
181 ArrayRef<ParserValue> Args,
182 Diagnostics *Error) {
183 CHECK_ARG_COUNT(2);
184 CHECK_ARG_TYPE(0, ArgType1);
185 CHECK_ARG_TYPE(1, ArgType2);
186 return Func(ArgTypeTraits<ArgType1>::get(Args[0].Value),
187 ArgTypeTraits<ArgType2>::get(Args[1].Value)).clone();
188}
189
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000190#undef CHECK_ARG_COUNT
191#undef CHECK_ARG_TYPE
192
Samuel Benzaquencf695902013-06-11 18:51:07 +0000193/// \brief Variadic marshaller function.
194template <typename BaseType, typename DerivedType>
195DynTypedMatcher *VariadicMatcherCreateCallback(StringRef MatcherName,
196 const SourceRange &NameRange,
197 ArrayRef<ParserValue> Args,
198 Diagnostics *Error) {
199 typedef ast_matchers::internal::Matcher<DerivedType> DerivedMatcherType;
200 DerivedMatcherType **InnerArgs = new DerivedMatcherType *[Args.size()]();
201
202 bool HasError = false;
203 for (size_t i = 0, e = Args.size(); i != e; ++i) {
204 if (!Args[i].Value.isTypedMatcher<DerivedType>()) {
205 Error->pushErrorFrame(Args[i].Range, Error->ET_RegistryWrongArgType)
206 << MatcherName << (i + 1);
207 HasError = true;
208 break;
209 }
210 InnerArgs[i] =
211 new DerivedMatcherType(Args[i].Value.getTypedMatcher<DerivedType>());
212 }
213
214 DynTypedMatcher *Out = NULL;
215 if (!HasError) {
216 Out = ast_matchers::internal::makeDynCastAllOfComposite<BaseType>(
217 ArrayRef<const DerivedMatcherType *>(InnerArgs, Args.size())).clone();
218 }
219
220 for (size_t i = 0, e = Args.size(); i != e; ++i) {
221 delete InnerArgs[i];
222 }
223 delete[] InnerArgs;
224 return Out;
225}
226
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000227/// Helper functions to select the appropriate marshaller functions.
Samuel Benzaquencf695902013-06-11 18:51:07 +0000228/// They detect the number of arguments, arguments types and return type.
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000229
230/// \brief 0-arg overload
231template <typename ReturnType>
232MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(),
233 StringRef MatcherName) {
Samuel Benzaquencf695902013-06-11 18:51:07 +0000234 return new FixedArgCountMatcherCreateCallback<ReturnType (*)()>(
235 matcherMarshall0, Func, MatcherName);
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000236}
237
238/// \brief 1-arg overload
239template <typename ReturnType, typename ArgType1>
240MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1),
241 StringRef MatcherName) {
Samuel Benzaquencf695902013-06-11 18:51:07 +0000242 return new FixedArgCountMatcherCreateCallback<ReturnType (*)(ArgType1)>(
243 matcherMarshall1, Func, MatcherName);
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000244}
245
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000246/// \brief 2-arg overload
247template <typename ReturnType, typename ArgType1, typename ArgType2>
248MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1,
249 ArgType2),
250 StringRef MatcherName) {
Samuel Benzaquencf695902013-06-11 18:51:07 +0000251 return new FixedArgCountMatcherCreateCallback<
252 ReturnType (*)(ArgType1, ArgType2)>(matcherMarshall2, Func, MatcherName);
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000253}
254
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000255/// \brief Variadic overload.
256template <typename MatcherType>
257MatcherCreateCallback *makeMatcherAutoMarshall(
258 ast_matchers::internal::VariadicAllOfMatcher<MatcherType> Func,
259 StringRef MatcherName) {
Samuel Benzaquencf695902013-06-11 18:51:07 +0000260 return new FreeFuncMatcherCreateCallback(
261 &VariadicMatcherCreateCallback<MatcherType, MatcherType>, MatcherName);
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000262}
263
264template <typename BaseType, typename MatcherType>
265MatcherCreateCallback *
266makeMatcherAutoMarshall(ast_matchers::internal::VariadicDynCastAllOfMatcher<
267 BaseType, MatcherType> Func,
268 StringRef MatcherName) {
Samuel Benzaquencf695902013-06-11 18:51:07 +0000269 return new FreeFuncMatcherCreateCallback(
270 &VariadicMatcherCreateCallback<BaseType, MatcherType>, MatcherName);
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000271}
272
273} // namespace internal
274} // namespace dynamic
275} // namespace ast_matchers
276} // namespace clang
277
278#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H