1 | //===--- ASTMatchersMacros.h - Structural query framework -------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Defines macros that enable us to define new matchers in a single place. |
10 | // Since a matcher is a function which returns a Matcher<T> object, where |
11 | // T is the type of the actual implementation of the matcher, the macros allow |
12 | // us to write matchers like functions and take care of the definition of the |
13 | // class boilerplate. |
14 | // |
15 | // Note that when you define a matcher with an AST_MATCHER* macro, only the |
16 | // function which creates the matcher goes into the current namespace - the |
17 | // class that implements the actual matcher, which gets returned by the |
18 | // generator function, is put into the 'internal' namespace. This allows us |
19 | // to only have the functions (which is all the user cares about) in the |
20 | // 'ast_matchers' namespace and hide the boilerplate. |
21 | // |
22 | // To define a matcher in user code, put it into your own namespace. This would |
23 | // help to prevent ODR violations in case a matcher with the same name is |
24 | // defined in multiple translation units: |
25 | // |
26 | // namespace my_matchers { |
27 | // AST_MATCHER_P(clang::MemberExpr, Member, |
28 | // clang::ast_matchers::internal::Matcher<clang::ValueDecl>, |
29 | // InnerMatcher) { |
30 | // return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder); |
31 | // } |
32 | // } // namespace my_matchers |
33 | // |
34 | // Alternatively, an unnamed namespace may be used: |
35 | // |
36 | // namespace clang { |
37 | // namespace ast_matchers { |
38 | // namespace { |
39 | // AST_MATCHER_P(MemberExpr, Member, |
40 | // internal::Matcher<ValueDecl>, InnerMatcher) { |
41 | // return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder); |
42 | // } |
43 | // } // namespace |
44 | // } // namespace ast_matchers |
45 | // } // namespace clang |
46 | // |
47 | //===----------------------------------------------------------------------===// |
48 | |
49 | #ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H |
50 | #define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H |
51 | |
52 | /// AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) { ... } |
53 | /// defines a zero parameter function named DefineMatcher() that returns a |
54 | /// ReturnType object. |
55 | #define AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) \ |
56 | inline ReturnType DefineMatcher##_getInstance(); \ |
57 | inline ReturnType DefineMatcher() { \ |
58 | return ::clang::ast_matchers::internal::MemoizedMatcher< \ |
59 | ReturnType, DefineMatcher##_getInstance>::getInstance(); \ |
60 | } \ |
61 | inline ReturnType DefineMatcher##_getInstance() |
62 | |
63 | /// AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) { |
64 | /// ... } |
65 | /// defines a single-parameter function named DefineMatcher() that returns a |
66 | /// ReturnType object. |
67 | /// |
68 | /// The code between the curly braces has access to the following variables: |
69 | /// |
70 | /// Param: the parameter passed to the function; its type |
71 | /// is ParamType. |
72 | /// |
73 | /// The code should return an instance of ReturnType. |
74 | #define AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) \ |
75 | AST_MATCHER_FUNCTION_P_OVERLOAD(ReturnType, DefineMatcher, ParamType, Param, \ |
76 | 0) |
77 | #define AST_MATCHER_FUNCTION_P_OVERLOAD(ReturnType, DefineMatcher, ParamType, \ |
78 | Param, OverloadId) \ |
79 | inline ReturnType DefineMatcher(ParamType const &Param); \ |
80 | typedef ReturnType (&DefineMatcher##_Type##OverloadId)(ParamType const &); \ |
81 | inline ReturnType DefineMatcher(ParamType const &Param) |
82 | |
83 | /// AST_MATCHER(Type, DefineMatcher) { ... } |
84 | /// defines a zero parameter function named DefineMatcher() that returns a |
85 | /// Matcher<Type> object. |
86 | /// |
87 | /// The code between the curly braces has access to the following variables: |
88 | /// |
89 | /// Node: the AST node being matched; its type is Type. |
90 | /// Finder: an ASTMatchFinder*. |
91 | /// Builder: a BoundNodesTreeBuilder*. |
92 | /// |
93 | /// The code should return true if 'Node' matches. |
94 | #define AST_MATCHER(Type, DefineMatcher) \ |
95 | namespace internal { \ |
96 | class matcher_##DefineMatcher##Matcher \ |
97 | : public ::clang::ast_matchers::internal::MatcherInterface<Type> { \ |
98 | public: \ |
99 | explicit matcher_##DefineMatcher##Matcher() = default; \ |
100 | bool matches(const Type &Node, \ |
101 | ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ |
102 | ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ |
103 | *Builder) const override; \ |
104 | }; \ |
105 | } \ |
106 | inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher() { \ |
107 | return ::clang::ast_matchers::internal::makeMatcher( \ |
108 | new internal::matcher_##DefineMatcher##Matcher()); \ |
109 | } \ |
110 | inline bool internal::matcher_##DefineMatcher##Matcher::matches( \ |
111 | const Type &Node, \ |
112 | ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ |
113 | ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const |
114 | |
115 | /// AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... } |
116 | /// defines a single-parameter function named DefineMatcher() that returns a |
117 | /// Matcher<Type> object. |
118 | /// |
119 | /// The code between the curly braces has access to the following variables: |
120 | /// |
121 | /// Node: the AST node being matched; its type is Type. |
122 | /// Param: the parameter passed to the function; its type |
123 | /// is ParamType. |
124 | /// Finder: an ASTMatchFinder*. |
125 | /// Builder: a BoundNodesTreeBuilder*. |
126 | /// |
127 | /// The code should return true if 'Node' matches. |
128 | #define AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) \ |
129 | AST_MATCHER_P_OVERLOAD(Type, DefineMatcher, ParamType, Param, 0) |
130 | |
131 | #define AST_MATCHER_P_OVERLOAD(Type, DefineMatcher, ParamType, Param, \ |
132 | OverloadId) \ |
133 | namespace internal { \ |
134 | class matcher_##DefineMatcher##OverloadId##Matcher \ |
135 | : public ::clang::ast_matchers::internal::MatcherInterface<Type> { \ |
136 | public: \ |
137 | explicit matcher_##DefineMatcher##OverloadId##Matcher( \ |
138 | ParamType const &A##Param) \ |
139 | : Param(A##Param) {} \ |
140 | bool matches(const Type &Node, \ |
141 | ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ |
142 | ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ |
143 | *Builder) const override; \ |
144 | \ |
145 | private: \ |
146 | ParamType const Param; \ |
147 | }; \ |
148 | } \ |
149 | inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher( \ |
150 | ParamType const &Param) { \ |
151 | return ::clang::ast_matchers::internal::makeMatcher( \ |
152 | new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param)); \ |
153 | } \ |
154 | typedef ::clang::ast_matchers::internal::Matcher<Type>( \ |
155 | &DefineMatcher##_Type##OverloadId)(ParamType const &Param); \ |
156 | inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \ |
157 | const Type &Node, \ |
158 | ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ |
159 | ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const |
160 | |
161 | /// AST_MATCHER_P2( |
162 | /// Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... } |
163 | /// defines a two-parameter function named DefineMatcher() that returns a |
164 | /// Matcher<Type> object. |
165 | /// |
166 | /// The code between the curly braces has access to the following variables: |
167 | /// |
168 | /// Node: the AST node being matched; its type is Type. |
169 | /// Param1, Param2: the parameters passed to the function; their types |
170 | /// are ParamType1 and ParamType2. |
171 | /// Finder: an ASTMatchFinder*. |
172 | /// Builder: a BoundNodesTreeBuilder*. |
173 | /// |
174 | /// The code should return true if 'Node' matches. |
175 | #define AST_MATCHER_P2(Type, DefineMatcher, ParamType1, Param1, ParamType2, \ |
176 | Param2) \ |
177 | AST_MATCHER_P2_OVERLOAD(Type, DefineMatcher, ParamType1, Param1, ParamType2, \ |
178 | Param2, 0) |
179 | |
180 | #define AST_MATCHER_P2_OVERLOAD(Type, DefineMatcher, ParamType1, Param1, \ |
181 | ParamType2, Param2, OverloadId) \ |
182 | namespace internal { \ |
183 | class matcher_##DefineMatcher##OverloadId##Matcher \ |
184 | : public ::clang::ast_matchers::internal::MatcherInterface<Type> { \ |
185 | public: \ |
186 | matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \ |
187 | ParamType2 const &A##Param2) \ |
188 | : Param1(A##Param1), Param2(A##Param2) {} \ |
189 | bool matches(const Type &Node, \ |
190 | ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ |
191 | ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ |
192 | *Builder) const override; \ |
193 | \ |
194 | private: \ |
195 | ParamType1 const Param1; \ |
196 | ParamType2 const Param2; \ |
197 | }; \ |
198 | } \ |
199 | inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher( \ |
200 | ParamType1 const &Param1, ParamType2 const &Param2) { \ |
201 | return ::clang::ast_matchers::internal::makeMatcher( \ |
202 | new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1, \ |
203 | Param2)); \ |
204 | } \ |
205 | typedef ::clang::ast_matchers::internal::Matcher<Type>( \ |
206 | &DefineMatcher##_Type##OverloadId)(ParamType1 const &Param1, \ |
207 | ParamType2 const &Param2); \ |
208 | inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \ |
209 | const Type &Node, \ |
210 | ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ |
211 | ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const |
212 | |
213 | /// Construct a type-list to be passed to the AST_POLYMORPHIC_MATCHER* |
214 | /// macros. |
215 | /// |
216 | /// You can't pass something like \c TypeList<Foo, Bar> to a macro, because it |
217 | /// will look at that as two arguments. However, you can pass |
218 | /// \c void(TypeList<Foo, Bar>), which works thanks to the parenthesis. |
219 | /// The \c PolymorphicMatcherWithParam* classes will unpack the function type to |
220 | /// extract the TypeList object. |
221 | #define AST_POLYMORPHIC_SUPPORTED_TYPES(...) \ |
222 | void(::clang::ast_matchers::internal::TypeList<__VA_ARGS__>) |
223 | |
224 | /// AST_POLYMORPHIC_MATCHER(DefineMatcher) { ... } |
225 | /// defines a single-parameter function named DefineMatcher() that is |
226 | /// polymorphic in the return type. |
227 | /// |
228 | /// The variables are the same as for AST_MATCHER, but NodeType will be deduced |
229 | /// from the calling context. |
230 | #define AST_POLYMORPHIC_MATCHER(DefineMatcher, ReturnTypesF) \ |
231 | namespace internal { \ |
232 | template <typename NodeType> \ |
233 | class matcher_##DefineMatcher##Matcher \ |
234 | : public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \ |
235 | public: \ |
236 | bool matches(const NodeType &Node, \ |
237 | ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ |
238 | ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ |
239 | *Builder) const override; \ |
240 | }; \ |
241 | } \ |
242 | inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam0< \ |
243 | internal::matcher_##DefineMatcher##Matcher, ReturnTypesF> \ |
244 | DefineMatcher() { \ |
245 | return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam0< \ |
246 | internal::matcher_##DefineMatcher##Matcher, ReturnTypesF>(); \ |
247 | } \ |
248 | template <typename NodeType> \ |
249 | bool internal::matcher_##DefineMatcher##Matcher<NodeType>::matches( \ |
250 | const NodeType &Node, \ |
251 | ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ |
252 | ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const |
253 | |
254 | /// AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... } |
255 | /// defines a single-parameter function named DefineMatcher() that is |
256 | /// polymorphic in the return type. |
257 | /// |
258 | /// The variables are the same as for |
259 | /// AST_MATCHER_P, with the addition of NodeType, which specifies the node type |
260 | /// of the matcher Matcher<NodeType> returned by the function matcher(). |
261 | /// |
262 | /// FIXME: Pull out common code with above macro? |
263 | #define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ReturnTypesF, ParamType, \ |
264 | Param) \ |
265 | AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType, \ |
266 | Param, 0) |
267 | |
268 | #define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF, \ |
269 | ParamType, Param, OverloadId) \ |
270 | namespace internal { \ |
271 | template <typename NodeType, typename ParamT> \ |
272 | class matcher_##DefineMatcher##OverloadId##Matcher \ |
273 | : public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \ |
274 | public: \ |
275 | explicit matcher_##DefineMatcher##OverloadId##Matcher( \ |
276 | ParamType const &A##Param) \ |
277 | : Param(A##Param) {} \ |
278 | bool matches(const NodeType &Node, \ |
279 | ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ |
280 | ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ |
281 | *Builder) const override; \ |
282 | \ |
283 | private: \ |
284 | ParamType const Param; \ |
285 | }; \ |
286 | } \ |
287 | inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \ |
288 | internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \ |
289 | ReturnTypesF> \ |
290 | DefineMatcher(ParamType const &Param) { \ |
291 | return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \ |
292 | internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \ |
293 | ReturnTypesF>(Param); \ |
294 | } \ |
295 | typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \ |
296 | internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \ |
297 | ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \ |
298 | ParamType const &Param); \ |
299 | template <typename NodeType, typename ParamT> \ |
300 | bool internal:: \ |
301 | matcher_##DefineMatcher##OverloadId##Matcher<NodeType, ParamT>::matches( \ |
302 | const NodeType &Node, \ |
303 | ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ |
304 | ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) \ |
305 | const |
306 | |
307 | /// AST_POLYMORPHIC_MATCHER_P2( |
308 | /// DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... } |
309 | /// defines a two-parameter function named matcher() that is polymorphic in |
310 | /// the return type. |
311 | /// |
312 | /// The variables are the same as for AST_MATCHER_P2, with the |
313 | /// addition of NodeType, which specifies the node type of the matcher |
314 | /// Matcher<NodeType> returned by the function DefineMatcher(). |
315 | #define AST_POLYMORPHIC_MATCHER_P2(DefineMatcher, ReturnTypesF, ParamType1, \ |
316 | Param1, ParamType2, Param2) \ |
317 | AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType1, \ |
318 | Param1, ParamType2, Param2, 0) |
319 | |
320 | #define AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ReturnTypesF, \ |
321 | ParamType1, Param1, ParamType2, \ |
322 | Param2, OverloadId) \ |
323 | namespace internal { \ |
324 | template <typename NodeType, typename ParamT1, typename ParamT2> \ |
325 | class matcher_##DefineMatcher##OverloadId##Matcher \ |
326 | : public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \ |
327 | public: \ |
328 | matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \ |
329 | ParamType2 const &A##Param2) \ |
330 | : Param1(A##Param1), Param2(A##Param2) {} \ |
331 | bool matches(const NodeType &Node, \ |
332 | ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ |
333 | ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ |
334 | *Builder) const override; \ |
335 | \ |
336 | private: \ |
337 | ParamType1 const Param1; \ |
338 | ParamType2 const Param2; \ |
339 | }; \ |
340 | } \ |
341 | inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \ |
342 | internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ |
343 | ParamType2, ReturnTypesF> \ |
344 | DefineMatcher(ParamType1 const &Param1, ParamType2 const &Param2) { \ |
345 | return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \ |
346 | internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ |
347 | ParamType2, ReturnTypesF>(Param1, Param2); \ |
348 | } \ |
349 | typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \ |
350 | internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ |
351 | ParamType2, ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \ |
352 | ParamType1 const &Param1, ParamType2 const &Param2); \ |
353 | template <typename NodeType, typename ParamT1, typename ParamT2> \ |
354 | bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \ |
355 | NodeType, ParamT1, ParamT2>:: \ |
356 | matches(const NodeType &Node, \ |
357 | ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ |
358 | ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) \ |
359 | const |
360 | |
361 | // FIXME: add a matcher for TypeLoc derived classes using its custom casting |
362 | // API (no longer dyn_cast) if/when we need such matching |
363 | |
364 | #define AST_TYPE_TRAVERSE_MATCHER_DECL(MatcherName, FunctionName, \ |
365 | ReturnTypesF) \ |
366 | namespace internal { \ |
367 | template <typename T> struct TypeMatcher##MatcherName##Getter { \ |
368 | static QualType (T::*value())() const { return &T::FunctionName; } \ |
369 | }; \ |
370 | } \ |
371 | extern const ::clang::ast_matchers::internal:: \ |
372 | TypeTraversePolymorphicMatcher< \ |
373 | QualType, \ |
374 | ::clang::ast_matchers::internal::TypeMatcher##MatcherName##Getter, \ |
375 | ::clang::ast_matchers::internal::TypeTraverseMatcher, \ |
376 | ReturnTypesF>::Func MatcherName |
377 | |
378 | #define AST_TYPE_TRAVERSE_MATCHER_DEF(MatcherName, ReturnTypesF) \ |
379 | const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher< \ |
380 | QualType, \ |
381 | ::clang::ast_matchers::internal::TypeMatcher##MatcherName##Getter, \ |
382 | ::clang::ast_matchers::internal::TypeTraverseMatcher, \ |
383 | ReturnTypesF>::Func MatcherName |
384 | |
385 | /// AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) defines |
386 | /// the matcher \c MatcherName that can be used to traverse from one \c Type |
387 | /// to another. |
388 | /// |
389 | /// For a specific \c SpecificType, the traversal is done using |
390 | /// \c SpecificType::FunctionName. The existence of such a function determines |
391 | /// whether a corresponding matcher can be used on \c SpecificType. |
392 | #define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \ |
393 | namespace internal { \ |
394 | template <typename T> struct TypeMatcher##MatcherName##Getter { \ |
395 | static QualType (T::*value())() const { return &T::FunctionName; } \ |
396 | }; \ |
397 | } \ |
398 | const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher< \ |
399 | QualType, \ |
400 | ::clang::ast_matchers::internal::TypeMatcher##MatcherName##Getter, \ |
401 | ::clang::ast_matchers::internal::TypeTraverseMatcher, \ |
402 | ReturnTypesF>::Func MatcherName |
403 | |
404 | #define AST_TYPELOC_TRAVERSE_MATCHER_DECL(MatcherName, FunctionName, \ |
405 | ReturnTypesF) \ |
406 | namespace internal { \ |
407 | template <typename T> struct TypeLocMatcher##MatcherName##Getter { \ |
408 | static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; } \ |
409 | }; \ |
410 | } \ |
411 | extern const ::clang::ast_matchers::internal:: \ |
412 | TypeTraversePolymorphicMatcher< \ |
413 | TypeLoc, \ |
414 | ::clang::ast_matchers::internal:: \ |
415 | TypeLocMatcher##MatcherName##Getter, \ |
416 | ::clang::ast_matchers::internal::TypeLocTraverseMatcher, \ |
417 | ReturnTypesF>::Func MatcherName##Loc; \ |
418 | AST_TYPE_TRAVERSE_MATCHER_DECL(MatcherName, FunctionName##Type, ReturnTypesF) |
419 | |
420 | #define AST_TYPELOC_TRAVERSE_MATCHER_DEF(MatcherName, ReturnTypesF) \ |
421 | const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher< \ |
422 | TypeLoc, \ |
423 | ::clang::ast_matchers::internal::TypeLocMatcher##MatcherName##Getter, \ |
424 | ::clang::ast_matchers::internal::TypeLocTraverseMatcher, \ |
425 | ReturnTypesF>::Func MatcherName##Loc; \ |
426 | AST_TYPE_TRAVERSE_MATCHER_DEF(MatcherName, ReturnTypesF) |
427 | |
428 | /// AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works |
429 | /// identical to \c AST_TYPE_TRAVERSE_MATCHER but operates on \c TypeLocs. |
430 | #define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \ |
431 | namespace internal { \ |
432 | template <typename T> struct TypeLocMatcher##MatcherName##Getter { \ |
433 | static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; } \ |
434 | }; \ |
435 | } \ |
436 | const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher< \ |
437 | TypeLoc, \ |
438 | ::clang::ast_matchers::internal::TypeLocMatcher##MatcherName##Getter, \ |
439 | ::clang::ast_matchers::internal::TypeLocTraverseMatcher, \ |
440 | ReturnTypesF>::Func MatcherName##Loc; \ |
441 | AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type, ReturnTypesF) |
442 | |
443 | #endif // LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H |
444 | |