801 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			801 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C++
		
	
	
	
//===- Marshallers.h - Generic matcher function marshallers -----*- C++ -*-===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
/// \file
 | 
						|
/// \brief 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 "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 {
 | 
						|
 | 
						|
/// \brief 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);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
/// \brief 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;
 | 
						|
}
 | 
						|
 | 
						|
/// \brief 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;
 | 
						|
};
 | 
						|
 | 
						|
/// \brief 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());
 | 
						|
}
 | 
						|
 | 
						|
/// \brief 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>());
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
/// \brief 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;
 | 
						|
}
 | 
						|
 | 
						|
/// \brief 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;
 | 
						|
};
 | 
						|
 | 
						|
/// \brief 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;
 | 
						|
};
 | 
						|
 | 
						|
/// \brief 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();                                                   \
 | 
						|
  }
 | 
						|
 | 
						|
/// \brief 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)());
 | 
						|
}
 | 
						|
 | 
						|
/// \brief 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)));
 | 
						|
}
 | 
						|
 | 
						|
/// \brief 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
 | 
						|
 | 
						|
/// \brief 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>;
 | 
						|
 | 
						|
  /// \brief End case for the recursion
 | 
						|
  static void collect(ast_matchers::internal::EmptyTypeList) {}
 | 
						|
 | 
						|
  /// \brief 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;
 | 
						|
};
 | 
						|
 | 
						|
/// \brief 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;
 | 
						|
};
 | 
						|
 | 
						|
/// \brief 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.
 | 
						|
 | 
						|
/// \brief 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 llvm::make_unique<FixedArgCountMatcherDescriptor>(
 | 
						|
      matcherMarshall0<ReturnType>, reinterpret_cast<void (*)()>(Func),
 | 
						|
      MatcherName, RetTypes, None);
 | 
						|
}
 | 
						|
 | 
						|
/// \brief 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 llvm::make_unique<FixedArgCountMatcherDescriptor>(
 | 
						|
      matcherMarshall1<ReturnType, ArgType1>,
 | 
						|
      reinterpret_cast<void (*)()>(Func), MatcherName, RetTypes, AK);
 | 
						|
}
 | 
						|
 | 
						|
/// \brief 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 llvm::make_unique<FixedArgCountMatcherDescriptor>(
 | 
						|
      matcherMarshall2<ReturnType, ArgType1, ArgType2>,
 | 
						|
      reinterpret_cast<void (*)()>(Func), MatcherName, RetTypes, AKs);
 | 
						|
}
 | 
						|
 | 
						|
/// \brief 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 llvm::make_unique<VariadicFuncMatcherDescriptor>(VarFunc, MatcherName);
 | 
						|
}
 | 
						|
 | 
						|
/// \brief 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 llvm::make_unique<DynCastAllOfMatcherDescriptor>(VarFunc, MatcherName);
 | 
						|
}
 | 
						|
 | 
						|
/// \brief 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 llvm::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());
 | 
						|
}
 | 
						|
 | 
						|
/// \brief Variadic operator overload.
 | 
						|
template <unsigned MinCount, unsigned MaxCount>
 | 
						|
std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall(
 | 
						|
    ast_matchers::internal::VariadicOperatorMatcherFunc<MinCount, MaxCount>
 | 
						|
        Func,
 | 
						|
    StringRef MatcherName) {
 | 
						|
  return llvm::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
 |