1 //===--- ASTMatchersMacros.h - Structural query framework -------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Defines macros that enable us to define new matchers in a single place. 11 // Since a matcher is a function which returns a Matcher<T> object, where 12 // T is the type of the actual implementation of the matcher, the macros allow 13 // us to write matchers like functions and take care of the definition of the 14 // class boilerplate. 15 // 16 // Note that when you define a matcher with an AST_MATCHER* macro, only the 17 // function which creates the matcher goes into the current namespace - the 18 // class that implements the actual matcher, which gets returned by the 19 // generator function, is put into the 'internal' namespace. This allows us 20 // to only have the functions (which is all the user cares about) in the 21 // 'ast_matchers' namespace and hide the boilerplate. 22 // 23 // To define a matcher in user code, always put it into the clang::ast_matchers 24 // namespace and refer to the internal types via the 'internal::': 25 // 26 // namespace clang { 27 // namespace ast_matchers { 28 // AST_MATCHER_P(MemberExpr, Member, 29 // internal::Matcher<ValueDecl>, InnerMatcher) { 30 // return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder); 31 // } 32 // } // end namespace ast_matchers 33 // } // end namespace clang 34 // 35 //===----------------------------------------------------------------------===// 36 37 #ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H 38 #define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H 39 40 /// \brief AST_MATCHER(Type, DefineMatcher) { ... } 41 /// defines a zero parameter function named DefineMatcher() that returns a 42 /// Matcher<Type> object. 43 /// 44 /// The code between the curly braces has access to the following variables: 45 /// 46 /// Node: the AST node being matched; its type is Type. 47 /// Finder: an ASTMatchFinder*. 48 /// Builder: a BoundNodesTreeBuilder*. 49 /// 50 /// The code should return true if 'Node' matches. 51 #define AST_MATCHER(Type, DefineMatcher) \ 52 namespace internal { \ 53 class matcher_##DefineMatcher##Matcher \ 54 : public MatcherInterface<Type> { \ 55 public: \ 56 explicit matcher_##DefineMatcher##Matcher() {} \ 57 virtual bool matches( \ 58 const Type &Node, ASTMatchFinder *Finder, \ 59 BoundNodesTreeBuilder *Builder) const; \ 60 }; \ 61 } \ 62 inline internal::Matcher<Type> DefineMatcher() { \ 63 return internal::makeMatcher( \ 64 new internal::matcher_##DefineMatcher##Matcher()); \ 65 } \ 66 inline bool internal::matcher_##DefineMatcher##Matcher::matches( \ 67 const Type &Node, ASTMatchFinder *Finder, \ 68 BoundNodesTreeBuilder *Builder) const 69 70 /// \brief AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... } 71 /// defines a single-parameter function named DefineMatcher() that returns a 72 /// Matcher<Type> object. 73 /// 74 /// The code between the curly braces has access to the following variables: 75 /// 76 /// Node: the AST node being matched; its type is Type. 77 /// Param: the parameter passed to the function; its type 78 /// is ParamType. 79 /// Finder: an ASTMatchFinder*. 80 /// Builder: a BoundNodesTreeBuilder*. 81 /// 82 /// The code should return true if 'Node' matches. 83 #define AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) \ 84 namespace internal { \ 85 class matcher_##DefineMatcher##Matcher \ 86 : public MatcherInterface<Type> { \ 87 public: \ 88 explicit matcher_##DefineMatcher##Matcher( \ 89 const ParamType &A##Param) : Param(A##Param) {} \ 90 virtual bool matches( \ 91 const Type &Node, ASTMatchFinder *Finder, \ 92 BoundNodesTreeBuilder *Builder) const; \ 93 private: \ 94 const ParamType Param; \ 95 }; \ 96 } \ 97 inline internal::Matcher<Type> DefineMatcher(const ParamType &Param) { \ 98 return internal::makeMatcher( \ 99 new internal::matcher_##DefineMatcher##Matcher(Param)); \ 100 } \ 101 inline bool internal::matcher_##DefineMatcher##Matcher::matches( \ 102 const Type &Node, ASTMatchFinder *Finder, \ 103 BoundNodesTreeBuilder *Builder) const 104 105 /// \brief AST_MATCHER_P2( 106 /// Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... } 107 /// defines a two-parameter function named DefineMatcher() that returns a 108 /// Matcher<Type> object. 109 /// 110 /// The code between the curly braces has access to the following variables: 111 /// 112 /// Node: the AST node being matched; its type is Type. 113 /// Param1, Param2: the parameters passed to the function; their types 114 /// are ParamType1 and ParamType2. 115 /// Finder: an ASTMatchFinder*. 116 /// Builder: a BoundNodesTreeBuilder*. 117 /// 118 /// The code should return true if 'Node' matches. 119 #define AST_MATCHER_P2( \ 120 Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) \ 121 namespace internal { \ 122 class matcher_##DefineMatcher##Matcher \ 123 : public MatcherInterface<Type> { \ 124 public: \ 125 matcher_##DefineMatcher##Matcher( \ 126 const ParamType1 &A##Param1, const ParamType2 &A##Param2) \ 127 : Param1(A##Param1), Param2(A##Param2) {} \ 128 virtual bool matches( \ 129 const Type &Node, ASTMatchFinder *Finder, \ 130 BoundNodesTreeBuilder *Builder) const; \ 131 private: \ 132 const ParamType1 Param1; \ 133 const ParamType2 Param2; \ 134 }; \ 135 } \ 136 inline internal::Matcher<Type> DefineMatcher( \ 137 const ParamType1 &Param1, const ParamType2 &Param2) { \ 138 return internal::makeMatcher( \ 139 new internal::matcher_##DefineMatcher##Matcher( \ 140 Param1, Param2)); \ 141 } \ 142 inline bool internal::matcher_##DefineMatcher##Matcher::matches( \ 143 const Type &Node, ASTMatchFinder *Finder, \ 144 BoundNodesTreeBuilder *Builder) const 145 146 /// \brief AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... } 147 /// defines a single-parameter function named DefineMatcher() that is 148 /// polymorphic in the return type. 149 /// 150 /// The variables are the same as for 151 /// AST_MATCHER_P, with the addition of NodeType, which specifies the node type 152 /// of the matcher Matcher<NodeType> returned by the function matcher(). 153 /// 154 /// FIXME: Pull out common code with above macro? 155 #define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) \ 156 namespace internal { \ 157 template <typename NodeType, typename ParamT> \ 158 class matcher_##DefineMatcher##Matcher \ 159 : public MatcherInterface<NodeType> { \ 160 public: \ 161 explicit matcher_##DefineMatcher##Matcher( \ 162 const ParamType &A##Param) : Param(A##Param) {} \ 163 virtual bool matches( \ 164 const NodeType &Node, ASTMatchFinder *Finder, \ 165 BoundNodesTreeBuilder *Builder) const; \ 166 private: \ 167 const ParamType Param; \ 168 }; \ 169 } \ 170 inline internal::PolymorphicMatcherWithParam1< \ 171 internal::matcher_##DefineMatcher##Matcher, \ 172 ParamType > \ 173 DefineMatcher(const ParamType &Param) { \ 174 return internal::PolymorphicMatcherWithParam1< \ 175 internal::matcher_##DefineMatcher##Matcher, \ 176 ParamType >(Param); \ 177 } \ 178 template <typename NodeType, typename ParamT> \ 179 bool internal::matcher_##DefineMatcher##Matcher<NodeType, ParamT>::matches( \ 180 const NodeType &Node, ASTMatchFinder *Finder, \ 181 BoundNodesTreeBuilder *Builder) const 182 183 /// \brief AST_POLYMORPHIC_MATCHER_P2( 184 /// DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... } 185 /// defines a two-parameter function named matcher() that is polymorphic in 186 /// the return type. 187 /// 188 /// The variables are the same as for AST_MATCHER_P2, with the 189 /// addition of NodeType, which specifies the node type of the matcher 190 /// Matcher<NodeType> returned by the function DefineMatcher(). 191 #define AST_POLYMORPHIC_MATCHER_P2( \ 192 DefineMatcher, ParamType1, Param1, ParamType2, Param2) \ 193 namespace internal { \ 194 template <typename NodeType, typename ParamT1, typename ParamT2> \ 195 class matcher_##DefineMatcher##Matcher \ 196 : public MatcherInterface<NodeType> { \ 197 public: \ 198 matcher_##DefineMatcher##Matcher( \ 199 const ParamType1 &A##Param1, const ParamType2 &A##Param2) \ 200 : Param1(A##Param1), Param2(A##Param2) {} \ 201 virtual bool matches( \ 202 const NodeType &Node, ASTMatchFinder *Finder, \ 203 BoundNodesTreeBuilder *Builder) const; \ 204 private: \ 205 const ParamType1 Param1; \ 206 const ParamType2 Param2; \ 207 }; \ 208 } \ 209 inline internal::PolymorphicMatcherWithParam2< \ 210 internal::matcher_##DefineMatcher##Matcher, \ 211 ParamType1, ParamType2 > \ 212 DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \ 213 return internal::PolymorphicMatcherWithParam2< \ 214 internal::matcher_##DefineMatcher##Matcher, \ 215 ParamType1, ParamType2 >( \ 216 Param1, Param2); \ 217 } \ 218 template <typename NodeType, typename ParamT1, typename ParamT2> \ 219 bool internal::matcher_##DefineMatcher##Matcher< \ 220 NodeType, ParamT1, ParamT2>::matches( \ 221 const NodeType &Node, ASTMatchFinder *Finder, \ 222 BoundNodesTreeBuilder *Builder) const 223 224 #endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H 225