blob: aceddc987fea28f6ba11f6782176beef580c113f [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
52template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > {
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000053 static std::string asString() {
54 return (Twine("Matcher<") +
55 ast_type_traits::ASTNodeKind::getFromNodeKind<T>().asStringRef() +
56 ">").str();
57 }
58 static bool is(const VariantValue &Value) {
59 return Value.hasTypedMatcher<T>();
60 }
Manuel Klimek24db0f02013-05-14 09:13:00 +000061 static ast_matchers::internal::Matcher<T> get(const VariantValue &Value) {
62 return Value.getTypedMatcher<T>();
63 }
Samuel Benzaquenc31b3522013-06-04 15:46:22 +000064};
Manuel Klimek24db0f02013-05-14 09:13:00 +000065
Samuel Benzaquenc31b3522013-06-04 15:46:22 +000066template <> struct ArgTypeTraits<unsigned> {
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000067 static std::string asString() { return "Unsigned"; }
Samuel Benzaquenc31b3522013-06-04 15:46:22 +000068 static bool is(const VariantValue &Value) { return Value.isUnsigned(); }
69 static unsigned get(const VariantValue &Value) {
70 return Value.getUnsigned();
71 }
Manuel Klimek24db0f02013-05-14 09:13:00 +000072};
73
74/// \brief Generic MatcherCreate interface.
75///
76/// Provides a \c run() method that constructs the matcher from the provided
77/// arguments.
78class MatcherCreateCallback {
79public:
80 virtual ~MatcherCreateCallback() {}
81 virtual DynTypedMatcher *run(const SourceRange &NameRange,
82 ArrayRef<ParserValue> Args,
83 Diagnostics *Error) const = 0;
84};
85
86/// \brief Simple callback implementation. Marshaller and function are provided.
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +000087///
88/// This class wraps a function of arbitrary signature and a marshaller
89/// function into a MatcherCreateCallback.
90/// The marshaller is in charge of taking the VariantValue arguments, checking
91/// their types, unpacking them and calling the underlying function.
92template <typename FuncType>
Manuel Klimek24db0f02013-05-14 09:13:00 +000093class FixedArgCountMatcherCreateCallback : public MatcherCreateCallback {
94public:
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +000095 /// FIXME: Use void(*)() as FuncType on this interface to remove the template
96 /// argument of this class. The marshaller can cast the function pointer back
97 /// to the original type.
98 typedef DynTypedMatcher *(*MarshallerType)(FuncType, StringRef,
99 const SourceRange &,
100 ArrayRef<ParserValue>,
101 Diagnostics *);
102
Dmitri Gribenkocb63baf2013-05-17 17:50:16 +0000103 /// \param Marshaller Function to unpack the arguments and call \c Func
104 /// \param Func Matcher construct function. This is the function that
105 /// compile-time matcher expressions would use to create the matcher.
Manuel Klimek24db0f02013-05-14 09:13:00 +0000106 FixedArgCountMatcherCreateCallback(MarshallerType Marshaller, FuncType Func,
107 StringRef MatcherName)
108 : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName.str()) {}
109
110 DynTypedMatcher *run(const SourceRange &NameRange,
111 ArrayRef<ParserValue> Args, Diagnostics *Error) const {
112 return Marshaller(Func, MatcherName, NameRange, Args, Error);
113 }
114
115private:
116 const MarshallerType Marshaller;
117 const FuncType Func;
118 const std::string MatcherName;
119};
120
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000121/// \brief Simple callback implementation. Free function is wrapped.
122///
123/// This class simply wraps a free function with the right signature to export
124/// it as a MatcherCreateCallback.
125/// This allows us to have one implementation of the interface for as many free
126/// functions as we want, reducing the number of symbols and size of the
127/// object file.
128class FreeFuncMatcherCreateCallback : public MatcherCreateCallback {
129public:
130 typedef DynTypedMatcher *(*RunFunc)(StringRef MatcherName,
131 const SourceRange &NameRange,
132 ArrayRef<ParserValue> Args,
133 Diagnostics *Error);
134
135 FreeFuncMatcherCreateCallback(RunFunc Func, StringRef MatcherName)
136 : Func(Func), MatcherName(MatcherName.str()) {}
137
138 DynTypedMatcher *run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
139 Diagnostics *Error) const {
140 return Func(MatcherName, NameRange, Args, Error);
141 }
142
143private:
144 const RunFunc Func;
145 const std::string MatcherName;
146};
Manuel Klimek24db0f02013-05-14 09:13:00 +0000147
148/// \brief Helper macros to check the arguments on all marshaller functions.
149#define CHECK_ARG_COUNT(count) \
150 if (Args.size() != count) { \
151 Error->pushErrorFrame(NameRange, Error->ET_RegistryWrongArgCount) \
152 << count << Args.size(); \
153 return NULL; \
154 }
155
156#define CHECK_ARG_TYPE(index, type) \
157 if (!ArgTypeTraits<type>::is(Args[index].Value)) { \
158 Error->pushErrorFrame(Args[index].Range, Error->ET_RegistryWrongArgType) \
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000159 << (index + 1) << ArgTypeTraits<type>::asString() \
160 << Args[index].Value.getTypeAsString(); \
Manuel Klimek24db0f02013-05-14 09:13:00 +0000161 return NULL; \
162 }
163
Manuel Klimek24db0f02013-05-14 09:13:00 +0000164/// \brief 0-arg marshaller function.
165template <typename ReturnType>
166DynTypedMatcher *matcherMarshall0(ReturnType (*Func)(), StringRef MatcherName,
167 const SourceRange &NameRange,
168 ArrayRef<ParserValue> Args,
169 Diagnostics *Error) {
170 CHECK_ARG_COUNT(0);
171 return Func().clone();
172}
173
174/// \brief 1-arg marshaller function.
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000175template <typename ReturnType, typename ArgType1>
176DynTypedMatcher *matcherMarshall1(ReturnType (*Func)(ArgType1),
Manuel Klimek24db0f02013-05-14 09:13:00 +0000177 StringRef MatcherName,
178 const SourceRange &NameRange,
179 ArrayRef<ParserValue> Args,
180 Diagnostics *Error) {
Manuel Klimek24db0f02013-05-14 09:13:00 +0000181 CHECK_ARG_COUNT(1);
182 CHECK_ARG_TYPE(0, ArgType1);
183 return Func(ArgTypeTraits<ArgType1>::get(Args[0].Value)).clone();
184}
185
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000186/// \brief 2-arg marshaller function.
187template <typename ReturnType, typename ArgType1, typename ArgType2>
188DynTypedMatcher *matcherMarshall2(ReturnType (*Func)(ArgType1, ArgType2),
189 StringRef MatcherName,
190 const SourceRange &NameRange,
191 ArrayRef<ParserValue> Args,
192 Diagnostics *Error) {
193 CHECK_ARG_COUNT(2);
194 CHECK_ARG_TYPE(0, ArgType1);
195 CHECK_ARG_TYPE(1, ArgType2);
196 return Func(ArgTypeTraits<ArgType1>::get(Args[0].Value),
197 ArgTypeTraits<ArgType2>::get(Args[1].Value)).clone();
198}
199
Manuel Klimek24db0f02013-05-14 09:13:00 +0000200#undef CHECK_ARG_COUNT
201#undef CHECK_ARG_TYPE
202
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000203/// \brief Variadic marshaller function.
204template <typename BaseType, typename DerivedType>
205DynTypedMatcher *VariadicMatcherCreateCallback(StringRef MatcherName,
206 const SourceRange &NameRange,
207 ArrayRef<ParserValue> Args,
208 Diagnostics *Error) {
209 typedef ast_matchers::internal::Matcher<DerivedType> DerivedMatcherType;
210 DerivedMatcherType **InnerArgs = new DerivedMatcherType *[Args.size()]();
211
212 bool HasError = false;
213 for (size_t i = 0, e = Args.size(); i != e; ++i) {
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000214 typedef ArgTypeTraits<DerivedMatcherType> DerivedTraits;
215 const ParserValue &Arg = Args[i];
216 const VariantValue &Value = Arg.Value;
217 if (!DerivedTraits::is(Value)) {
218 Error->pushErrorFrame(Arg.Range, Error->ET_RegistryWrongArgType)
219 << (i + 1) << DerivedTraits::asString() << Value.getTypeAsString();
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000220 HasError = true;
221 break;
222 }
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000223 InnerArgs[i] = new DerivedMatcherType(DerivedTraits::get(Value));
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000224 }
225
226 DynTypedMatcher *Out = NULL;
227 if (!HasError) {
228 Out = ast_matchers::internal::makeDynCastAllOfComposite<BaseType>(
229 ArrayRef<const DerivedMatcherType *>(InnerArgs, Args.size())).clone();
230 }
231
232 for (size_t i = 0, e = Args.size(); i != e; ++i) {
233 delete InnerArgs[i];
234 }
235 delete[] InnerArgs;
236 return Out;
237}
238
Manuel Klimek24db0f02013-05-14 09:13:00 +0000239/// Helper functions to select the appropriate marshaller functions.
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000240/// They detect the number of arguments, arguments types and return type.
Manuel Klimek24db0f02013-05-14 09:13:00 +0000241
242/// \brief 0-arg overload
243template <typename ReturnType>
244MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(),
245 StringRef MatcherName) {
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000246 return new FixedArgCountMatcherCreateCallback<ReturnType (*)()>(
247 matcherMarshall0, Func, MatcherName);
Manuel Klimek24db0f02013-05-14 09:13:00 +0000248}
249
250/// \brief 1-arg overload
251template <typename ReturnType, typename ArgType1>
252MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1),
253 StringRef MatcherName) {
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000254 return new FixedArgCountMatcherCreateCallback<ReturnType (*)(ArgType1)>(
255 matcherMarshall1, Func, MatcherName);
Manuel Klimek24db0f02013-05-14 09:13:00 +0000256}
257
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000258/// \brief 2-arg overload
259template <typename ReturnType, typename ArgType1, typename ArgType2>
260MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1,
261 ArgType2),
262 StringRef MatcherName) {
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000263 return new FixedArgCountMatcherCreateCallback<
264 ReturnType (*)(ArgType1, ArgType2)>(matcherMarshall2, Func, MatcherName);
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000265}
266
Manuel Klimek24db0f02013-05-14 09:13:00 +0000267/// \brief Variadic overload.
268template <typename MatcherType>
269MatcherCreateCallback *makeMatcherAutoMarshall(
270 ast_matchers::internal::VariadicAllOfMatcher<MatcherType> Func,
271 StringRef MatcherName) {
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000272 return new FreeFuncMatcherCreateCallback(
273 &VariadicMatcherCreateCallback<MatcherType, MatcherType>, MatcherName);
Manuel Klimek24db0f02013-05-14 09:13:00 +0000274}
275
276template <typename BaseType, typename MatcherType>
277MatcherCreateCallback *
278makeMatcherAutoMarshall(ast_matchers::internal::VariadicDynCastAllOfMatcher<
279 BaseType, MatcherType> Func,
280 StringRef MatcherName) {
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000281 return new FreeFuncMatcherCreateCallback(
282 &VariadicMatcherCreateCallback<BaseType, MatcherType>, MatcherName);
Manuel Klimek24db0f02013-05-14 09:13:00 +0000283}
284
285} // namespace internal
286} // namespace dynamic
287} // namespace ast_matchers
288} // namespace clang
289
290#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H