//===--- 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 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, 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 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) \ AST_MATCHER_OVERLOAD(Type, DefineMatcher, 0) #define AST_MATCHER_OVERLOAD(Type, DefineMatcher, OverloadId) \ namespace internal { \ class matcher_##DefineMatcher##OverloadId##Matcher \ : public MatcherInterface { \ public: \ explicit matcher_##DefineMatcher##OverloadId##Matcher() {} \ virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \ BoundNodesTreeBuilder *Builder) const; \ }; \ } \ inline internal::Matcher DefineMatcher() { \ return internal::makeMatcher( \ new internal::matcher_##DefineMatcher##OverloadId##Matcher()); \ } \ inline bool internal::matcher_##DefineMatcher##OverloadId##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 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 MatcherInterface { \ public: \ explicit matcher_##DefineMatcher##OverloadId##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 DefineMatcher(const ParamType &Param) { \ return internal::makeMatcher( \ new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param)); \ } \ inline bool internal::matcher_##DefineMatcher##OverloadId##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 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 MatcherInterface { \ public: \ matcher_##DefineMatcher##OverloadId##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 \ DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \ return internal::makeMatcher( \ new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1, \ Param2)); \ } \ inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \ const Type &Node, ASTMatchFinder *Finder, \ BoundNodesTreeBuilder *Builder) const /// \brief 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) \ AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, 0) #define AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, OverloadId) \ namespace internal { \ template \ class matcher_##DefineMatcher##OverloadId##Matcher \ : public MatcherInterface { \ public: \ virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \ BoundNodesTreeBuilder *Builder) const; \ }; \ } \ inline internal::PolymorphicMatcherWithParam0< \ internal::matcher_##DefineMatcher##OverloadId##Matcher> DefineMatcher() {\ return internal::PolymorphicMatcherWithParam0< \ internal::matcher_##DefineMatcher##OverloadId##Matcher>(); \ } \ template \ bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \ NodeType>::matches(const NodeType &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 returned by the function matcher(). /// /// FIXME: Pull out common code with above macro? #define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) \ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ParamType, Param, 0) #define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ParamType, Param, \ OverloadId) \ namespace internal { \ template \ class matcher_##DefineMatcher##OverloadId##Matcher \ : public MatcherInterface { \ public: \ explicit matcher_##DefineMatcher##OverloadId##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##OverloadId##Matcher, ParamType> \ DefineMatcher(const ParamType &Param) { \ return internal::PolymorphicMatcherWithParam1< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType>( \ Param); \ } \ template \ bool internal::matcher_##DefineMatcher##OverloadId##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 returned by the function DefineMatcher(). #define AST_POLYMORPHIC_MATCHER_P2(DefineMatcher, ParamType1, Param1, \ ParamType2, Param2) \ AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ParamType1, Param1, \ ParamType2, Param2, 0) #define AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ParamType1, Param1, \ ParamType2, Param2, OverloadId) \ namespace internal { \ template \ class matcher_##DefineMatcher##OverloadId##Matcher \ : public MatcherInterface { \ public: \ matcher_##DefineMatcher##OverloadId##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##OverloadId##Matcher, ParamType1, \ ParamType2> \ DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \ return internal::PolymorphicMatcherWithParam2< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ ParamType2>(Param1, Param2); \ } \ template \ bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \ NodeType, ParamT1, ParamT2>::matches( \ const NodeType &Node, ASTMatchFinder *Finder, \ BoundNodesTreeBuilder *Builder) const /// \brief Creates a variadic matcher for both a specific \c Type as well as /// the corresponding \c TypeLoc. #define AST_TYPE_MATCHER(NodeType, MatcherName) \ const internal::VariadicDynCastAllOfMatcher MatcherName // FIXME: add a matcher for TypeLoc derived classes using its custom casting // API (no longer dyn_cast) if/when we need such matching /// \brief 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 existance of such a function determines /// whether a corresponding matcher can be used on \c SpecificType. #define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) \ class Polymorphic##MatcherName##TypeMatcher { \ public: \ Polymorphic##MatcherName##TypeMatcher( \ const internal::Matcher &InnerMatcher) \ : InnerMatcher(InnerMatcher) { \ } \ template operator internal:: Matcher< T>() { \ return internal::Matcher(new internal::TypeTraverseMatcher( \ InnerMatcher, &T::FunctionName)); \ } \ private: \ const internal::Matcher InnerMatcher; \ } \ ; \ class Variadic##MatcherName##TypeTraverseMatcher \ : public llvm::VariadicFunction< \ Polymorphic##MatcherName##TypeMatcher, internal::Matcher, \ internal::makeTypeAllOfComposite< \ Polymorphic##MatcherName##TypeMatcher, QualType> > { \ public: \ Variadic##MatcherName##TypeTraverseMatcher() { \ } \ } \ ; \ const Variadic##MatcherName##TypeTraverseMatcher MatcherName /// \brief 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) \ class Polymorphic##MatcherName##TypeLocMatcher { \ public: \ Polymorphic##MatcherName##TypeLocMatcher( \ const internal::Matcher &InnerMatcher) \ : InnerMatcher(InnerMatcher) { \ } \ template operator internal:: Matcher< T>() { \ return internal::Matcher( \ new internal::TypeLocTraverseMatcher(InnerMatcher, \ &T::FunctionName##Loc)); \ } \ private: \ const internal::Matcher InnerMatcher; \ } \ ; \ class Variadic##MatcherName##TypeLocTraverseMatcher \ : public llvm::VariadicFunction< \ Polymorphic##MatcherName##TypeLocMatcher, internal::Matcher,\ internal::makeTypeAllOfComposite< \ Polymorphic##MatcherName##TypeLocMatcher, TypeLoc> > { \ public: \ Variadic##MatcherName##TypeLocTraverseMatcher() { \ } \ } \ ; \ const Variadic##MatcherName##TypeLocTraverseMatcher MatcherName##Loc; \ AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type) #endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H