blob: c68534acae355e6bb53db3d42fc1b1b682157aff [file] [log] [blame]
//===--- ASTMatchersMacros.h - Structural query framework -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// 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, always put it into the clang::ast_matchers
// namespace and refer to the internal types via the 'internal::':
//
// namespace clang {
// namespace ast_matchers {
// AST_MATCHER_P(MemberExpr, Member,
// internal::Matcher<ValueDecl>, InnerMatcher) {
// return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder);
// }
// } // end namespace ast_matchers
// } // end namespace clang
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
/// \brief 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 MatcherInterface<Type> { \
public: \
explicit matcher_##DefineMatcher##Matcher() {} \
virtual bool matches( \
const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
}; \
} \
inline internal::Matcher<Type> DefineMatcher() { \
return internal::makeMatcher( \
new internal::matcher_##DefineMatcher##Matcher()); \
} \
inline bool internal::matcher_##DefineMatcher##Matcher::matches( \
const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
/// \brief 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) \
namespace internal { \
class matcher_##DefineMatcher##Matcher \
: public MatcherInterface<Type> { \
public: \
explicit matcher_##DefineMatcher##Matcher( \
const ParamType &A##Param) : Param(A##Param) {} \
virtual bool matches( \
const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
private: \
const ParamType Param; \
}; \
} \
inline internal::Matcher<Type> DefineMatcher(const ParamType &Param) { \
return internal::makeMatcher( \
new internal::matcher_##DefineMatcher##Matcher(Param)); \
} \
inline bool internal::matcher_##DefineMatcher##Matcher::matches( \
const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
/// \brief 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) \
namespace internal { \
class matcher_##DefineMatcher##Matcher \
: public MatcherInterface<Type> { \
public: \
matcher_##DefineMatcher##Matcher( \
const ParamType1 &A##Param1, const ParamType2 &A##Param2) \
: Param1(A##Param1), Param2(A##Param2) {} \
virtual bool matches( \
const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
private: \
const ParamType1 Param1; \
const ParamType2 Param2; \
}; \
} \
inline internal::Matcher<Type> DefineMatcher( \
const ParamType1 &Param1, const ParamType2 &Param2) { \
return internal::makeMatcher( \
new internal::matcher_##DefineMatcher##Matcher( \
Param1, Param2)); \
} \
inline bool internal::matcher_##DefineMatcher##Matcher::matches( \
const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
/// \brief 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, ParamType, Param) \
namespace internal { \
template <typename NodeType, typename ParamT> \
class matcher_##DefineMatcher##Matcher \
: public MatcherInterface<NodeType> { \
public: \
explicit matcher_##DefineMatcher##Matcher( \
const ParamType &A##Param) : Param(A##Param) {} \
virtual bool matches( \
const NodeType &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
private: \
const ParamType Param; \
}; \
} \
inline internal::PolymorphicMatcherWithParam1< \
internal::matcher_##DefineMatcher##Matcher, \
ParamType > \
DefineMatcher(const ParamType &Param) { \
return internal::PolymorphicMatcherWithParam1< \
internal::matcher_##DefineMatcher##Matcher, \
ParamType >(Param); \
} \
template <typename NodeType, typename ParamT> \
bool internal::matcher_##DefineMatcher##Matcher<NodeType, ParamT>::matches( \
const NodeType &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
/// \brief 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, ParamType1, Param1, ParamType2, Param2) \
namespace internal { \
template <typename NodeType, typename ParamT1, typename ParamT2> \
class matcher_##DefineMatcher##Matcher \
: public MatcherInterface<NodeType> { \
public: \
matcher_##DefineMatcher##Matcher( \
const ParamType1 &A##Param1, const ParamType2 &A##Param2) \
: Param1(A##Param1), Param2(A##Param2) {} \
virtual bool matches( \
const NodeType &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
private: \
const ParamType1 Param1; \
const ParamType2 Param2; \
}; \
} \
inline internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##Matcher, \
ParamType1, ParamType2 > \
DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \
return internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##Matcher, \
ParamType1, ParamType2 >( \
Param1, Param2); \
} \
template <typename NodeType, typename ParamT1, typename ParamT2> \
bool internal::matcher_##DefineMatcher##Matcher< \
NodeType, ParamT1, ParamT2>::matches( \
const NodeType &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H