summaryrefslogtreecommitdiffstats
path: root/include/clang/ASTMatchers/ASTMatchersMacros.h
blob: 1d96ba6231cf0d5a8c1aa8211c356af109c37e62 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
//===--- ASTMatchersMacros.h - Structural query framework -------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  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, put it into your own namespace. This would
//  help to prevent ODR violations in case a matcher with the same name is
//  defined in multiple translation units:
//
//  namespace my_matchers {
//  AST_MATCHER_P(clang::MemberExpr, Member,
//                clang::ast_matchers::internal::Matcher<clang::ValueDecl>,
//                InnerMatcher) {
//    return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder);
//  }
//  } // namespace my_matchers
//
//  Alternatively, an unnamed namespace may be used:
//
//  namespace clang {
//  namespace ast_matchers {
//  namespace {
//  AST_MATCHER_P(MemberExpr, Member,
//                internal::Matcher<ValueDecl>, InnerMatcher) {
//    return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder);
//  }
//  } // namespace
//  } // namespace ast_matchers
//  } // namespace clang
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H

/// AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) { ... }
/// defines a zero parameter function named DefineMatcher() that returns a
/// ReturnType object.
#define AST_MATCHER_FUNCTION(ReturnType, DefineMatcher)                        \
  inline ReturnType DefineMatcher##_getInstance();                             \
  inline ReturnType DefineMatcher() {                                          \
    return ::clang::ast_matchers::internal::MemoizedMatcher<                   \
        ReturnType, DefineMatcher##_getInstance>::getInstance();               \
  }                                                                            \
  inline ReturnType DefineMatcher##_getInstance()

/// AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) {
/// ... }
/// defines a single-parameter function named DefineMatcher() that returns a
/// ReturnType object.
///
/// The code between the curly braces has access to the following variables:
///
///   Param:                 the parameter passed to the function; its type
///                          is ParamType.
///
/// The code should return an instance of ReturnType.
#define AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param)    \
  AST_MATCHER_FUNCTION_P_OVERLOAD(ReturnType, DefineMatcher, ParamType, Param, \
                                  0)
#define AST_MATCHER_FUNCTION_P_OVERLOAD(ReturnType, DefineMatcher, ParamType,  \
                                        Param, OverloadId)                     \
  inline ReturnType DefineMatcher(ParamType const &Param);                     \
  typedef ReturnType (&DefineMatcher##_Type##OverloadId)(ParamType const &);   \
  inline ReturnType DefineMatcher(ParamType const &Param)

/// 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 ::clang::ast_matchers::internal::MatcherInterface<Type> {       \
  public:                                                                      \
    explicit matcher_##DefineMatcher##Matcher() = default;                     \
    bool matches(const Type &Node,                                             \
                 ::clang::ast_matchers::internal::ASTMatchFinder *Finder,      \
                 ::clang::ast_matchers::internal::BoundNodesTreeBuilder        \
                     *Builder) const override;                                 \
  };                                                                           \
  }                                                                            \
  inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher() {      \
    return ::clang::ast_matchers::internal::makeMatcher(                       \
        new internal::matcher_##DefineMatcher##Matcher());                     \
  }                                                                            \
  inline bool internal::matcher_##DefineMatcher##Matcher::matches(             \
      const Type &Node,                                                        \
      ::clang::ast_matchers::internal::ASTMatchFinder *Finder,                 \
      ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const

/// 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)                   \
  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 ::clang::ast_matchers::internal::MatcherInterface<Type> {       \
  public:                                                                      \
    explicit matcher_##DefineMatcher##OverloadId##Matcher(                     \
        ParamType const &A##Param)                                             \
        : Param(A##Param) {}                                                   \
    bool matches(const Type &Node,                                             \
                 ::clang::ast_matchers::internal::ASTMatchFinder *Finder,      \
                 ::clang::ast_matchers::internal::BoundNodesTreeBuilder        \
                     *Builder) const override;                                 \
                                                                               \
  private:                                                                     \
    ParamType const Param;                                                     \
  };                                                                           \
  }                                                                            \
  inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher(         \
      ParamType const &Param) {                                                \
    return ::clang::ast_matchers::internal::makeMatcher(                       \
        new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param));    \
  }                                                                            \
  typedef ::clang::ast_matchers::internal::Matcher<Type>(                      \
      &DefineMatcher##_Type##OverloadId)(ParamType const &Param);              \
  inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
      const Type &Node,                                                        \
      ::clang::ast_matchers::internal::ASTMatchFinder *Finder,                 \
      ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const

/// 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)                                                 \
  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 ::clang::ast_matchers::internal::MatcherInterface<Type> {       \
  public:                                                                      \
    matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1,  \
                                                 ParamType2 const &A##Param2)  \
        : Param1(A##Param1), Param2(A##Param2) {}                              \
    bool matches(const Type &Node,                                             \
                 ::clang::ast_matchers::internal::ASTMatchFinder *Finder,      \
                 ::clang::ast_matchers::internal::BoundNodesTreeBuilder        \
                     *Builder) const override;                                 \
                                                                               \
  private:                                                                     \
    ParamType1 const Param1;                                                   \
    ParamType2 const Param2;                                                   \
  };                                                                           \
  }                                                                            \
  inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher(         \
      ParamType1 const &Param1, ParamType2 const &Param2) {                    \
    return ::clang::ast_matchers::internal::makeMatcher(                       \
        new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1,     \
                                                                   Param2));   \
  }                                                                            \
  typedef ::clang::ast_matchers::internal::Matcher<Type>(                      \
      &DefineMatcher##_Type##OverloadId)(ParamType1 const &Param1,             \
                                         ParamType2 const &Param2);            \
  inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
      const Type &Node,                                                        \
      ::clang::ast_matchers::internal::ASTMatchFinder *Finder,                 \
      ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const

/// Construct a type-list to be passed to the AST_POLYMORPHIC_MATCHER*
///   macros.
///
/// You can't pass something like \c TypeList<Foo, Bar> to a macro, because it
/// will look at that as two arguments. However, you can pass
/// \c void(TypeList<Foo, Bar>), which works thanks to the parenthesis.
/// The \c PolymorphicMatcherWithParam* classes will unpack the function type to
/// extract the TypeList object.
#define AST_POLYMORPHIC_SUPPORTED_TYPES(...)                                   \
  void(::clang::ast_matchers::internal::TypeList<__VA_ARGS__>)

/// 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, ReturnTypesF)                   \
  namespace internal {                                                         \
  template <typename NodeType>                                                 \
  class matcher_##DefineMatcher##Matcher                                       \
      : public ::clang::ast_matchers::internal::MatcherInterface<NodeType> {   \
  public:                                                                      \
    bool matches(const NodeType &Node,                                         \
                 ::clang::ast_matchers::internal::ASTMatchFinder *Finder,      \
                 ::clang::ast_matchers::internal::BoundNodesTreeBuilder        \
                     *Builder) const override;                                 \
  };                                                                           \
  }                                                                            \
  inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam0<        \
      internal::matcher_##DefineMatcher##Matcher, ReturnTypesF>                \
  DefineMatcher() {                                                            \
    return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam0<      \
        internal::matcher_##DefineMatcher##Matcher, ReturnTypesF>();           \
  }                                                                            \
  template <typename NodeType>                                                 \
  bool internal::matcher_##DefineMatcher##Matcher<NodeType>::matches(          \
      const NodeType &Node,                                                    \
      ::clang::ast_matchers::internal::ASTMatchFinder *Finder,                 \
      ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const

/// 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, ReturnTypesF, ParamType,      \
                                  Param)                                       \
  AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType,   \
                                     Param, 0)

#define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF,        \
                                           ParamType, Param, OverloadId)       \
  namespace internal {                                                         \
  template <typename NodeType, typename ParamT>                                \
  class matcher_##DefineMatcher##OverloadId##Matcher                           \
      : public ::clang::ast_matchers::internal::MatcherInterface<NodeType> {   \
  public:                                                                      \
    explicit matcher_##DefineMatcher##OverloadId##Matcher(                     \
        ParamType const &A##Param)                                             \
        : Param(A##Param) {}                                                   \
    bool matches(const NodeType &Node,                                         \
                 ::clang::ast_matchers::internal::ASTMatchFinder *Finder,      \
                 ::clang::ast_matchers::internal::BoundNodesTreeBuilder        \
                     *Builder) const override;                                 \
                                                                               \
  private:                                                                     \
    ParamType const Param;                                                     \
  };                                                                           \
  }                                                                            \
  inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1<        \
      internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType,       \
      ReturnTypesF>                                                            \
  DefineMatcher(ParamType const &Param) {                                      \
    return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1<      \
        internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType,     \
        ReturnTypesF>(Param);                                                  \
  }                                                                            \
  typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1<       \
      internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType,       \
      ReturnTypesF>(&DefineMatcher##_Type##OverloadId)(                        \
      ParamType const &Param);                                                 \
  template <typename NodeType, typename ParamT>                                \
  bool internal::                                                              \
      matcher_##DefineMatcher##OverloadId##Matcher<NodeType, ParamT>::matches( \
          const NodeType &Node,                                                \
          ::clang::ast_matchers::internal::ASTMatchFinder *Finder,             \
          ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder)     \
          const

/// 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, ReturnTypesF, ParamType1,    \
                                   Param1, ParamType2, Param2)                 \
  AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType1, \
                                      Param1, ParamType2, Param2, 0)

#define AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ReturnTypesF,       \
                                            ParamType1, Param1, ParamType2,    \
                                            Param2, OverloadId)                \
  namespace internal {                                                         \
  template <typename NodeType, typename ParamT1, typename ParamT2>             \
  class matcher_##DefineMatcher##OverloadId##Matcher                           \
      : public ::clang::ast_matchers::internal::MatcherInterface<NodeType> {   \
  public:                                                                      \
    matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1,  \
                                                 ParamType2 const &A##Param2)  \
        : Param1(A##Param1), Param2(A##Param2) {}                              \
    bool matches(const NodeType &Node,                                         \
                 ::clang::ast_matchers::internal::ASTMatchFinder *Finder,      \
                 ::clang::ast_matchers::internal::BoundNodesTreeBuilder        \
                     *Builder) const override;                                 \
                                                                               \
  private:                                                                     \
    ParamType1 const Param1;                                                   \
    ParamType2 const Param2;                                                   \
  };                                                                           \
  }                                                                            \
  inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2<        \
      internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1,      \
      ParamType2, ReturnTypesF>                                                \
  DefineMatcher(ParamType1 const &Param1, ParamType2 const &Param2) {          \
    return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2<      \
        internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1,    \
        ParamType2, ReturnTypesF>(Param1, Param2);                             \
  }                                                                            \
  typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2<       \
      internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1,      \
      ParamType2, ReturnTypesF>(&DefineMatcher##_Type##OverloadId)(            \
      ParamType1 const &Param1, ParamType2 const &Param2);                     \
  template <typename NodeType, typename ParamT1, typename ParamT2>             \
  bool internal::matcher_##DefineMatcher##OverloadId##Matcher<                 \
      NodeType, ParamT1, ParamT2>::                                            \
      matches(const NodeType &Node,                                            \
              ::clang::ast_matchers::internal::ASTMatchFinder *Finder,         \
              ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) \
          const

// FIXME: add a matcher for TypeLoc derived classes using its custom casting
// API (no longer dyn_cast) if/when we need such matching

#define AST_TYPE_TRAVERSE_MATCHER_DECL(MatcherName, FunctionName,              \
                                       ReturnTypesF)                           \
  namespace internal {                                                         \
  template <typename T> struct TypeMatcher##MatcherName##Getter {              \
    static QualType (T::*value())() const { return &T::FunctionName; }         \
  };                                                                           \
  }                                                                            \
  extern const ::clang::ast_matchers::internal::                               \
      TypeTraversePolymorphicMatcher<                                          \
          QualType,                                                            \
          ::clang::ast_matchers::internal::TypeMatcher##MatcherName##Getter,   \
          ::clang::ast_matchers::internal::TypeTraverseMatcher,                \
          ReturnTypesF>::Func MatcherName

#define AST_TYPE_TRAVERSE_MATCHER_DEF(MatcherName, ReturnTypesF)               \
  const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher<       \
      QualType,                                                                \
      ::clang::ast_matchers::internal::TypeMatcher##MatcherName##Getter,       \
      ::clang::ast_matchers::internal::TypeTraverseMatcher,                    \
      ReturnTypesF>::Func MatcherName

/// 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 existence of such a function determines
/// whether a corresponding matcher can be used on \c SpecificType.
#define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF)     \
  namespace internal {                                                         \
  template <typename T> struct TypeMatcher##MatcherName##Getter {              \
    static QualType (T::*value())() const { return &T::FunctionName; }         \
  };                                                                           \
  }                                                                            \
  const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher<       \
      QualType,                                                                \
      ::clang::ast_matchers::internal::TypeMatcher##MatcherName##Getter,       \
      ::clang::ast_matchers::internal::TypeTraverseMatcher,                    \
      ReturnTypesF>::Func MatcherName

#define AST_TYPELOC_TRAVERSE_MATCHER_DECL(MatcherName, FunctionName,           \
                                          ReturnTypesF)                        \
  namespace internal {                                                         \
  template <typename T> struct TypeLocMatcher##MatcherName##Getter {           \
    static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; }     \
  };                                                                           \
  }                                                                            \
  extern const ::clang::ast_matchers::internal::                               \
      TypeTraversePolymorphicMatcher<                                          \
          TypeLoc,                                                             \
          ::clang::ast_matchers::internal::                                    \
              TypeLocMatcher##MatcherName##Getter,                             \
          ::clang::ast_matchers::internal::TypeLocTraverseMatcher,             \
          ReturnTypesF>::Func MatcherName##Loc;                                \
  AST_TYPE_TRAVERSE_MATCHER_DECL(MatcherName, FunctionName##Type, ReturnTypesF)

#define AST_TYPELOC_TRAVERSE_MATCHER_DEF(MatcherName, ReturnTypesF)            \
  const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher<       \
      TypeLoc,                                                                 \
      ::clang::ast_matchers::internal::TypeLocMatcher##MatcherName##Getter,    \
      ::clang::ast_matchers::internal::TypeLocTraverseMatcher,                 \
      ReturnTypesF>::Func MatcherName##Loc;                                    \
  AST_TYPE_TRAVERSE_MATCHER_DEF(MatcherName, ReturnTypesF)

/// 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, ReturnTypesF)  \
  namespace internal {                                                         \
  template <typename T> struct TypeLocMatcher##MatcherName##Getter {           \
    static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; }     \
  };                                                                           \
  }                                                                            \
  const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher<       \
      TypeLoc,                                                                 \
      ::clang::ast_matchers::internal::TypeLocMatcher##MatcherName##Getter,    \
      ::clang::ast_matchers::internal::TypeLocTraverseMatcher,                 \
      ReturnTypesF>::Func MatcherName##Loc;                                    \
  AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type, ReturnTypesF)

#endif // LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H