blob: abd5d402f1590db9263f4b4e3c187170a95a9c83 [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"
Samuel Benzaquen0239b692013-08-13 14:54:51 +000029#include "llvm/ADT/STLExtras.h"
Manuel Klimek24db0f02013-05-14 09:13:00 +000030#include "llvm/Support/type_traits.h"
31
32namespace clang {
33namespace ast_matchers {
34namespace dynamic {
35
36namespace internal {
37
38/// \brief Helper template class to just from argument type to the right is/get
39/// functions in VariantValue.
40/// Used to verify and extract the matcher arguments below.
41template <class T> struct ArgTypeTraits;
42template <class T> struct ArgTypeTraits<const T &> : public ArgTypeTraits<T> {
43};
44
45template <> struct ArgTypeTraits<std::string> {
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000046 static StringRef asString() { return "String"; }
Manuel Klimek24db0f02013-05-14 09:13:00 +000047 static bool is(const VariantValue &Value) { return Value.isString(); }
48 static const std::string &get(const VariantValue &Value) {
49 return Value.getString();
50 }
51};
52
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +000053template <>
54struct ArgTypeTraits<StringRef> : public ArgTypeTraits<std::string> {
55};
56
Manuel Klimek24db0f02013-05-14 09:13:00 +000057template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > {
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000058 static std::string asString() {
59 return (Twine("Matcher<") +
60 ast_type_traits::ASTNodeKind::getFromNodeKind<T>().asStringRef() +
61 ">").str();
62 }
63 static bool is(const VariantValue &Value) {
64 return Value.hasTypedMatcher<T>();
65 }
Manuel Klimek24db0f02013-05-14 09:13:00 +000066 static ast_matchers::internal::Matcher<T> get(const VariantValue &Value) {
67 return Value.getTypedMatcher<T>();
68 }
Samuel Benzaquenc31b3522013-06-04 15:46:22 +000069};
Manuel Klimek24db0f02013-05-14 09:13:00 +000070
Samuel Benzaquenc31b3522013-06-04 15:46:22 +000071template <> struct ArgTypeTraits<unsigned> {
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000072 static std::string asString() { return "Unsigned"; }
Samuel Benzaquenc31b3522013-06-04 15:46:22 +000073 static bool is(const VariantValue &Value) { return Value.isUnsigned(); }
74 static unsigned get(const VariantValue &Value) {
75 return Value.getUnsigned();
76 }
Manuel Klimek24db0f02013-05-14 09:13:00 +000077};
78
79/// \brief Generic MatcherCreate interface.
80///
81/// Provides a \c run() method that constructs the matcher from the provided
82/// arguments.
83class MatcherCreateCallback {
84public:
85 virtual ~MatcherCreateCallback() {}
Samuel Benzaquen0239b692013-08-13 14:54:51 +000086 virtual VariantMatcher run(const SourceRange &NameRange,
87 ArrayRef<ParserValue> Args,
88 Diagnostics *Error) const = 0;
Manuel Klimek24db0f02013-05-14 09:13:00 +000089};
90
91/// \brief Simple callback implementation. Marshaller and function are provided.
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +000092///
93/// This class wraps a function of arbitrary signature and a marshaller
94/// function into a MatcherCreateCallback.
95/// The marshaller is in charge of taking the VariantValue arguments, checking
96/// their types, unpacking them and calling the underlying function.
97template <typename FuncType>
Manuel Klimek24db0f02013-05-14 09:13:00 +000098class FixedArgCountMatcherCreateCallback : public MatcherCreateCallback {
99public:
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000100 /// FIXME: Use void(*)() as FuncType on this interface to remove the template
101 /// argument of this class. The marshaller can cast the function pointer back
102 /// to the original type.
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000103 typedef VariantMatcher (*MarshallerType)(FuncType, StringRef,
104 const SourceRange &,
105 ArrayRef<ParserValue>,
106 Diagnostics *);
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000107
Dmitri Gribenkocb63baf2013-05-17 17:50:16 +0000108 /// \param Marshaller Function to unpack the arguments and call \c Func
109 /// \param Func Matcher construct function. This is the function that
110 /// compile-time matcher expressions would use to create the matcher.
Manuel Klimek24db0f02013-05-14 09:13:00 +0000111 FixedArgCountMatcherCreateCallback(MarshallerType Marshaller, FuncType Func,
112 StringRef MatcherName)
113 : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName.str()) {}
114
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000115 VariantMatcher run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
116 Diagnostics *Error) const {
Manuel Klimek24db0f02013-05-14 09:13:00 +0000117 return Marshaller(Func, MatcherName, NameRange, Args, Error);
118 }
119
120private:
121 const MarshallerType Marshaller;
122 const FuncType Func;
123 const std::string MatcherName;
124};
125
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000126/// \brief Simple callback implementation. Free function is wrapped.
127///
128/// This class simply wraps a free function with the right signature to export
129/// it as a MatcherCreateCallback.
130/// This allows us to have one implementation of the interface for as many free
131/// functions as we want, reducing the number of symbols and size of the
132/// object file.
133class FreeFuncMatcherCreateCallback : public MatcherCreateCallback {
134public:
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000135 typedef VariantMatcher (*RunFunc)(StringRef MatcherName,
136 const SourceRange &NameRange,
137 ArrayRef<ParserValue> Args,
138 Diagnostics *Error);
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000139
140 FreeFuncMatcherCreateCallback(RunFunc Func, StringRef MatcherName)
141 : Func(Func), MatcherName(MatcherName.str()) {}
142
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000143 VariantMatcher run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
144 Diagnostics *Error) const {
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000145 return Func(MatcherName, NameRange, Args, Error);
146 }
147
148private:
149 const RunFunc Func;
150 const std::string MatcherName;
151};
Manuel Klimek24db0f02013-05-14 09:13:00 +0000152
153/// \brief Helper macros to check the arguments on all marshaller functions.
154#define CHECK_ARG_COUNT(count) \
155 if (Args.size() != count) { \
Samuel Benzaquena37bb8c2013-07-18 19:47:59 +0000156 Error->addError(NameRange, Error->ET_RegistryWrongArgCount) \
Manuel Klimek24db0f02013-05-14 09:13:00 +0000157 << count << Args.size(); \
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000158 return VariantMatcher(); \
Manuel Klimek24db0f02013-05-14 09:13:00 +0000159 }
160
161#define CHECK_ARG_TYPE(index, type) \
162 if (!ArgTypeTraits<type>::is(Args[index].Value)) { \
Samuel Benzaquena37bb8c2013-07-18 19:47:59 +0000163 Error->addError(Args[index].Range, Error->ET_RegistryWrongArgType) \
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000164 << (index + 1) << ArgTypeTraits<type>::asString() \
165 << Args[index].Value.getTypeAsString(); \
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000166 return VariantMatcher(); \
Manuel Klimek24db0f02013-05-14 09:13:00 +0000167 }
168
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000169/// \brief Helper methods to extract and merge all possible typed matchers
170/// out of the polymorphic object.
171template <class PolyMatcher>
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000172static void mergePolyMatchers(const PolyMatcher &Poly,
173 std::vector<const DynTypedMatcher *> &Out,
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000174 ast_matchers::internal::EmptyTypeList) {}
175
176template <class PolyMatcher, class TypeList>
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000177static void mergePolyMatchers(const PolyMatcher &Poly,
178 std::vector<const DynTypedMatcher *> &Out,
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000179 TypeList) {
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000180 Out.push_back(ast_matchers::internal::Matcher<typename TypeList::head>(Poly)
181 .clone());
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000182 mergePolyMatchers(Poly, Out, typename TypeList::tail());
183}
184
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000185/// \brief Convert the return values of the functions into a VariantMatcher.
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000186///
187/// There are 2 cases right now: The return value is a Matcher<T> or is a
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000188/// polymorphic matcher. For the former, we just construct the VariantMatcher.
189/// For the latter, we instantiate all the possible Matcher<T> of the poly
190/// matcher.
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000191template <typename T>
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000192static VariantMatcher
193outvalueToVariantMatcher(const ast_matchers::internal::Matcher<T> &Matcher) {
194 return VariantMatcher::SingleMatcher(Matcher);
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000195}
196
197template <typename T>
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000198static VariantMatcher outvalueToVariantMatcher(const T &PolyMatcher,
199 typename T::ReturnTypes * =
200 NULL) {
201 std::vector<const DynTypedMatcher *> Matchers;
202 mergePolyMatchers(PolyMatcher, Matchers, typename T::ReturnTypes());
203 VariantMatcher Out = VariantMatcher::PolymorphicMatcher(Matchers);
204 llvm::DeleteContainerPointers(Matchers);
205 return Out;
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000206}
207
Manuel Klimek24db0f02013-05-14 09:13:00 +0000208/// \brief 0-arg marshaller function.
209template <typename ReturnType>
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000210static VariantMatcher
211matcherMarshall0(ReturnType (*Func)(), StringRef MatcherName,
212 const SourceRange &NameRange, ArrayRef<ParserValue> Args,
213 Diagnostics *Error) {
Manuel Klimek24db0f02013-05-14 09:13:00 +0000214 CHECK_ARG_COUNT(0);
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000215 return outvalueToVariantMatcher(Func());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000216}
217
218/// \brief 1-arg marshaller function.
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000219template <typename ReturnType, typename ArgType1>
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000220static VariantMatcher
221matcherMarshall1(ReturnType (*Func)(ArgType1), StringRef MatcherName,
222 const SourceRange &NameRange, ArrayRef<ParserValue> Args,
223 Diagnostics *Error) {
Manuel Klimek24db0f02013-05-14 09:13:00 +0000224 CHECK_ARG_COUNT(1);
225 CHECK_ARG_TYPE(0, ArgType1);
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000226 return outvalueToVariantMatcher(
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000227 Func(ArgTypeTraits<ArgType1>::get(Args[0].Value)));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000228}
229
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000230/// \brief 2-arg marshaller function.
231template <typename ReturnType, typename ArgType1, typename ArgType2>
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000232static VariantMatcher
233matcherMarshall2(ReturnType (*Func)(ArgType1, ArgType2), StringRef MatcherName,
234 const SourceRange &NameRange, ArrayRef<ParserValue> Args,
235 Diagnostics *Error) {
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000236 CHECK_ARG_COUNT(2);
237 CHECK_ARG_TYPE(0, ArgType1);
238 CHECK_ARG_TYPE(1, ArgType2);
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000239 return outvalueToVariantMatcher(
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000240 Func(ArgTypeTraits<ArgType1>::get(Args[0].Value),
241 ArgTypeTraits<ArgType2>::get(Args[1].Value)));
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000242}
243
Manuel Klimek24db0f02013-05-14 09:13:00 +0000244#undef CHECK_ARG_COUNT
245#undef CHECK_ARG_TYPE
246
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000247/// \brief Variadic marshaller function.
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000248template <typename ResultT, typename ArgT,
249 ResultT (*Func)(ArrayRef<const ArgT *>)>
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000250VariantMatcher
251variadicMatcherCreateCallback(StringRef MatcherName,
252 const SourceRange &NameRange,
253 ArrayRef<ParserValue> Args, Diagnostics *Error) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000254 ArgT **InnerArgs = new ArgT *[Args.size()]();
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000255
256 bool HasError = false;
257 for (size_t i = 0, e = Args.size(); i != e; ++i) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000258 typedef ArgTypeTraits<ArgT> ArgTraits;
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000259 const ParserValue &Arg = Args[i];
260 const VariantValue &Value = Arg.Value;
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000261 if (!ArgTraits::is(Value)) {
Samuel Benzaquena37bb8c2013-07-18 19:47:59 +0000262 Error->addError(Arg.Range, Error->ET_RegistryWrongArgType)
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000263 << (i + 1) << ArgTraits::asString() << Value.getTypeAsString();
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000264 HasError = true;
265 break;
266 }
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000267 InnerArgs[i] = new ArgT(ArgTraits::get(Value));
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000268 }
269
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000270 VariantMatcher Out;
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000271 if (!HasError) {
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000272 Out = outvalueToVariantMatcher(
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000273 Func(ArrayRef<const ArgT *>(InnerArgs, Args.size())));
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000274 }
275
276 for (size_t i = 0, e = Args.size(); i != e; ++i) {
277 delete InnerArgs[i];
278 }
279 delete[] InnerArgs;
280 return Out;
281}
282
Manuel Klimek24db0f02013-05-14 09:13:00 +0000283/// Helper functions to select the appropriate marshaller functions.
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000284/// They detect the number of arguments, arguments types and return type.
Manuel Klimek24db0f02013-05-14 09:13:00 +0000285
286/// \brief 0-arg overload
287template <typename ReturnType>
288MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(),
289 StringRef MatcherName) {
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000290 return new FixedArgCountMatcherCreateCallback<ReturnType (*)()>(
291 matcherMarshall0, Func, MatcherName);
Manuel Klimek24db0f02013-05-14 09:13:00 +0000292}
293
294/// \brief 1-arg overload
295template <typename ReturnType, typename ArgType1>
296MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1),
297 StringRef MatcherName) {
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000298 return new FixedArgCountMatcherCreateCallback<ReturnType (*)(ArgType1)>(
299 matcherMarshall1, Func, MatcherName);
Manuel Klimek24db0f02013-05-14 09:13:00 +0000300}
301
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000302/// \brief 2-arg overload
303template <typename ReturnType, typename ArgType1, typename ArgType2>
304MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1,
305 ArgType2),
306 StringRef MatcherName) {
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000307 return new FixedArgCountMatcherCreateCallback<
308 ReturnType (*)(ArgType1, ArgType2)>(matcherMarshall2, Func, MatcherName);
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000309}
310
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000311/// \brief Variadic overload.
312template <typename ResultT, typename ArgT,
313 ResultT (*Func)(ArrayRef<const ArgT *>)>
Manuel Klimek24db0f02013-05-14 09:13:00 +0000314MatcherCreateCallback *
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000315makeMatcherAutoMarshall(llvm::VariadicFunction<ResultT, ArgT, Func> VarFunc,
Manuel Klimek24db0f02013-05-14 09:13:00 +0000316 StringRef MatcherName) {
Samuel Benzaquenb5dd69f2013-06-11 18:51:07 +0000317 return new FreeFuncMatcherCreateCallback(
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000318 &variadicMatcherCreateCallback<ResultT, ArgT, Func>, MatcherName);
Manuel Klimek24db0f02013-05-14 09:13:00 +0000319}
320
321} // namespace internal
322} // namespace dynamic
323} // namespace ast_matchers
324} // namespace clang
325
326#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H