Home | History | Annotate | Download | only in Dynamic
      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