diff options
Diffstat (limited to 'clang/lib/ASTMatchers/Dynamic/Marshallers.h')
| -rw-r--r-- | clang/lib/ASTMatchers/Dynamic/Marshallers.h | 822 | 
1 files changed, 822 insertions, 0 deletions
diff --git a/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/clang/lib/ASTMatchers/Dynamic/Marshallers.h new file mode 100644 index 000000000000..9f46108d1848 --- /dev/null +++ b/clang/lib/ASTMatchers/Dynamic/Marshallers.h @@ -0,0 +1,822 @@ +//===- Marshallers.h - Generic matcher function marshallers -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file +/// Functions templates and classes to wrap matcher construct functions. +/// +/// A collection of template function and classes that provide a generic +/// marshalling layer on top of matcher construct functions. +/// These are used by the registry to export all marshaller constructors with +/// the same generic interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_ASTMATCHERS_DYNAMIC_MARSHALLERS_H +#define LLVM_CLANG_LIB_ASTMATCHERS_DYNAMIC_MARSHALLERS_H + +#include "clang/AST/ASTTypeTraits.h" +#include "clang/AST/OperationKinds.h" +#include "clang/ASTMatchers/ASTMatchersInternal.h" +#include "clang/ASTMatchers/Dynamic/Diagnostics.h" +#include "clang/ASTMatchers/Dynamic/VariantValue.h" +#include "clang/Basic/AttrKinds.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/OpenMPKinds.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" +#include <cassert> +#include <cstddef> +#include <iterator> +#include <limits> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +namespace clang { +namespace ast_matchers { +namespace dynamic { +namespace internal { + +/// Helper template class to just from argument type to the right is/get +///   functions in VariantValue. +/// Used to verify and extract the matcher arguments below. +template <class T> struct ArgTypeTraits; +template <class T> struct ArgTypeTraits<const T &> : public ArgTypeTraits<T> { +}; + +template <> struct ArgTypeTraits<std::string> { +  static bool is(const VariantValue &Value) { return Value.isString(); } + +  static const std::string &get(const VariantValue &Value) { +    return Value.getString(); +  } + +  static ArgKind getKind() { +    return ArgKind(ArgKind::AK_String); +  } +}; + +template <> +struct ArgTypeTraits<StringRef> : public ArgTypeTraits<std::string> { +}; + +template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T>> { +  static bool is(const VariantValue &Value) { +    return Value.isMatcher() && Value.getMatcher().hasTypedMatcher<T>(); +  } + +  static ast_matchers::internal::Matcher<T> get(const VariantValue &Value) { +    return Value.getMatcher().getTypedMatcher<T>(); +  } + +  static ArgKind getKind() { +    return ArgKind(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); +  } +}; + +template <> struct ArgTypeTraits<bool> { +  static bool is(const VariantValue &Value) { return Value.isBoolean(); } + +  static bool get(const VariantValue &Value) { +    return Value.getBoolean(); +  } + +  static ArgKind getKind() { +    return ArgKind(ArgKind::AK_Boolean); +  } +}; + +template <> struct ArgTypeTraits<double> { +  static bool is(const VariantValue &Value) { return Value.isDouble(); } + +  static double get(const VariantValue &Value) { +    return Value.getDouble(); +  } + +  static ArgKind getKind() { +    return ArgKind(ArgKind::AK_Double); +  } +}; + +template <> struct ArgTypeTraits<unsigned> { +  static bool is(const VariantValue &Value) { return Value.isUnsigned(); } + +  static unsigned get(const VariantValue &Value) { +    return Value.getUnsigned(); +  } + +  static ArgKind getKind() { +    return ArgKind(ArgKind::AK_Unsigned); +  } +}; + +template <> struct ArgTypeTraits<attr::Kind> { +private: +  static Optional<attr::Kind> getAttrKind(llvm::StringRef AttrKind) { +    return llvm::StringSwitch<Optional<attr::Kind>>(AttrKind) +#define ATTR(X) .Case("attr::" #X, attr:: X) +#include "clang/Basic/AttrList.inc" +        .Default(llvm::None); +  } + +public: +  static bool is(const VariantValue &Value) { +    return Value.isString() && getAttrKind(Value.getString()); +  } + +  static attr::Kind get(const VariantValue &Value) { +    return *getAttrKind(Value.getString()); +  } + +  static ArgKind getKind() { +    return ArgKind(ArgKind::AK_String); +  } +}; + +template <> struct ArgTypeTraits<CastKind> { +private: +  static Optional<CastKind> getCastKind(llvm::StringRef AttrKind) { +    return llvm::StringSwitch<Optional<CastKind>>(AttrKind) +#define CAST_OPERATION(Name) .Case( #Name, CK_##Name) +#include "clang/AST/OperationKinds.def" +        .Default(llvm::None); +  } + +public: +  static bool is(const VariantValue &Value) { +    return Value.isString() && getCastKind(Value.getString()); +  } + +  static CastKind get(const VariantValue &Value) { +    return *getCastKind(Value.getString()); +  } + +  static ArgKind getKind() { +    return ArgKind(ArgKind::AK_String); +  } +}; + +template <> struct ArgTypeTraits<OpenMPClauseKind> { +private: +  static Optional<OpenMPClauseKind> getClauseKind(llvm::StringRef ClauseKind) { +    return llvm::StringSwitch<Optional<OpenMPClauseKind>>(ClauseKind) +#define OPENMP_CLAUSE(TextualSpelling, Class)                                  \ +  .Case("OMPC_" #TextualSpelling, OMPC_##TextualSpelling) +#include "clang/Basic/OpenMPKinds.def" +        .Default(llvm::None); +  } + +public: +  static bool is(const VariantValue &Value) { +    return Value.isString() && getClauseKind(Value.getString()); +  } + +  static OpenMPClauseKind get(const VariantValue &Value) { +    return *getClauseKind(Value.getString()); +  } + +  static ArgKind getKind() { return ArgKind(ArgKind::AK_String); } +}; + +/// Matcher descriptor interface. +/// +/// Provides a \c create() method that constructs the matcher from the provided +/// arguments, and various other methods for type introspection. +class MatcherDescriptor { +public: +  virtual ~MatcherDescriptor() = default; + +  virtual VariantMatcher create(SourceRange NameRange, +                                ArrayRef<ParserValue> Args, +                                Diagnostics *Error) const = 0; + +  /// Returns whether the matcher is variadic. Variadic matchers can take any +  /// number of arguments, but they must be of the same type. +  virtual bool isVariadic() const = 0; + +  /// Returns the number of arguments accepted by the matcher if not variadic. +  virtual unsigned getNumArgs() const = 0; + +  /// Given that the matcher is being converted to type \p ThisKind, append the +  /// set of argument types accepted for argument \p ArgNo to \p ArgKinds. +  // FIXME: We should provide the ability to constrain the output of this +  // function based on the types of other matcher arguments. +  virtual void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo, +                           std::vector<ArgKind> &ArgKinds) const = 0; + +  /// Returns whether this matcher is convertible to the given type.  If it is +  /// so convertible, store in *Specificity a value corresponding to the +  /// "specificity" of the converted matcher to the given context, and in +  /// *LeastDerivedKind the least derived matcher kind which would result in the +  /// same matcher overload.  Zero specificity indicates that this conversion +  /// would produce a trivial matcher that will either always or never match. +  /// Such matchers are excluded from code completion results. +  virtual bool isConvertibleTo( +      ast_type_traits::ASTNodeKind Kind, unsigned *Specificity = nullptr, +      ast_type_traits::ASTNodeKind *LeastDerivedKind = nullptr) const = 0; + +  /// Returns whether the matcher will, given a matcher of any type T, yield a +  /// matcher of type T. +  virtual bool isPolymorphic() const { return false; } +}; + +inline bool isRetKindConvertibleTo( +    ArrayRef<ast_type_traits::ASTNodeKind> RetKinds, +    ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, +    ast_type_traits::ASTNodeKind *LeastDerivedKind) { +  for (const ast_type_traits::ASTNodeKind &NodeKind : RetKinds) { +    if (ArgKind(NodeKind).isConvertibleTo(Kind, Specificity)) { +      if (LeastDerivedKind) +        *LeastDerivedKind = NodeKind; +      return true; +    } +  } +  return false; +} + +/// Simple callback implementation. Marshaller and function are provided. +/// +/// This class wraps a function of arbitrary signature and a marshaller +/// function into a MatcherDescriptor. +/// The marshaller is in charge of taking the VariantValue arguments, checking +/// their types, unpacking them and calling the underlying function. +class FixedArgCountMatcherDescriptor : public MatcherDescriptor { +public: +  using MarshallerType = VariantMatcher (*)(void (*Func)(), +                                            StringRef MatcherName, +                                            SourceRange NameRange, +                                            ArrayRef<ParserValue> Args, +                                            Diagnostics *Error); + +  /// \param Marshaller Function to unpack the arguments and call \c Func +  /// \param Func Matcher construct function. This is the function that +  ///   compile-time matcher expressions would use to create the matcher. +  /// \param RetKinds The list of matcher types to which the matcher is +  ///   convertible. +  /// \param ArgKinds The types of the arguments this matcher takes. +  FixedArgCountMatcherDescriptor( +      MarshallerType Marshaller, void (*Func)(), StringRef MatcherName, +      ArrayRef<ast_type_traits::ASTNodeKind> RetKinds, +      ArrayRef<ArgKind> ArgKinds) +      : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName), +        RetKinds(RetKinds.begin(), RetKinds.end()), +        ArgKinds(ArgKinds.begin(), ArgKinds.end()) {} + +  VariantMatcher create(SourceRange NameRange, +                        ArrayRef<ParserValue> Args, +                        Diagnostics *Error) const override { +    return Marshaller(Func, MatcherName, NameRange, Args, Error); +  } + +  bool isVariadic() const override { return false; } +  unsigned getNumArgs() const override { return ArgKinds.size(); } + +  void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo, +                   std::vector<ArgKind> &Kinds) const override { +    Kinds.push_back(ArgKinds[ArgNo]); +  } + +  bool isConvertibleTo( +      ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, +      ast_type_traits::ASTNodeKind *LeastDerivedKind) const override { +    return isRetKindConvertibleTo(RetKinds, Kind, Specificity, +                                  LeastDerivedKind); +  } + +private: +  const MarshallerType Marshaller; +  void (* const Func)(); +  const std::string MatcherName; +  const std::vector<ast_type_traits::ASTNodeKind> RetKinds; +  const std::vector<ArgKind> ArgKinds; +}; + +/// Helper methods to extract and merge all possible typed matchers +/// out of the polymorphic object. +template <class PolyMatcher> +static void mergePolyMatchers(const PolyMatcher &Poly, +                              std::vector<DynTypedMatcher> &Out, +                              ast_matchers::internal::EmptyTypeList) {} + +template <class PolyMatcher, class TypeList> +static void mergePolyMatchers(const PolyMatcher &Poly, +                              std::vector<DynTypedMatcher> &Out, TypeList) { +  Out.push_back(ast_matchers::internal::Matcher<typename TypeList::head>(Poly)); +  mergePolyMatchers(Poly, Out, typename TypeList::tail()); +} + +/// Convert the return values of the functions into a VariantMatcher. +/// +/// There are 2 cases right now: The return value is a Matcher<T> or is a +/// polymorphic matcher. For the former, we just construct the VariantMatcher. +/// For the latter, we instantiate all the possible Matcher<T> of the poly +/// matcher. +static VariantMatcher outvalueToVariantMatcher(const DynTypedMatcher &Matcher) { +  return VariantMatcher::SingleMatcher(Matcher); +} + +template <typename T> +static VariantMatcher outvalueToVariantMatcher(const T &PolyMatcher, +                                               typename T::ReturnTypes * = +                                                   nullptr) { +  std::vector<DynTypedMatcher> Matchers; +  mergePolyMatchers(PolyMatcher, Matchers, typename T::ReturnTypes()); +  VariantMatcher Out = VariantMatcher::PolymorphicMatcher(std::move(Matchers)); +  return Out; +} + +template <typename T> +inline void buildReturnTypeVectorFromTypeList( +    std::vector<ast_type_traits::ASTNodeKind> &RetTypes) { +  RetTypes.push_back( +      ast_type_traits::ASTNodeKind::getFromNodeKind<typename T::head>()); +  buildReturnTypeVectorFromTypeList<typename T::tail>(RetTypes); +} + +template <> +inline void +buildReturnTypeVectorFromTypeList<ast_matchers::internal::EmptyTypeList>( +    std::vector<ast_type_traits::ASTNodeKind> &RetTypes) {} + +template <typename T> +struct BuildReturnTypeVector { +  static void build(std::vector<ast_type_traits::ASTNodeKind> &RetTypes) { +    buildReturnTypeVectorFromTypeList<typename T::ReturnTypes>(RetTypes); +  } +}; + +template <typename T> +struct BuildReturnTypeVector<ast_matchers::internal::Matcher<T>> { +  static void build(std::vector<ast_type_traits::ASTNodeKind> &RetTypes) { +    RetTypes.push_back(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); +  } +}; + +template <typename T> +struct BuildReturnTypeVector<ast_matchers::internal::BindableMatcher<T>> { +  static void build(std::vector<ast_type_traits::ASTNodeKind> &RetTypes) { +    RetTypes.push_back(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); +  } +}; + +/// Variadic marshaller function. +template <typename ResultT, typename ArgT, +          ResultT (*Func)(ArrayRef<const ArgT *>)> +VariantMatcher +variadicMatcherDescriptor(StringRef MatcherName, SourceRange NameRange, +                          ArrayRef<ParserValue> Args, Diagnostics *Error) { +  ArgT **InnerArgs = new ArgT *[Args.size()](); + +  bool HasError = false; +  for (size_t i = 0, e = Args.size(); i != e; ++i) { +    using ArgTraits = ArgTypeTraits<ArgT>; + +    const ParserValue &Arg = Args[i]; +    const VariantValue &Value = Arg.Value; +    if (!ArgTraits::is(Value)) { +      Error->addError(Arg.Range, Error->ET_RegistryWrongArgType) +          << (i + 1) << ArgTraits::getKind().asString() << Value.getTypeAsString(); +      HasError = true; +      break; +    } +    InnerArgs[i] = new ArgT(ArgTraits::get(Value)); +  } + +  VariantMatcher Out; +  if (!HasError) { +    Out = outvalueToVariantMatcher(Func(llvm::makeArrayRef(InnerArgs, +                                                           Args.size()))); +  } + +  for (size_t i = 0, e = Args.size(); i != e; ++i) { +    delete InnerArgs[i]; +  } +  delete[] InnerArgs; +  return Out; +} + +/// Matcher descriptor for variadic functions. +/// +/// This class simply wraps a VariadicFunction with the right signature to export +/// it as a MatcherDescriptor. +/// This allows us to have one implementation of the interface for as many free +/// functions as we want, reducing the number of symbols and size of the +/// object file. +class VariadicFuncMatcherDescriptor : public MatcherDescriptor { +public: +  using RunFunc = VariantMatcher (*)(StringRef MatcherName, +                                     SourceRange NameRange, +                                     ArrayRef<ParserValue> Args, +                                     Diagnostics *Error); + +  template <typename ResultT, typename ArgT, +            ResultT (*F)(ArrayRef<const ArgT *>)> +  VariadicFuncMatcherDescriptor( +      ast_matchers::internal::VariadicFunction<ResultT, ArgT, F> Func, +      StringRef MatcherName) +      : Func(&variadicMatcherDescriptor<ResultT, ArgT, F>), +        MatcherName(MatcherName.str()), +        ArgsKind(ArgTypeTraits<ArgT>::getKind()) { +    BuildReturnTypeVector<ResultT>::build(RetKinds); +  } + +  VariantMatcher create(SourceRange NameRange, +                        ArrayRef<ParserValue> Args, +                        Diagnostics *Error) const override { +    return Func(MatcherName, NameRange, Args, Error); +  } + +  bool isVariadic() const override { return true; } +  unsigned getNumArgs() const override { return 0; } + +  void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo, +                   std::vector<ArgKind> &Kinds) const override { +    Kinds.push_back(ArgsKind); +  } + +  bool isConvertibleTo( +      ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, +      ast_type_traits::ASTNodeKind *LeastDerivedKind) const override { +    return isRetKindConvertibleTo(RetKinds, Kind, Specificity, +                                  LeastDerivedKind); +  } + +private: +  const RunFunc Func; +  const std::string MatcherName; +  std::vector<ast_type_traits::ASTNodeKind> RetKinds; +  const ArgKind ArgsKind; +}; + +/// Return CK_Trivial when appropriate for VariadicDynCastAllOfMatchers. +class DynCastAllOfMatcherDescriptor : public VariadicFuncMatcherDescriptor { +public: +  template <typename BaseT, typename DerivedT> +  DynCastAllOfMatcherDescriptor( +      ast_matchers::internal::VariadicDynCastAllOfMatcher<BaseT, DerivedT> Func, +      StringRef MatcherName) +      : VariadicFuncMatcherDescriptor(Func, MatcherName), +        DerivedKind(ast_type_traits::ASTNodeKind::getFromNodeKind<DerivedT>()) { +  } + +  bool +  isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, +                ast_type_traits::ASTNodeKind *LeastDerivedKind) const override { +    // If Kind is not a base of DerivedKind, either DerivedKind is a base of +    // Kind (in which case the match will always succeed) or Kind and +    // DerivedKind are unrelated (in which case it will always fail), so set +    // Specificity to 0. +    if (VariadicFuncMatcherDescriptor::isConvertibleTo(Kind, Specificity, +                                                 LeastDerivedKind)) { +      if (Kind.isSame(DerivedKind) || !Kind.isBaseOf(DerivedKind)) { +        if (Specificity) +          *Specificity = 0; +      } +      return true; +    } else { +      return false; +    } +  } + +private: +  const ast_type_traits::ASTNodeKind DerivedKind; +}; + +/// Helper macros to check the arguments on all marshaller functions. +#define CHECK_ARG_COUNT(count)                                                 \ +  if (Args.size() != count) {                                                  \ +    Error->addError(NameRange, Error->ET_RegistryWrongArgCount)                \ +        << count << Args.size();                                               \ +    return VariantMatcher();                                                   \ +  } + +#define CHECK_ARG_TYPE(index, type)                                            \ +  if (!ArgTypeTraits<type>::is(Args[index].Value)) {                           \ +    Error->addError(Args[index].Range, Error->ET_RegistryWrongArgType)         \ +        << (index + 1) << ArgTypeTraits<type>::getKind().asString()            \ +        << Args[index].Value.getTypeAsString();                                \ +    return VariantMatcher();                                                   \ +  } + +/// 0-arg marshaller function. +template <typename ReturnType> +static VariantMatcher matcherMarshall0(void (*Func)(), StringRef MatcherName, +                                       SourceRange NameRange, +                                       ArrayRef<ParserValue> Args, +                                       Diagnostics *Error) { +  using FuncType = ReturnType (*)(); +  CHECK_ARG_COUNT(0); +  return outvalueToVariantMatcher(reinterpret_cast<FuncType>(Func)()); +} + +/// 1-arg marshaller function. +template <typename ReturnType, typename ArgType1> +static VariantMatcher matcherMarshall1(void (*Func)(), StringRef MatcherName, +                                       SourceRange NameRange, +                                       ArrayRef<ParserValue> Args, +                                       Diagnostics *Error) { +  using FuncType = ReturnType (*)(ArgType1); +  CHECK_ARG_COUNT(1); +  CHECK_ARG_TYPE(0, ArgType1); +  return outvalueToVariantMatcher(reinterpret_cast<FuncType>(Func)( +      ArgTypeTraits<ArgType1>::get(Args[0].Value))); +} + +/// 2-arg marshaller function. +template <typename ReturnType, typename ArgType1, typename ArgType2> +static VariantMatcher matcherMarshall2(void (*Func)(), StringRef MatcherName, +                                       SourceRange NameRange, +                                       ArrayRef<ParserValue> Args, +                                       Diagnostics *Error) { +  using FuncType = ReturnType (*)(ArgType1, ArgType2); +  CHECK_ARG_COUNT(2); +  CHECK_ARG_TYPE(0, ArgType1); +  CHECK_ARG_TYPE(1, ArgType2); +  return outvalueToVariantMatcher(reinterpret_cast<FuncType>(Func)( +      ArgTypeTraits<ArgType1>::get(Args[0].Value), +      ArgTypeTraits<ArgType2>::get(Args[1].Value))); +} + +#undef CHECK_ARG_COUNT +#undef CHECK_ARG_TYPE + +/// Helper class used to collect all the possible overloads of an +///   argument adaptative matcher function. +template <template <typename ToArg, typename FromArg> class ArgumentAdapterT, +          typename FromTypes, typename ToTypes> +class AdaptativeOverloadCollector { +public: +  AdaptativeOverloadCollector( +      StringRef Name, std::vector<std::unique_ptr<MatcherDescriptor>> &Out) +      : Name(Name), Out(Out) { +    collect(FromTypes()); +  } + +private: +  using AdaptativeFunc = ast_matchers::internal::ArgumentAdaptingMatcherFunc< +      ArgumentAdapterT, FromTypes, ToTypes>; + +  /// End case for the recursion +  static void collect(ast_matchers::internal::EmptyTypeList) {} + +  /// Recursive case. Get the overload for the head of the list, and +  ///   recurse to the tail. +  template <typename FromTypeList> +  inline void collect(FromTypeList); + +  StringRef Name; +  std::vector<std::unique_ptr<MatcherDescriptor>> &Out; +}; + +/// MatcherDescriptor that wraps multiple "overloads" of the same +///   matcher. +/// +/// It will try every overload and generate appropriate errors for when none or +/// more than one overloads match the arguments. +class OverloadedMatcherDescriptor : public MatcherDescriptor { +public: +  OverloadedMatcherDescriptor( +      MutableArrayRef<std::unique_ptr<MatcherDescriptor>> Callbacks) +      : Overloads(std::make_move_iterator(Callbacks.begin()), +                  std::make_move_iterator(Callbacks.end())) {} + +  ~OverloadedMatcherDescriptor() override = default; + +  VariantMatcher create(SourceRange NameRange, +                        ArrayRef<ParserValue> Args, +                        Diagnostics *Error) const override { +    std::vector<VariantMatcher> Constructed; +    Diagnostics::OverloadContext Ctx(Error); +    for (const auto &O : Overloads) { +      VariantMatcher SubMatcher = O->create(NameRange, Args, Error); +      if (!SubMatcher.isNull()) { +        Constructed.push_back(SubMatcher); +      } +    } + +    if (Constructed.empty()) return VariantMatcher(); // No overload matched. +    // We ignore the errors if any matcher succeeded. +    Ctx.revertErrors(); +    if (Constructed.size() > 1) { +      // More than one constructed. It is ambiguous. +      Error->addError(NameRange, Error->ET_RegistryAmbiguousOverload); +      return VariantMatcher(); +    } +    return Constructed[0]; +  } + +  bool isVariadic() const override { +    bool Overload0Variadic = Overloads[0]->isVariadic(); +#ifndef NDEBUG +    for (const auto &O : Overloads) { +      assert(Overload0Variadic == O->isVariadic()); +    } +#endif +    return Overload0Variadic; +  } + +  unsigned getNumArgs() const override { +    unsigned Overload0NumArgs = Overloads[0]->getNumArgs(); +#ifndef NDEBUG +    for (const auto &O : Overloads) { +      assert(Overload0NumArgs == O->getNumArgs()); +    } +#endif +    return Overload0NumArgs; +  } + +  void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo, +                   std::vector<ArgKind> &Kinds) const override { +    for (const auto &O : Overloads) { +      if (O->isConvertibleTo(ThisKind)) +        O->getArgKinds(ThisKind, ArgNo, Kinds); +    } +  } + +  bool isConvertibleTo( +      ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, +      ast_type_traits::ASTNodeKind *LeastDerivedKind) const override { +    for (const auto &O : Overloads) { +      if (O->isConvertibleTo(Kind, Specificity, LeastDerivedKind)) +        return true; +    } +    return false; +  } + +private: +  std::vector<std::unique_ptr<MatcherDescriptor>> Overloads; +}; + +/// Variadic operator marshaller function. +class VariadicOperatorMatcherDescriptor : public MatcherDescriptor { +public: +  using VarOp = DynTypedMatcher::VariadicOperator; + +  VariadicOperatorMatcherDescriptor(unsigned MinCount, unsigned MaxCount, +                                    VarOp Op, StringRef MatcherName) +      : MinCount(MinCount), MaxCount(MaxCount), Op(Op), +        MatcherName(MatcherName) {} + +  VariantMatcher create(SourceRange NameRange, +                        ArrayRef<ParserValue> Args, +                        Diagnostics *Error) const override { +    if (Args.size() < MinCount || MaxCount < Args.size()) { +      const std::string MaxStr = +          (MaxCount == std::numeric_limits<unsigned>::max() ? "" +                                                            : Twine(MaxCount)) +              .str(); +      Error->addError(NameRange, Error->ET_RegistryWrongArgCount) +          << ("(" + Twine(MinCount) + ", " + MaxStr + ")") << Args.size(); +      return VariantMatcher(); +    } + +    std::vector<VariantMatcher> InnerArgs; +    for (size_t i = 0, e = Args.size(); i != e; ++i) { +      const ParserValue &Arg = Args[i]; +      const VariantValue &Value = Arg.Value; +      if (!Value.isMatcher()) { +        Error->addError(Arg.Range, Error->ET_RegistryWrongArgType) +            << (i + 1) << "Matcher<>" << Value.getTypeAsString(); +        return VariantMatcher(); +      } +      InnerArgs.push_back(Value.getMatcher()); +    } +    return VariantMatcher::VariadicOperatorMatcher(Op, std::move(InnerArgs)); +  } + +  bool isVariadic() const override { return true; } +  unsigned getNumArgs() const override { return 0; } + +  void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo, +                   std::vector<ArgKind> &Kinds) const override { +    Kinds.push_back(ThisKind); +  } + +  bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, +                       ast_type_traits::ASTNodeKind *LeastDerivedKind) const override { +    if (Specificity) +      *Specificity = 1; +    if (LeastDerivedKind) +      *LeastDerivedKind = Kind; +    return true; +  } + +  bool isPolymorphic() const override { return true; } + +private: +  const unsigned MinCount; +  const unsigned MaxCount; +  const VarOp Op; +  const StringRef MatcherName; +}; + +/// Helper functions to select the appropriate marshaller functions. +/// They detect the number of arguments, arguments types and return type. + +/// 0-arg overload +template <typename ReturnType> +std::unique_ptr<MatcherDescriptor> +makeMatcherAutoMarshall(ReturnType (*Func)(), StringRef MatcherName) { +  std::vector<ast_type_traits::ASTNodeKind> RetTypes; +  BuildReturnTypeVector<ReturnType>::build(RetTypes); +  return std::make_unique<FixedArgCountMatcherDescriptor>( +      matcherMarshall0<ReturnType>, reinterpret_cast<void (*)()>(Func), +      MatcherName, RetTypes, None); +} + +/// 1-arg overload +template <typename ReturnType, typename ArgType1> +std::unique_ptr<MatcherDescriptor> +makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1), StringRef MatcherName) { +  std::vector<ast_type_traits::ASTNodeKind> RetTypes; +  BuildReturnTypeVector<ReturnType>::build(RetTypes); +  ArgKind AK = ArgTypeTraits<ArgType1>::getKind(); +  return std::make_unique<FixedArgCountMatcherDescriptor>( +      matcherMarshall1<ReturnType, ArgType1>, +      reinterpret_cast<void (*)()>(Func), MatcherName, RetTypes, AK); +} + +/// 2-arg overload +template <typename ReturnType, typename ArgType1, typename ArgType2> +std::unique_ptr<MatcherDescriptor> +makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1, ArgType2), +                        StringRef MatcherName) { +  std::vector<ast_type_traits::ASTNodeKind> RetTypes; +  BuildReturnTypeVector<ReturnType>::build(RetTypes); +  ArgKind AKs[] = { ArgTypeTraits<ArgType1>::getKind(), +                    ArgTypeTraits<ArgType2>::getKind() }; +  return std::make_unique<FixedArgCountMatcherDescriptor>( +      matcherMarshall2<ReturnType, ArgType1, ArgType2>, +      reinterpret_cast<void (*)()>(Func), MatcherName, RetTypes, AKs); +} + +/// Variadic overload. +template <typename ResultT, typename ArgT, +          ResultT (*Func)(ArrayRef<const ArgT *>)> +std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall( +    ast_matchers::internal::VariadicFunction<ResultT, ArgT, Func> VarFunc, +    StringRef MatcherName) { +  return std::make_unique<VariadicFuncMatcherDescriptor>(VarFunc, MatcherName); +} + +/// Overload for VariadicDynCastAllOfMatchers. +/// +/// Not strictly necessary, but DynCastAllOfMatcherDescriptor gives us better +/// completion results for that type of matcher. +template <typename BaseT, typename DerivedT> +std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall( +    ast_matchers::internal::VariadicDynCastAllOfMatcher<BaseT, DerivedT> +        VarFunc, +    StringRef MatcherName) { +  return std::make_unique<DynCastAllOfMatcherDescriptor>(VarFunc, MatcherName); +} + +/// Argument adaptative overload. +template <template <typename ToArg, typename FromArg> class ArgumentAdapterT, +          typename FromTypes, typename ToTypes> +std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall( +    ast_matchers::internal::ArgumentAdaptingMatcherFunc<ArgumentAdapterT, +                                                        FromTypes, ToTypes>, +    StringRef MatcherName) { +  std::vector<std::unique_ptr<MatcherDescriptor>> Overloads; +  AdaptativeOverloadCollector<ArgumentAdapterT, FromTypes, ToTypes>(MatcherName, +                                                                    Overloads); +  return std::make_unique<OverloadedMatcherDescriptor>(Overloads); +} + +template <template <typename ToArg, typename FromArg> class ArgumentAdapterT, +          typename FromTypes, typename ToTypes> +template <typename FromTypeList> +inline void AdaptativeOverloadCollector<ArgumentAdapterT, FromTypes, +                                        ToTypes>::collect(FromTypeList) { +  Out.push_back(makeMatcherAutoMarshall( +      &AdaptativeFunc::template create<typename FromTypeList::head>, Name)); +  collect(typename FromTypeList::tail()); +} + +/// Variadic operator overload. +template <unsigned MinCount, unsigned MaxCount> +std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall( +    ast_matchers::internal::VariadicOperatorMatcherFunc<MinCount, MaxCount> +        Func, +    StringRef MatcherName) { +  return std::make_unique<VariadicOperatorMatcherDescriptor>( +      MinCount, MaxCount, Func.Op, MatcherName); +} + +} // namespace internal +} // namespace dynamic +} // namespace ast_matchers +} // namespace clang + +#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H  | 
