aboutsummaryrefslogtreecommitdiff
path: root/include/clang/ASTMatchers/ASTMatchersMacros.h
blob: f5ca26bca73c3216cb7312d3ed941d3e810cc4e0 (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
//===--- 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(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)                                       \
  AST_MATCHER_OVERLOAD(Type, DefineMatcher, 0)

#define AST_MATCHER_OVERLOAD(Type, DefineMatcher, OverloadId)                  \
  namespace internal {                                                         \
  class matcher_##DefineMatcher##OverloadId##Matcher                           \
      : public MatcherInterface<Type> {                                        \
  public:                                                                      \
    explicit matcher_##DefineMatcher##OverloadId##Matcher() {}                 \
    virtual bool matches(const Type &Node, ASTMatchFinder *Finder,             \
                         BoundNodesTreeBuilder *Builder) const;                \
  };                                                                           \
  }                                                                            \
  inline internal::Matcher<Type> 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<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(                     \
        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<Type> 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<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(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<Type>                                               \
  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 <typename NodeType>                                                 \
  class matcher_##DefineMatcher##OverloadId##Matcher                           \
      : public MatcherInterface<NodeType> {                                    \
  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 <typename NodeType>                                                 \
  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<NodeType> 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 <typename NodeType, typename ParamT>                                \
  class matcher_##DefineMatcher##OverloadId##Matcher                           \
      : public MatcherInterface<NodeType> {                                    \
  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 <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, 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 <typename NodeType, typename ParamT1, typename ParamT2>             \
  class matcher_##DefineMatcher##OverloadId##Matcher                           \
      : public MatcherInterface<NodeType> {                                    \
  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 <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 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<QualType> &InnerMatcher)                       \
        : InnerMatcher(InnerMatcher) {                                         \
    }                                                                          \
    template <typename T> operator internal:: Matcher< T>() {                  \
      return internal::Matcher<T>(new internal::TypeTraverseMatcher<T>(        \
                                          InnerMatcher, &T::FunctionName));    \
    }                                                                          \
  private:                                                                     \
    const internal::Matcher<QualType> InnerMatcher;                            \
  }                                                                            \
  ;                                                                            \
  class Variadic##MatcherName##TypeTraverseMatcher                             \
      : public llvm::VariadicFunction<                                         \
          Polymorphic##MatcherName##TypeMatcher, internal::Matcher<QualType>,  \
          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<TypeLoc> &InnerMatcher)                        \
        : InnerMatcher(InnerMatcher) {                                         \
    }                                                                          \
    template <typename T> operator internal:: Matcher< T>() {                  \
      return internal::Matcher<T>(                                             \
          new internal::TypeLocTraverseMatcher<T>(InnerMatcher,                \
                                                  &T::FunctionName##Loc));     \
    }                                                                          \
  private:                                                                     \
    const internal::Matcher<TypeLoc> InnerMatcher;                             \
  }                                                                            \
  ;                                                                            \
  class Variadic##MatcherName##TypeLocTraverseMatcher                          \
      : public llvm::VariadicFunction<                                         \
          Polymorphic##MatcherName##TypeLocMatcher, internal::Matcher<TypeLoc>,\
          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