blob: a41ed249983209577391cd8c80dd9d56afe4fe63 [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 }
58
59};
60
61/// \brief Generic MatcherCreate interface.
62///
63/// Provides a \c run() method that constructs the matcher from the provided
64/// arguments.
65class MatcherCreateCallback {
66public:
67 virtual ~MatcherCreateCallback() {}
68 virtual DynTypedMatcher *run(const SourceRange &NameRange,
69 ArrayRef<ParserValue> Args,
70 Diagnostics *Error) const = 0;
71};
72
73/// \brief Simple callback implementation. Marshaller and function are provided.
Manuel Klimekf7f295f2013-05-14 09:13:00 +000074template <typename MarshallerType, typename FuncType>
75class FixedArgCountMatcherCreateCallback : public MatcherCreateCallback {
76public:
Dmitri Gribenkoe3c63fc2013-05-17 17:50:16 +000077 /// \param Marshaller Function to unpack the arguments and call \c Func
78 /// \param Func Matcher construct function. This is the function that
79 /// compile-time matcher expressions would use to create the matcher.
Manuel Klimekf7f295f2013-05-14 09:13:00 +000080 FixedArgCountMatcherCreateCallback(MarshallerType Marshaller, FuncType Func,
81 StringRef MatcherName)
82 : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName.str()) {}
83
84 DynTypedMatcher *run(const SourceRange &NameRange,
85 ArrayRef<ParserValue> Args, Diagnostics *Error) const {
86 return Marshaller(Func, MatcherName, NameRange, Args, Error);
87 }
88
89private:
90 const MarshallerType Marshaller;
91 const FuncType Func;
92 const std::string MatcherName;
93};
94
95/// \brief Helper function to do template argument deduction.
96template <typename MarshallerType, typename FuncType>
97MatcherCreateCallback *
98createMarshallerCallback(MarshallerType Marshaller, FuncType Func,
99 StringRef MatcherName) {
100 return new FixedArgCountMatcherCreateCallback<MarshallerType, FuncType>(
101 Marshaller, Func, MatcherName);
102}
103
104/// \brief Helper macros to check the arguments on all marshaller functions.
105#define CHECK_ARG_COUNT(count) \
106 if (Args.size() != count) { \
107 Error->pushErrorFrame(NameRange, Error->ET_RegistryWrongArgCount) \
108 << count << Args.size(); \
109 return NULL; \
110 }
111
112#define CHECK_ARG_TYPE(index, type) \
113 if (!ArgTypeTraits<type>::is(Args[index].Value)) { \
114 Error->pushErrorFrame(Args[index].Range, Error->ET_RegistryWrongArgType) \
115 << MatcherName << (index + 1); \
116 return NULL; \
117 }
118
119/// \brief Metafunction to normalize argument types.
120///
121/// We need to remove the const& out of the function parameters to be able to
122/// find values on VariantValue.
123template <typename T>
124struct remove_const_ref :
125 public llvm::remove_const<typename llvm::remove_reference<T>::type> {
126};
127
128/// \brief 0-arg marshaller function.
129template <typename ReturnType>
130DynTypedMatcher *matcherMarshall0(ReturnType (*Func)(), StringRef MatcherName,
131 const SourceRange &NameRange,
132 ArrayRef<ParserValue> Args,
133 Diagnostics *Error) {
134 CHECK_ARG_COUNT(0);
135 return Func().clone();
136}
137
138/// \brief 1-arg marshaller function.
139template <typename ReturnType, typename InArgType1>
140DynTypedMatcher *matcherMarshall1(ReturnType (*Func)(InArgType1),
141 StringRef MatcherName,
142 const SourceRange &NameRange,
143 ArrayRef<ParserValue> Args,
144 Diagnostics *Error) {
145 typedef typename remove_const_ref<InArgType1>::type ArgType1;
146 CHECK_ARG_COUNT(1);
147 CHECK_ARG_TYPE(0, ArgType1);
148 return Func(ArgTypeTraits<ArgType1>::get(Args[0].Value)).clone();
149}
150
151/// \brief Variadic marshaller function.
152template <typename BaseType, typename DerivedType>
153class VariadicMatcherCreateCallback : public MatcherCreateCallback {
154public:
155 explicit VariadicMatcherCreateCallback(StringRef MatcherName)
156 : MatcherName(MatcherName.str()) {}
157
158 typedef ast_matchers::internal::Matcher<DerivedType> DerivedMatcherType;
159
160 DynTypedMatcher *run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
161 Diagnostics *Error) const {
162 std::list<DerivedMatcherType> References;
163 std::vector<const DerivedMatcherType *> InnerArgs(Args.size());
164 for (size_t i = 0, e = Args.size(); i != e; ++i) {
165 CHECK_ARG_TYPE(i, DerivedMatcherType);
166 References.push_back(
167 ArgTypeTraits<DerivedMatcherType>::get(Args[i].Value));
168 InnerArgs[i] = &References.back();
169 }
170 return ast_matchers::internal::makeDynCastAllOfComposite<BaseType>(
171 ArrayRef<const DerivedMatcherType *>(InnerArgs)).clone();
172 }
173
174private:
175 const std::string MatcherName;
176};
177
178#undef CHECK_ARG_COUNT
179#undef CHECK_ARG_TYPE
180
181/// Helper functions to select the appropriate marshaller functions.
182/// They detects the number of arguments, arguments types and return type.
183
184/// \brief 0-arg overload
185template <typename ReturnType>
186MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(),
187 StringRef MatcherName) {
188 return createMarshallerCallback(matcherMarshall0<ReturnType>, Func,
189 MatcherName);
190}
191
192/// \brief 1-arg overload
193template <typename ReturnType, typename ArgType1>
194MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1),
195 StringRef MatcherName) {
196 return createMarshallerCallback(matcherMarshall1<ReturnType, ArgType1>, Func,
197 MatcherName);
198}
199
200/// \brief Variadic overload.
201template <typename MatcherType>
202MatcherCreateCallback *makeMatcherAutoMarshall(
203 ast_matchers::internal::VariadicAllOfMatcher<MatcherType> Func,
204 StringRef MatcherName) {
205 return new VariadicMatcherCreateCallback<MatcherType, MatcherType>(
206 MatcherName);
207}
208
209template <typename BaseType, typename MatcherType>
210MatcherCreateCallback *
211makeMatcherAutoMarshall(ast_matchers::internal::VariadicDynCastAllOfMatcher<
212 BaseType, MatcherType> Func,
213 StringRef MatcherName) {
214 return new VariadicMatcherCreateCallback<BaseType, MatcherType>(MatcherName);
215}
216
217} // namespace internal
218} // namespace dynamic
219} // namespace ast_matchers
220} // namespace clang
221
222#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H