summaryrefslogtreecommitdiffstats
path: root/include/clang/ASTMatchers/ASTMatchersMacros.h
blob: 563372a506091e6b82ddbf84e5d3288510d03b93 (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
//===--- 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_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)

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

/// \brief 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_1(t1) void(internal::TypeList<t1>)
#define AST_POLYMORPHIC_SUPPORTED_TYPES_2(t1, t2)                              \
  void(internal::TypeList<t1, t2>)
#define AST_POLYMORPHIC_SUPPORTED_TYPES_3(t1, t2, t3)                          \
  void(internal::TypeList<t1, t2, t3>)
#define AST_POLYMORPHIC_SUPPORTED_TYPES_4(t1, t2, t3, t4)                      \
  void(internal::TypeList<t1, t2, t3, t4>)
#define AST_POLYMORPHIC_SUPPORTED_TYPES_5(t1, t2, t3, t4, t5)                  \
  void(internal::TypeList<t1, t2, t3, internal::TypeList<t4, t5> >)

/// \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, ReturnTypesF)                   \
  namespace internal {                                                         \
  template <typename NodeType>                                                 \
  class matcher_##DefineMatcher##Matcher : public MatcherInterface<NodeType> { \
  public:                                                                      \
    bool matches(const NodeType &Node, ASTMatchFinder *Finder,                 \
                 BoundNodesTreeBuilder *Builder) const override;               \
  };                                                                           \
  }                                                                            \
  inline internal::PolymorphicMatcherWithParam0<                               \
      internal::matcher_##DefineMatcher##Matcher, ReturnTypesF>                \
  DefineMatcher() {                                                            \
    return internal::PolymorphicMatcherWithParam0<                             \
        internal::matcher_##DefineMatcher##Matcher, ReturnTypesF>();           \
  }                                                                            \
  template <typename NodeType>                                                 \
  bool internal::matcher_##DefineMatcher##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<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 MatcherInterface<NodeType> {                                    \
  public:                                                                      \
    explicit matcher_##DefineMatcher##OverloadId##Matcher(                     \
        ParamType const &A##Param)                                             \
        : Param(A##Param) {}                                                   \
    bool matches(const NodeType &Node, ASTMatchFinder *Finder,                 \
                 BoundNodesTreeBuilder *Builder) const override;               \
                                                                               \
  private:                                                                     \
    ParamType const Param;                                                     \
  };                                                                           \
  }                                                                            \
  inline internal::PolymorphicMatcherWithParam1<                               \
      internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType,       \
      ReturnTypesF> DefineMatcher(ParamType const &Param) {                    \
    return internal::PolymorphicMatcherWithParam1<                             \
        internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType,     \
        ReturnTypesF>(Param);                                                  \
  }                                                                            \
  typedef 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, 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, 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 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, ASTMatchFinder *Finder,                \
                  BoundNodesTreeBuilder *Builder) const override;              \
                                                                               \
  private:                                                                     \
    ParamType1 const Param1;                                                   \
    ParamType2 const Param2;                                                   \
  };                                                                           \
  }                                                                            \
  inline internal::PolymorphicMatcherWithParam2<                               \
      internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1,      \
      ParamType2, ReturnTypesF> DefineMatcher(ParamType1 const &Param1,        \
                                              ParamType2 const &Param2) {      \
    return internal::PolymorphicMatcherWithParam2<                             \
        internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1,    \
        ParamType2, ReturnTypesF>(Param1, Param2);                             \
  }                                                                            \
  typedef 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, 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<Type, NodeType> 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 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 internal::TypeTraversePolymorphicMatcher<                              \
      QualType, internal::TypeMatcher##MatcherName##Getter,                    \
      internal::TypeTraverseMatcher, ReturnTypesF>::Func 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, ReturnTypesF)  \
  namespace internal {                                                         \
  template <typename T> struct TypeLocMatcher##MatcherName##Getter {           \
    static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; }     \
  };                                                                           \
  }                                                                            \
  const internal::TypeTraversePolymorphicMatcher<                              \
      TypeLoc, internal::TypeLocMatcher##MatcherName##Getter,                  \
      internal::TypeLocTraverseMatcher, ReturnTypesF>::Func MatcherName##Loc;  \
  AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type, ReturnTypesF)

#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H