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