clang 20.0.0 (based on r547379) from build 12806354. Bug: http://b/379133546 Test: N/A Change-Id: I2eb8938af55d809de674be63cb30cf27e801862b Upstream-Commit: ad834e67b1105d15ef907f6255d4c96e8e733f57
561 lines
36 KiB
C++
561 lines
36 KiB
C++
//===--- ASTMatchersMacros.h - Structural query framework -------*- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Defines macros that enable us to define new matchers in a single place.
|
|
// Since a matcher is a function which returns a Matcher<T> object, where
|
|
// T is the type of the actual implementation of the matcher, the macros allow
|
|
// us to write matchers like functions and take care of the definition of the
|
|
// class boilerplate.
|
|
//
|
|
// Note that when you define a matcher with an AST_MATCHER* macro, only the
|
|
// function which creates the matcher goes into the current namespace - the
|
|
// class that implements the actual matcher, which gets returned by the
|
|
// generator function, is put into the 'internal' namespace. This allows us
|
|
// to only have the functions (which is all the user cares about) in the
|
|
// 'ast_matchers' namespace and hide the boilerplate.
|
|
//
|
|
// To define a matcher in user code, put it into your own namespace. This would
|
|
// help to prevent ODR violations in case a matcher with the same name is
|
|
// defined in multiple translation units:
|
|
//
|
|
// namespace my_matchers {
|
|
// AST_MATCHER_P(clang::MemberExpr, Member,
|
|
// clang::ast_matchers::internal::Matcher<clang::ValueDecl>,
|
|
// InnerMatcher) {
|
|
// return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder);
|
|
// }
|
|
// } // namespace my_matchers
|
|
//
|
|
// Alternatively, an unnamed namespace may be used:
|
|
//
|
|
// namespace clang {
|
|
// namespace ast_matchers {
|
|
// namespace {
|
|
// AST_MATCHER_P(MemberExpr, Member,
|
|
// internal::Matcher<ValueDecl>, InnerMatcher) {
|
|
// return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder);
|
|
// }
|
|
// } // namespace
|
|
// } // namespace ast_matchers
|
|
// } // namespace clang
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
|
|
#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
|
|
|
|
/// AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) { ... }
|
|
/// defines a zero parameter function named DefineMatcher() that returns a
|
|
/// ReturnType object.
|
|
#define AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) \
|
|
inline ReturnType DefineMatcher##_getInstance(); \
|
|
inline ReturnType DefineMatcher() { \
|
|
return ::clang::ast_matchers::internal::MemoizedMatcher< \
|
|
ReturnType, DefineMatcher##_getInstance>::getInstance(); \
|
|
} \
|
|
inline ReturnType DefineMatcher##_getInstance()
|
|
|
|
/// AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) {
|
|
/// ... }
|
|
/// defines a single-parameter function named DefineMatcher() that returns a
|
|
/// ReturnType object.
|
|
///
|
|
/// The code between the curly braces has access to the following variables:
|
|
///
|
|
/// Param: the parameter passed to the function; its type
|
|
/// is ParamType.
|
|
///
|
|
/// The code should return an instance of ReturnType.
|
|
#define AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) \
|
|
AST_MATCHER_FUNCTION_P_OVERLOAD(ReturnType, DefineMatcher, ParamType, Param, \
|
|
0)
|
|
#define AST_MATCHER_FUNCTION_P_OVERLOAD(ReturnType, DefineMatcher, ParamType, \
|
|
Param, OverloadId) \
|
|
inline ReturnType DefineMatcher(ParamType const &Param); \
|
|
typedef ReturnType (&DefineMatcher##_Type##OverloadId)(ParamType const &); \
|
|
inline ReturnType DefineMatcher(ParamType const &Param)
|
|
|
|
/// AST_MATCHER(Type, DefineMatcher) { ... }
|
|
/// defines a zero parameter function named DefineMatcher() that returns a
|
|
/// Matcher<Type> object.
|
|
///
|
|
/// The code between the curly braces has access to the following variables:
|
|
///
|
|
/// Node: the AST node being matched; its type is Type.
|
|
/// Finder: an ASTMatchFinder*.
|
|
/// Builder: a BoundNodesTreeBuilder*.
|
|
///
|
|
/// The code should return true if 'Node' matches.
|
|
#define AST_MATCHER(Type, DefineMatcher) \
|
|
namespace internal { \
|
|
class matcher_##DefineMatcher##Matcher \
|
|
: public ::clang::ast_matchers::internal::MatcherInterface<Type> { \
|
|
public: \
|
|
explicit matcher_##DefineMatcher##Matcher() = default; \
|
|
bool matches(const Type &Node, \
|
|
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
|
|
::clang::ast_matchers::internal::BoundNodesTreeBuilder \
|
|
*Builder) const override; \
|
|
}; \
|
|
} \
|
|
inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher() { \
|
|
return ::clang::ast_matchers::internal::makeMatcher( \
|
|
new internal::matcher_##DefineMatcher##Matcher()); \
|
|
} \
|
|
inline bool internal::matcher_##DefineMatcher##Matcher::matches( \
|
|
const Type &Node, \
|
|
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
|
|
::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const
|
|
|
|
/// AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... }
|
|
/// defines a single-parameter function named DefineMatcher() that returns a
|
|
/// Matcher<Type> object.
|
|
///
|
|
/// The code between the curly braces has access to the following variables:
|
|
///
|
|
/// Node: the AST node being matched; its type is Type.
|
|
/// Param: the parameter passed to the function; its type
|
|
/// is ParamType.
|
|
/// Finder: an ASTMatchFinder*.
|
|
/// Builder: a BoundNodesTreeBuilder*.
|
|
///
|
|
/// The code should return true if 'Node' matches.
|
|
#define AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) \
|
|
AST_MATCHER_P_OVERLOAD(Type, DefineMatcher, ParamType, Param, 0)
|
|
|
|
#define AST_MATCHER_P_OVERLOAD(Type, DefineMatcher, ParamType, Param, \
|
|
OverloadId) \
|
|
namespace internal { \
|
|
class matcher_##DefineMatcher##OverloadId##Matcher \
|
|
: public ::clang::ast_matchers::internal::MatcherInterface<Type> { \
|
|
public: \
|
|
explicit matcher_##DefineMatcher##OverloadId##Matcher( \
|
|
ParamType const &A##Param) \
|
|
: Param(A##Param) {} \
|
|
bool matches(const Type &Node, \
|
|
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
|
|
::clang::ast_matchers::internal::BoundNodesTreeBuilder \
|
|
*Builder) const override; \
|
|
\
|
|
private: \
|
|
ParamType Param; \
|
|
}; \
|
|
} \
|
|
inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher( \
|
|
ParamType const &Param) { \
|
|
return ::clang::ast_matchers::internal::makeMatcher( \
|
|
new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param)); \
|
|
} \
|
|
typedef ::clang::ast_matchers::internal::Matcher<Type> ( \
|
|
&DefineMatcher##_Type##OverloadId)(ParamType const &Param); \
|
|
inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
|
|
const Type &Node, \
|
|
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
|
|
::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const
|
|
|
|
/// AST_MATCHER_P2(
|
|
/// Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... }
|
|
/// defines a two-parameter function named DefineMatcher() that returns a
|
|
/// Matcher<Type> object.
|
|
///
|
|
/// The code between the curly braces has access to the following variables:
|
|
///
|
|
/// Node: the AST node being matched; its type is Type.
|
|
/// Param1, Param2: the parameters passed to the function; their types
|
|
/// are ParamType1 and ParamType2.
|
|
/// Finder: an ASTMatchFinder*.
|
|
/// Builder: a BoundNodesTreeBuilder*.
|
|
///
|
|
/// The code should return true if 'Node' matches.
|
|
#define AST_MATCHER_P2(Type, DefineMatcher, ParamType1, Param1, ParamType2, \
|
|
Param2) \
|
|
AST_MATCHER_P2_OVERLOAD(Type, DefineMatcher, ParamType1, Param1, ParamType2, \
|
|
Param2, 0)
|
|
|
|
#define AST_MATCHER_P2_OVERLOAD(Type, DefineMatcher, ParamType1, Param1, \
|
|
ParamType2, Param2, OverloadId) \
|
|
namespace internal { \
|
|
class matcher_##DefineMatcher##OverloadId##Matcher \
|
|
: public ::clang::ast_matchers::internal::MatcherInterface<Type> { \
|
|
public: \
|
|
matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \
|
|
ParamType2 const &A##Param2) \
|
|
: Param1(A##Param1), Param2(A##Param2) {} \
|
|
bool matches(const Type &Node, \
|
|
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
|
|
::clang::ast_matchers::internal::BoundNodesTreeBuilder \
|
|
*Builder) const override; \
|
|
\
|
|
private: \
|
|
ParamType1 Param1; \
|
|
ParamType2 Param2; \
|
|
}; \
|
|
} \
|
|
inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher( \
|
|
ParamType1 const &Param1, ParamType2 const &Param2) { \
|
|
return ::clang::ast_matchers::internal::makeMatcher( \
|
|
new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1, \
|
|
Param2)); \
|
|
} \
|
|
typedef ::clang::ast_matchers::internal::Matcher<Type> ( \
|
|
&DefineMatcher##_Type##OverloadId)(ParamType1 const &Param1, \
|
|
ParamType2 const &Param2); \
|
|
inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
|
|
const Type &Node, \
|
|
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
|
|
::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const
|
|
|
|
/// Construct a type-list to be passed to the AST_POLYMORPHIC_MATCHER*
|
|
/// macros.
|
|
///
|
|
/// You can't pass something like \c TypeList<Foo, Bar> to a macro, because it
|
|
/// will look at that as two arguments. However, you can pass
|
|
/// \c void(TypeList<Foo, Bar>), which works thanks to the parenthesis.
|
|
/// The \c PolymorphicMatcherWithParam* classes will unpack the function type to
|
|
/// extract the TypeList object.
|
|
#define AST_POLYMORPHIC_SUPPORTED_TYPES(...) \
|
|
void(::clang::ast_matchers::internal::TypeList<__VA_ARGS__>)
|
|
|
|
/// AST_POLYMORPHIC_MATCHER(DefineMatcher) { ... }
|
|
/// defines a single-parameter function named DefineMatcher() that is
|
|
/// polymorphic in the return type.
|
|
///
|
|
/// The variables are the same as for AST_MATCHER, but NodeType will be deduced
|
|
/// from the calling context.
|
|
#define AST_POLYMORPHIC_MATCHER(DefineMatcher, ReturnTypesF) \
|
|
namespace internal { \
|
|
template <typename NodeType> \
|
|
class matcher_##DefineMatcher##Matcher \
|
|
: public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \
|
|
public: \
|
|
bool matches(const NodeType &Node, \
|
|
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
|
|
::clang::ast_matchers::internal::BoundNodesTreeBuilder \
|
|
*Builder) const override; \
|
|
}; \
|
|
} \
|
|
inline ::clang::ast_matchers::internal::PolymorphicMatcher< \
|
|
internal::matcher_##DefineMatcher##Matcher, ReturnTypesF> \
|
|
DefineMatcher() { \
|
|
return ::clang::ast_matchers::internal::PolymorphicMatcher< \
|
|
internal::matcher_##DefineMatcher##Matcher, ReturnTypesF>(); \
|
|
} \
|
|
template <typename NodeType> \
|
|
bool internal::matcher_##DefineMatcher##Matcher<NodeType>::matches( \
|
|
const NodeType &Node, \
|
|
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
|
|
::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const
|
|
|
|
/// AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... }
|
|
/// defines a single-parameter function named DefineMatcher() that is
|
|
/// polymorphic in the return type.
|
|
///
|
|
/// The variables are the same as for
|
|
/// AST_MATCHER_P, with the addition of NodeType, which specifies the node type
|
|
/// of the matcher Matcher<NodeType> returned by the function matcher().
|
|
///
|
|
/// FIXME: Pull out common code with above macro?
|
|
#define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ReturnTypesF, ParamType, \
|
|
Param) \
|
|
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType, \
|
|
Param, 0)
|
|
|
|
#define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF, \
|
|
ParamType, Param, OverloadId) \
|
|
namespace internal { \
|
|
template <typename NodeType, typename ParamT> \
|
|
class matcher_##DefineMatcher##OverloadId##Matcher \
|
|
: public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \
|
|
public: \
|
|
explicit matcher_##DefineMatcher##OverloadId##Matcher( \
|
|
ParamType const &A##Param) \
|
|
: Param(A##Param) {} \
|
|
bool matches(const NodeType &Node, \
|
|
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
|
|
::clang::ast_matchers::internal::BoundNodesTreeBuilder \
|
|
*Builder) const override; \
|
|
\
|
|
private: \
|
|
ParamType Param; \
|
|
}; \
|
|
} \
|
|
inline ::clang::ast_matchers::internal::PolymorphicMatcher< \
|
|
internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \
|
|
ParamType> \
|
|
DefineMatcher(ParamType const &Param) { \
|
|
return ::clang::ast_matchers::internal::PolymorphicMatcher< \
|
|
internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \
|
|
ParamType>(Param); \
|
|
} \
|
|
typedef ::clang::ast_matchers::internal::PolymorphicMatcher< \
|
|
internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \
|
|
ParamType> (&DefineMatcher##_Type##OverloadId)(ParamType const &Param); \
|
|
template <typename NodeType, typename ParamT> \
|
|
bool internal:: \
|
|
matcher_##DefineMatcher##OverloadId##Matcher<NodeType, ParamT>::matches( \
|
|
const NodeType &Node, \
|
|
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
|
|
::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) \
|
|
const
|
|
|
|
/// AST_POLYMORPHIC_MATCHER_P2(
|
|
/// DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... }
|
|
/// defines a two-parameter function named matcher() that is polymorphic in
|
|
/// the return type.
|
|
///
|
|
/// The variables are the same as for AST_MATCHER_P2, with the
|
|
/// addition of NodeType, which specifies the node type of the matcher
|
|
/// Matcher<NodeType> returned by the function DefineMatcher().
|
|
#define AST_POLYMORPHIC_MATCHER_P2(DefineMatcher, ReturnTypesF, ParamType1, \
|
|
Param1, ParamType2, Param2) \
|
|
AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType1, \
|
|
Param1, ParamType2, Param2, 0)
|
|
|
|
#define AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ReturnTypesF, \
|
|
ParamType1, Param1, ParamType2, \
|
|
Param2, OverloadId) \
|
|
namespace internal { \
|
|
template <typename NodeType, typename ParamT1, typename ParamT2> \
|
|
class matcher_##DefineMatcher##OverloadId##Matcher \
|
|
: public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \
|
|
public: \
|
|
matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \
|
|
ParamType2 const &A##Param2) \
|
|
: Param1(A##Param1), Param2(A##Param2) {} \
|
|
bool matches(const NodeType &Node, \
|
|
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
|
|
::clang::ast_matchers::internal::BoundNodesTreeBuilder \
|
|
*Builder) const override; \
|
|
\
|
|
private: \
|
|
ParamType1 Param1; \
|
|
ParamType2 Param2; \
|
|
}; \
|
|
} \
|
|
inline ::clang::ast_matchers::internal::PolymorphicMatcher< \
|
|
internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \
|
|
ParamType1, ParamType2> \
|
|
DefineMatcher(ParamType1 const &Param1, ParamType2 const &Param2) { \
|
|
return ::clang::ast_matchers::internal::PolymorphicMatcher< \
|
|
internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \
|
|
ParamType1, ParamType2>(Param1, Param2); \
|
|
} \
|
|
typedef ::clang::ast_matchers::internal::PolymorphicMatcher< \
|
|
internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \
|
|
ParamType1, ParamType2> (&DefineMatcher##_Type##OverloadId)( \
|
|
ParamType1 const &Param1, ParamType2 const &Param2); \
|
|
template <typename NodeType, typename ParamT1, typename ParamT2> \
|
|
bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
|
|
NodeType, ParamT1, ParamT2>:: \
|
|
matches(const NodeType &Node, \
|
|
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
|
|
::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) \
|
|
const
|
|
|
|
// FIXME: add a matcher for TypeLoc derived classes using its custom casting
|
|
// API (no longer dyn_cast) if/when we need such matching
|
|
|
|
#define AST_TYPE_TRAVERSE_MATCHER_DECL(MatcherName, FunctionName, \
|
|
ReturnTypesF) \
|
|
namespace internal { \
|
|
template <typename T> struct TypeMatcher##MatcherName##Getter { \
|
|
static QualType (T::*value())() const { return &T::FunctionName; } \
|
|
}; \
|
|
} \
|
|
extern const ::clang::ast_matchers::internal:: \
|
|
TypeTraversePolymorphicMatcher< \
|
|
QualType, \
|
|
::clang::ast_matchers::internal::TypeMatcher##MatcherName##Getter, \
|
|
::clang::ast_matchers::internal::TypeTraverseMatcher, \
|
|
ReturnTypesF>::Func MatcherName
|
|
|
|
#define AST_TYPE_TRAVERSE_MATCHER_DEF(MatcherName, ReturnTypesF) \
|
|
const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher< \
|
|
QualType, \
|
|
::clang::ast_matchers::internal::TypeMatcher##MatcherName##Getter, \
|
|
::clang::ast_matchers::internal::TypeTraverseMatcher, \
|
|
ReturnTypesF>::Func MatcherName
|
|
|
|
/// AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) defines
|
|
/// the matcher \c MatcherName that can be used to traverse from one \c Type
|
|
/// to another.
|
|
///
|
|
/// For a specific \c SpecificType, the traversal is done using
|
|
/// \c SpecificType::FunctionName. The existence of such a function determines
|
|
/// whether a corresponding matcher can be used on \c SpecificType.
|
|
#define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \
|
|
namespace internal { \
|
|
template <typename T> struct TypeMatcher##MatcherName##Getter { \
|
|
static QualType (T::*value())() const { return &T::FunctionName; } \
|
|
}; \
|
|
} \
|
|
const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher< \
|
|
QualType, \
|
|
::clang::ast_matchers::internal::TypeMatcher##MatcherName##Getter, \
|
|
::clang::ast_matchers::internal::TypeTraverseMatcher, \
|
|
ReturnTypesF>::Func MatcherName
|
|
|
|
#define AST_TYPELOC_TRAVERSE_MATCHER_DECL(MatcherName, FunctionName, \
|
|
ReturnTypesF) \
|
|
namespace internal { \
|
|
template <typename T> struct TypeLocMatcher##MatcherName##Getter { \
|
|
static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; } \
|
|
}; \
|
|
} \
|
|
extern const ::clang::ast_matchers::internal:: \
|
|
TypeTraversePolymorphicMatcher< \
|
|
TypeLoc, \
|
|
::clang::ast_matchers::internal:: \
|
|
TypeLocMatcher##MatcherName##Getter, \
|
|
::clang::ast_matchers::internal::TypeLocTraverseMatcher, \
|
|
ReturnTypesF>::Func MatcherName##Loc; \
|
|
AST_TYPE_TRAVERSE_MATCHER_DECL(MatcherName, FunctionName##Type, ReturnTypesF)
|
|
|
|
#define AST_TYPELOC_TRAVERSE_MATCHER_DEF(MatcherName, ReturnTypesF) \
|
|
const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher< \
|
|
TypeLoc, \
|
|
::clang::ast_matchers::internal::TypeLocMatcher##MatcherName##Getter, \
|
|
::clang::ast_matchers::internal::TypeLocTraverseMatcher, \
|
|
ReturnTypesF>::Func MatcherName##Loc; \
|
|
AST_TYPE_TRAVERSE_MATCHER_DEF(MatcherName, ReturnTypesF)
|
|
|
|
/// AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works
|
|
/// identical to \c AST_TYPE_TRAVERSE_MATCHER but operates on \c TypeLocs.
|
|
#define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \
|
|
namespace internal { \
|
|
template <typename T> struct TypeLocMatcher##MatcherName##Getter { \
|
|
static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; } \
|
|
}; \
|
|
} \
|
|
const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher< \
|
|
TypeLoc, \
|
|
::clang::ast_matchers::internal::TypeLocMatcher##MatcherName##Getter, \
|
|
::clang::ast_matchers::internal::TypeLocTraverseMatcher, \
|
|
ReturnTypesF>::Func MatcherName##Loc; \
|
|
AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type, ReturnTypesF)
|
|
|
|
/// AST_MATCHER_REGEX(Type, DefineMatcher, Param) { ... }
|
|
/// defines a function named DefineMatcher() that takes a regular expression
|
|
/// string paramater and an optional RegexFlags parameter and returns a
|
|
/// Matcher<Type> object.
|
|
///
|
|
/// The code between the curly braces has access to the following variables:
|
|
///
|
|
/// Node: the AST node being matched; its type is Type.
|
|
/// Param: a pointer to an \ref llvm::Regex object
|
|
/// Finder: an ASTMatchFinder*.
|
|
/// Builder: a BoundNodesTreeBuilder*.
|
|
///
|
|
/// The code should return true if 'Node' matches.
|
|
#define AST_MATCHER_REGEX(Type, DefineMatcher, Param) \
|
|
AST_MATCHER_REGEX_OVERLOAD(Type, DefineMatcher, Param, 0)
|
|
|
|
#define AST_MATCHER_REGEX_OVERLOAD(Type, DefineMatcher, Param, OverloadId) \
|
|
namespace internal { \
|
|
class matcher_##DefineMatcher##OverloadId##Matcher \
|
|
: public ::clang::ast_matchers::internal::MatcherInterface<Type> { \
|
|
public: \
|
|
explicit matcher_##DefineMatcher##OverloadId##Matcher( \
|
|
std::shared_ptr<llvm::Regex> RE) \
|
|
: Param(std::move(RE)) {} \
|
|
bool matches(const Type &Node, \
|
|
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
|
|
::clang::ast_matchers::internal::BoundNodesTreeBuilder \
|
|
*Builder) const override; \
|
|
\
|
|
private: \
|
|
std::shared_ptr<llvm::Regex> Param; \
|
|
}; \
|
|
} \
|
|
inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher( \
|
|
llvm::StringRef Param, llvm::Regex::RegexFlags RegexFlags) { \
|
|
return ::clang::ast_matchers::internal::makeMatcher( \
|
|
new internal::matcher_##DefineMatcher##OverloadId##Matcher( \
|
|
::clang::ast_matchers::internal::createAndVerifyRegex( \
|
|
Param, RegexFlags, #DefineMatcher))); \
|
|
} \
|
|
inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher( \
|
|
llvm::StringRef Param) { \
|
|
return DefineMatcher(Param, llvm::Regex::NoFlags); \
|
|
} \
|
|
\
|
|
typedef ::clang::ast_matchers::internal::Matcher<Type> ( \
|
|
&DefineMatcher##_Type##OverloadId##Flags)(llvm::StringRef, \
|
|
llvm::Regex::RegexFlags); \
|
|
typedef ::clang::ast_matchers::internal::Matcher<Type> ( \
|
|
&DefineMatcher##_Type##OverloadId)(llvm::StringRef); \
|
|
inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
|
|
const Type &Node, \
|
|
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
|
|
::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const
|
|
|
|
/// AST_POLYMORPHIC_MATCHER_REGEX(DefineMatcher, ReturnTypesF, Param) { ... }
|
|
/// defines a function named DefineMatcher() that takes a regular expression
|
|
/// string paramater and an optional RegexFlags parameter that is polymorphic in
|
|
/// the return type.
|
|
///
|
|
/// The variables are the same as for
|
|
/// AST_MATCHER_REGEX, with the addition of NodeType, which specifies the node
|
|
/// type of the matcher Matcher<NodeType> returned by the function matcher().
|
|
#define AST_POLYMORPHIC_MATCHER_REGEX(DefineMatcher, ReturnTypesF, Param) \
|
|
AST_POLYMORPHIC_MATCHER_REGEX_OVERLOAD(DefineMatcher, ReturnTypesF, Param, 0)
|
|
|
|
#define AST_POLYMORPHIC_MATCHER_REGEX_OVERLOAD(DefineMatcher, ReturnTypesF, \
|
|
Param, OverloadId) \
|
|
namespace internal { \
|
|
template <typename NodeType, typename ParamT> \
|
|
class matcher_##DefineMatcher##OverloadId##Matcher \
|
|
: public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \
|
|
public: \
|
|
explicit matcher_##DefineMatcher##OverloadId##Matcher( \
|
|
std::shared_ptr<llvm::Regex> RE) \
|
|
: Param(std::move(RE)) {} \
|
|
bool matches(const NodeType &Node, \
|
|
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
|
|
::clang::ast_matchers::internal::BoundNodesTreeBuilder \
|
|
*Builder) const override; \
|
|
\
|
|
private: \
|
|
std::shared_ptr<llvm::Regex> Param; \
|
|
}; \
|
|
} \
|
|
inline ::clang::ast_matchers::internal::PolymorphicMatcher< \
|
|
internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \
|
|
std::shared_ptr<llvm::Regex>> \
|
|
DefineMatcher(llvm::StringRef Param, llvm::Regex::RegexFlags RegexFlags) { \
|
|
return ::clang::ast_matchers::internal::PolymorphicMatcher< \
|
|
internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \
|
|
std::shared_ptr<llvm::Regex>>( \
|
|
::clang::ast_matchers::internal::createAndVerifyRegex( \
|
|
Param, RegexFlags, #DefineMatcher)); \
|
|
} \
|
|
inline ::clang::ast_matchers::internal::PolymorphicMatcher< \
|
|
internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \
|
|
std::shared_ptr<llvm::Regex>> \
|
|
DefineMatcher(llvm::StringRef Param) { \
|
|
return DefineMatcher(Param, llvm::Regex::NoFlags); \
|
|
} \
|
|
typedef ::clang::ast_matchers::internal::PolymorphicMatcher< \
|
|
internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \
|
|
std::shared_ptr<llvm::Regex>> ( \
|
|
&DefineMatcher##_Type##OverloadId##Flags)( \
|
|
llvm::StringRef Param, llvm::Regex::RegexFlags RegexFlags); \
|
|
typedef ::clang::ast_matchers::internal::PolymorphicMatcher< \
|
|
internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \
|
|
std::shared_ptr<llvm::Regex>> (&DefineMatcher##_Type##OverloadId)( \
|
|
llvm::StringRef Param); \
|
|
template <typename NodeType, typename ParamT> \
|
|
bool internal:: \
|
|
matcher_##DefineMatcher##OverloadId##Matcher<NodeType, ParamT>::matches( \
|
|
const NodeType &Node, \
|
|
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
|
|
::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) \
|
|
const
|
|
|
|
#endif // LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
|