• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- 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 <string>
24 
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 
31 namespace clang {
32 namespace ast_matchers {
33 namespace dynamic {
34 
35 namespace 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.
40 template <class T> struct ArgTypeTraits;
41 template <class T> struct ArgTypeTraits<const T &> : public ArgTypeTraits<T> {
42 };
43 
44 template <> struct ArgTypeTraits<std::string> {
45   static StringRef asString() { return "String"; }
46   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 
52 template <>
53 struct ArgTypeTraits<StringRef> : public ArgTypeTraits<std::string> {
54 };
55 
56 template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > {
57   static std::string asString() {
58     return (Twine("Matcher<") +
59             ast_type_traits::ASTNodeKind::getFromNodeKind<T>().asStringRef() +
60             ">").str();
61   }
62   static bool is(const VariantValue &Value) {
63     return Value.hasTypedMatcher<T>();
64   }
65   static ast_matchers::internal::Matcher<T> get(const VariantValue &Value) {
66     return Value.getTypedMatcher<T>();
67   }
68 };
69 
70 template <> struct ArgTypeTraits<unsigned> {
71   static std::string asString() { return "Unsigned"; }
72   static bool is(const VariantValue &Value) { return Value.isUnsigned(); }
73   static unsigned get(const VariantValue &Value) {
74     return Value.getUnsigned();
75   }
76 };
77 
78 /// \brief Generic MatcherCreate interface.
79 ///
80 /// Provides a \c run() method that constructs the matcher from the provided
81 /// arguments.
82 class MatcherCreateCallback {
83 public:
84   virtual ~MatcherCreateCallback() {}
85   virtual MatcherList run(const SourceRange &NameRange,
86                           ArrayRef<ParserValue> Args,
87                           Diagnostics *Error) const = 0;
88 };
89 
90 /// \brief Simple callback implementation. Marshaller and function are provided.
91 ///
92 /// This class wraps a function of arbitrary signature and a marshaller
93 /// function into a MatcherCreateCallback.
94 /// The marshaller is in charge of taking the VariantValue arguments, checking
95 /// their types, unpacking them and calling the underlying function.
96 template <typename FuncType>
97 class FixedArgCountMatcherCreateCallback : public MatcherCreateCallback {
98 public:
99   /// FIXME: Use void(*)() as FuncType on this interface to remove the template
100   /// argument of this class. The marshaller can cast the function pointer back
101   /// to the original type.
102   typedef MatcherList (*MarshallerType)(FuncType, StringRef,
103                                         const SourceRange &,
104                                         ArrayRef<ParserValue>,
105                                         Diagnostics *);
106 
107   /// \param Marshaller Function to unpack the arguments and call \c Func
108   /// \param Func Matcher construct function. This is the function that
109   ///   compile-time matcher expressions would use to create the matcher.
110   FixedArgCountMatcherCreateCallback(MarshallerType Marshaller, FuncType Func,
111                                      StringRef MatcherName)
112       : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName.str()) {}
113 
114   MatcherList run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
115                   Diagnostics *Error) const {
116     return Marshaller(Func, MatcherName, NameRange, Args, Error);
117   }
118 
119 private:
120   const MarshallerType Marshaller;
121   const FuncType Func;
122   const std::string MatcherName;
123 };
124 
125 /// \brief Simple callback implementation. Free function is wrapped.
126 ///
127 /// This class simply wraps a free function with the right signature to export
128 /// it as a MatcherCreateCallback.
129 /// This allows us to have one implementation of the interface for as many free
130 /// functions as we want, reducing the number of symbols and size of the
131 /// object file.
132 class FreeFuncMatcherCreateCallback : public MatcherCreateCallback {
133 public:
134   typedef MatcherList (*RunFunc)(StringRef MatcherName,
135                                  const SourceRange &NameRange,
136                                  ArrayRef<ParserValue> Args,
137                                  Diagnostics *Error);
138 
139   FreeFuncMatcherCreateCallback(RunFunc Func, StringRef MatcherName)
140       : Func(Func), MatcherName(MatcherName.str()) {}
141 
142   MatcherList run(const SourceRange &NameRange, ArrayRef<ParserValue> Args,
143                   Diagnostics *Error) const {
144     return Func(MatcherName, NameRange, Args, Error);
145   }
146 
147 private:
148   const RunFunc Func;
149   const std::string MatcherName;
150 };
151 
152 /// \brief Helper macros to check the arguments on all marshaller functions.
153 #define CHECK_ARG_COUNT(count)                                                 \
154   if (Args.size() != count) {                                                  \
155     Error->addError(NameRange, Error->ET_RegistryWrongArgCount)                \
156         << count << Args.size();                                               \
157     return MatcherList();                                                      \
158   }
159 
160 #define CHECK_ARG_TYPE(index, type)                                            \
161   if (!ArgTypeTraits<type>::is(Args[index].Value)) {                           \
162     Error->addError(Args[index].Range, Error->ET_RegistryWrongArgType)         \
163         << (index + 1) << ArgTypeTraits<type>::asString()                      \
164         << Args[index].Value.getTypeAsString();                                \
165     return MatcherList();                                                      \
166   }
167 
168 /// \brief Helper methods to extract and merge all possible typed matchers
169 /// out of the polymorphic object.
170 template <class PolyMatcher>
171 static void mergePolyMatchers(const PolyMatcher &Poly, MatcherList *Out,
172                               ast_matchers::internal::EmptyTypeList) {}
173 
174 template <class PolyMatcher, class TypeList>
175 static void mergePolyMatchers(const PolyMatcher &Poly, MatcherList *Out,
176                               TypeList) {
177   Out->add(ast_matchers::internal::Matcher<typename TypeList::head>(Poly));
178   mergePolyMatchers(Poly, Out, typename TypeList::tail());
179 }
180 
181 /// \brief Convert the return values of the functions into a MatcherList.
182 ///
183 /// There are 2 cases right now: The return value is a Matcher<T> or is a
184 /// polymorphic matcher. For the former, we just construct the MatcherList. For
185 /// the latter, we instantiate all the possible Matcher<T> of the poly matcher.
186 template <typename T>
187 static MatcherList
188 outvalueToMatcherList(const ast_matchers::internal::Matcher<T> &Matcher) {
189   return MatcherList(Matcher);
190 }
191 
192 template <typename T>
193 static MatcherList
194 outvalueToMatcherList(const T& PolyMatcher, typename T::ReturnTypes* = NULL) {
195   MatcherList Matchers;
196   mergePolyMatchers(PolyMatcher, &Matchers, typename T::ReturnTypes());
197   return Matchers;
198 }
199 
200 /// \brief 0-arg marshaller function.
201 template <typename ReturnType>
202 static MatcherList matcherMarshall0(ReturnType (*Func)(),
203                                     StringRef MatcherName,
204                                     const SourceRange &NameRange,
205                                     ArrayRef<ParserValue> Args,
206                                     Diagnostics *Error) {
207   CHECK_ARG_COUNT(0);
208   return outvalueToMatcherList(Func());
209 }
210 
211 /// \brief 1-arg marshaller function.
212 template <typename ReturnType, typename ArgType1>
213 static MatcherList matcherMarshall1(ReturnType (*Func)(ArgType1),
214                                     StringRef MatcherName,
215                                     const SourceRange &NameRange,
216                                     ArrayRef<ParserValue> Args,
217                                     Diagnostics *Error) {
218   CHECK_ARG_COUNT(1);
219   CHECK_ARG_TYPE(0, ArgType1);
220   return outvalueToMatcherList(
221       Func(ArgTypeTraits<ArgType1>::get(Args[0].Value)));
222 }
223 
224 /// \brief 2-arg marshaller function.
225 template <typename ReturnType, typename ArgType1, typename ArgType2>
226 static MatcherList matcherMarshall2(ReturnType (*Func)(ArgType1, ArgType2),
227                                     StringRef MatcherName,
228                                     const SourceRange &NameRange,
229                                     ArrayRef<ParserValue> Args,
230                                     Diagnostics *Error) {
231   CHECK_ARG_COUNT(2);
232   CHECK_ARG_TYPE(0, ArgType1);
233   CHECK_ARG_TYPE(1, ArgType2);
234   return outvalueToMatcherList(
235       Func(ArgTypeTraits<ArgType1>::get(Args[0].Value),
236            ArgTypeTraits<ArgType2>::get(Args[1].Value)));
237 }
238 
239 #undef CHECK_ARG_COUNT
240 #undef CHECK_ARG_TYPE
241 
242 /// \brief Variadic marshaller function.
243 template <typename ResultT, typename ArgT,
244           ResultT (*Func)(ArrayRef<const ArgT *>)>
245 MatcherList variadicMatcherCreateCallback(StringRef MatcherName,
246                                           const SourceRange &NameRange,
247                                           ArrayRef<ParserValue> Args,
248                                           Diagnostics *Error) {
249   ArgT **InnerArgs = new ArgT *[Args.size()]();
250 
251   bool HasError = false;
252   for (size_t i = 0, e = Args.size(); i != e; ++i) {
253     typedef ArgTypeTraits<ArgT> ArgTraits;
254     const ParserValue &Arg = Args[i];
255     const VariantValue &Value = Arg.Value;
256     if (!ArgTraits::is(Value)) {
257       Error->addError(Arg.Range, Error->ET_RegistryWrongArgType)
258           << (i + 1) << ArgTraits::asString() << Value.getTypeAsString();
259       HasError = true;
260       break;
261     }
262     InnerArgs[i] = new ArgT(ArgTraits::get(Value));
263   }
264 
265   MatcherList Out;
266   if (!HasError) {
267     Out = outvalueToMatcherList(
268         Func(ArrayRef<const ArgT *>(InnerArgs, Args.size())));
269   }
270 
271   for (size_t i = 0, e = Args.size(); i != e; ++i) {
272     delete InnerArgs[i];
273   }
274   delete[] InnerArgs;
275   return Out;
276 }
277 
278 /// Helper functions to select the appropriate marshaller functions.
279 /// They detect the number of arguments, arguments types and return type.
280 
281 /// \brief 0-arg overload
282 template <typename ReturnType>
283 MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(),
284                                                StringRef MatcherName) {
285   return new FixedArgCountMatcherCreateCallback<ReturnType (*)()>(
286       matcherMarshall0, Func, MatcherName);
287 }
288 
289 /// \brief 1-arg overload
290 template <typename ReturnType, typename ArgType1>
291 MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1),
292                                                StringRef MatcherName) {
293   return new FixedArgCountMatcherCreateCallback<ReturnType (*)(ArgType1)>(
294       matcherMarshall1, Func, MatcherName);
295 }
296 
297 /// \brief 2-arg overload
298 template <typename ReturnType, typename ArgType1, typename ArgType2>
299 MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1,
300                                                                   ArgType2),
301                                                StringRef MatcherName) {
302   return new FixedArgCountMatcherCreateCallback<
303       ReturnType (*)(ArgType1, ArgType2)>(matcherMarshall2, Func, MatcherName);
304 }
305 
306 /// \brief Variadic overload.
307 template <typename ResultT, typename ArgT,
308           ResultT (*Func)(ArrayRef<const ArgT *>)>
309 MatcherCreateCallback *
310 makeMatcherAutoMarshall(llvm::VariadicFunction<ResultT, ArgT, Func> VarFunc,
311                         StringRef MatcherName) {
312   return new FreeFuncMatcherCreateCallback(
313       &variadicMatcherCreateCallback<ResultT, ArgT, Func>, MatcherName);
314 }
315 
316 }  // namespace internal
317 }  // namespace dynamic
318 }  // namespace ast_matchers
319 }  // namespace clang
320 
321 #endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H
322