aboutsummaryrefslogtreecommitdiff
path: root/include/clang/ASTMatchers/ASTMatchersMacros.h
blob: c68534acae355e6bb53db3d42fc1b1b682157aff (plain) (blame)
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
//===--- 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)                                       \
  namespace internal {                                                         \
  class matcher_##DefineMatcher##Matcher                                       \
      : public MatcherInterface<Type> {                                        \
   public:                                                                     \
    explicit matcher_##DefineMatcher##Matcher() {}                             \
    virtual bool matches(                                                      \
        const Type &Node, ASTMatchFinder *Finder,                              \
        BoundNodesTreeBuilder *Builder) const;                                 \
  };                                                                           \
  }                                                                            \
  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)                   \
  namespace internal {                                                         \
  class matcher_##DefineMatcher##Matcher                                       \
      : public MatcherInterface<Type> {                                        \
   public:                                                                     \
    explicit matcher_##DefineMatcher##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##Matcher(Param));                  \
  }                                                                            \
  inline bool internal::matcher_##DefineMatcher##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)               \
  namespace internal {                                                         \
  class matcher_##DefineMatcher##Matcher                                       \
      : public MatcherInterface<Type> {                                        \
   public:                                                                     \
    matcher_##DefineMatcher##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##Matcher(                          \
        Param1, Param2));                                                      \
  }                                                                            \
  inline bool internal::matcher_##DefineMatcher##Matcher::matches(             \
      const Type &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)             \
  namespace internal {                                                         \
  template <typename NodeType, typename ParamT>                                \
  class matcher_##DefineMatcher##Matcher                                       \
      : public MatcherInterface<NodeType> {                                    \
   public:                                                                     \
    explicit matcher_##DefineMatcher##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##Matcher,                              \
      ParamType >                                                              \
    DefineMatcher(const ParamType &Param) {                                    \
    return internal::PolymorphicMatcherWithParam1<                             \
        internal::matcher_##DefineMatcher##Matcher,                            \
        ParamType >(Param);                                                    \
  }                                                                            \
  template <typename NodeType, typename ParamT>                                \
  bool internal::matcher_##DefineMatcher##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)                   \
  namespace internal {                                                         \
  template <typename NodeType, typename ParamT1, typename ParamT2>             \
  class matcher_##DefineMatcher##Matcher                                       \
      : public MatcherInterface<NodeType> {                                    \
   public:                                                                     \
    matcher_##DefineMatcher##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##Matcher,                              \
      ParamType1, ParamType2 >                                                 \
    DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) {        \
    return internal::PolymorphicMatcherWithParam2<                             \
        internal::matcher_##DefineMatcher##Matcher,                            \
        ParamType1, ParamType2 >(                                              \
        Param1, Param2);                                                       \
  }                                                                            \
  template <typename NodeType, typename ParamT1, typename ParamT2>             \
  bool internal::matcher_##DefineMatcher##Matcher<                             \
      NodeType, ParamT1, ParamT2>::matches(                                    \
      const NodeType &Node, ASTMatchFinder *Finder,                            \
      BoundNodesTreeBuilder *Builder) const

#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H