| //===--- 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 |