blob: 2cc5f7cdaa4ed684eac67f52bd468fa38d3f9d3e [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
23#include <list>
24#include <string>
25#include <vector>
26
27#include "clang/ASTMatchers/ASTMatchers.h"
28#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
29#include "clang/ASTMatchers/Dynamic/VariantValue.h"
30#include "clang/Basic/LLVM.h"
31#include "llvm/Support/type_traits.h"
32
33namespace clang {
34namespace ast_matchers {
35namespace dynamic {
36
37namespace internal {
38
39/// \brief Helper template class to just from argument type to the right is/get
40/// functions in VariantValue.
41/// Used to verify and extract the matcher arguments below.
42template <class T> struct ArgTypeTraits;
43template <class T> struct ArgTypeTraits<const T &> : public ArgTypeTraits<T> {
44};
45
46template <> struct ArgTypeTraits<std::string> {
47 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
53template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > {
54 static bool is(const VariantValue &Value) { return Value.isMatcher(); }
55 static ast_matchers::internal::Matcher<T> get(const VariantValue &Value) {
56 return Value.getTypedMatcher<T>();
57 }
Samuel Benzaquen7a337af2013-06-04 15:46:22 +000058};
Manuel Klimekf7f295f2013-05-14 09:13:00 +000059
Samuel Benzaquen7a337af2013-06-04 15:46:22 +000060template <> struct ArgTypeTraits<unsigned> {
61 static bool is(const VariantValue &Value) { return Value.isUnsigned(); }
62 static unsigned get(const VariantValue &Value) {
63 return Value.getUnsigned();
64 }
Manuel Klimekf7f295f2013-05-14 09:13:00 +000065};
66
67/// \brief Generic MatcherCreate interface.
68///
69/// Provides a \c run() method that constructs the matcher from the provided
70/// arguments.
71class MatcherCreateCallback {
72public:
73 virtual ~MatcherCreateCallback() {}
74 virtual DynTypedMatcher *run(const SourceRange &NameRange,
75 ArrayRef<ParserValue> Args,
76 Diagnostics *Error) const = 0;
77};
78
79/// \brief Simple callback implementation. Marshaller and function are provided.
Manuel Klimekf7f295f2013-05-14 09:13:00 +000080template <typename MarshallerType, typename FuncType>
81class FixedArgCountMatcherCreateCallback : public MatcherCreateCallback {
82public:
Dmitri Gribenkoe3c63fc2013-05-17 17:50:16 +000083 /// \param Marshaller Function to unpack the arguments and call \c Func
84 /// \param Func Matcher construct function. This is the function that
85 /// compile-time matcher expressions would use to create the matcher.
Manuel Klimekf7f295f2013-05-14 09:13:00 +000086 FixedArgCountMatcherCreateCallback(MarshallerType Marshaller, FuncType Func,
87 StringRef MatcherName)
88 : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName.str()) {}
89
90 DynTypedMatcher *run(const SourceRange &NameRange,
91 ArrayRef<ParserValue> Args, Diagnostics *Error) const {
92 return Marshaller(Func, MatcherName, NameRange, Args, Error);
93 }
94
95private:
96 const MarshallerType Marshaller;
97 const FuncType Func;
98 const std::string MatcherName;
99};
100
101/// \brief Helper function to do template argument deduction.
102template <typename MarshallerType, typename FuncType>
103MatcherCreateCallback *
104createMarshallerCallback(MarshallerType Marshaller, FuncType Func,
105 StringRef MatcherName) {
106 return new FixedArgCountMatcherCreateCallback<MarshallerType, FuncType>(
107 Marshaller, Func, MatcherName);
108}
109
110/// \brief Helper macros to check the arguments on all marshaller functions.
111#define CHECK_ARG_COUNT(count) \
112 if (Args.size() != count) { \
113 Error->pushErrorFrame(NameRange, Error->ET_RegistryWrongArgCount) \
114 << count << Args.size(); \
115 return NULL; \
116 }
117
118#define CHECK_ARG_TYPE(index, type) \
119 if (!ArgTypeTraits<type>::is(Args[index].Value)) { \
120 Error->pushErrorFrame(Args[index].Range, Error->ET_RegistryWrongArgType) \
121 << MatcherName << (index + 1); \
122 return NULL; \
123 }
124
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000125/// \brief 0-arg marshaller function.
126template <typename ReturnType>
127DynTypedMatcher *matcherMarshall0(ReturnType (*Func)(), StringRef MatcherName,
128 const SourceRange &NameRange,
129 ArrayRef<ParserValue> Args,
130 Diagnostics *Error) {
131 CHECK_ARG_COUNT(0);
132 return Func().clone();
133}
134
135/// \brief 1-arg marshaller function.
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000136template <typename ReturnType, typename ArgType1>
137DynTypedMatcher *matcherMarshall1(ReturnType (*Func)(ArgType1),
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000138 StringRef MatcherName,
139 const SourceRange &NameRange,
140 ArrayRef<ParserValue> Args,
141 Diagnostics *Error) {
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000142 CHECK_ARG_COUNT(1);
143 CHECK_ARG_TYPE(0, ArgType1);
144 return Func(ArgTypeTraits<ArgType1>::get(Args[0].Value)).clone();
145}
146
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000147/// \brief 2-arg marshaller function.
148template <typename ReturnType, typename ArgType1, typename ArgType2>
149DynTypedMatcher *matcherMarshall2(ReturnType (*Func)(ArgType1, ArgType2),
150 StringRef MatcherName,
151 const SourceRange &NameRange,
152 ArrayRef<ParserValue> Args,
153 Diagnostics *Error) {
154 CHECK_ARG_COUNT(2);
155 CHECK_ARG_TYPE(0, ArgType1);
156 CHECK_ARG_TYPE(1, ArgType2);
157 return Func(ArgTypeTraits<ArgType1>::get(Args[0].Value),
158 ArgTypeTraits<ArgType2>::get(Args[1].Value)).clone();
159}
160
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000161/// \brief Variadic marshaller function.
162template <typename BaseType, typename DerivedType>
163class VariadicMatcherCreateCallback : public MatcherCreateCallback {
164public:
165 explicit VariadicMatcherCreateCallback(StringRef MatcherName)
166 : MatcherName(MatcherName.str()) {}
167
168 typedef ast_matchers::internal::Matcher<DerivedType> DerivedMatcherType;
169
170 DynTypedMatcher *run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
171 Diagnostics *Error) const {
172 std::list<DerivedMatcherType> References;
173 std::vector<const DerivedMatcherType *> InnerArgs(Args.size());
174 for (size_t i = 0, e = Args.size(); i != e; ++i) {
175 CHECK_ARG_TYPE(i, DerivedMatcherType);
176 References.push_back(
177 ArgTypeTraits<DerivedMatcherType>::get(Args[i].Value));
178 InnerArgs[i] = &References.back();
179 }
180 return ast_matchers::internal::makeDynCastAllOfComposite<BaseType>(
181 ArrayRef<const DerivedMatcherType *>(InnerArgs)).clone();
182 }
183
184private:
185 const std::string MatcherName;
186};
187
188#undef CHECK_ARG_COUNT
189#undef CHECK_ARG_TYPE
190
191/// Helper functions to select the appropriate marshaller functions.
192/// They detects the number of arguments, arguments types and return type.
193
194/// \brief 0-arg overload
195template <typename ReturnType>
196MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(),
197 StringRef MatcherName) {
198 return createMarshallerCallback(matcherMarshall0<ReturnType>, Func,
199 MatcherName);
200}
201
202/// \brief 1-arg overload
203template <typename ReturnType, typename ArgType1>
204MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1),
205 StringRef MatcherName) {
206 return createMarshallerCallback(matcherMarshall1<ReturnType, ArgType1>, Func,
207 MatcherName);
208}
209
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000210/// \brief 2-arg overload
211template <typename ReturnType, typename ArgType1, typename ArgType2>
212MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1,
213 ArgType2),
214 StringRef MatcherName) {
215 return createMarshallerCallback(
216 matcherMarshall2<ReturnType, ArgType1, ArgType2>, Func, MatcherName);
217}
218
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000219/// \brief Variadic overload.
220template <typename MatcherType>
221MatcherCreateCallback *makeMatcherAutoMarshall(
222 ast_matchers::internal::VariadicAllOfMatcher<MatcherType> Func,
223 StringRef MatcherName) {
224 return new VariadicMatcherCreateCallback<MatcherType, MatcherType>(
225 MatcherName);
226}
227
228template <typename BaseType, typename MatcherType>
229MatcherCreateCallback *
230makeMatcherAutoMarshall(ast_matchers::internal::VariadicDynCastAllOfMatcher<
231 BaseType, MatcherType> Func,
232 StringRef MatcherName) {
233 return new VariadicMatcherCreateCallback<BaseType, MatcherType>(MatcherName);
234}
235
236} // namespace internal
237} // namespace dynamic
238} // namespace ast_matchers
239} // namespace clang
240
241#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H