Coverage Report

Created: 2018-09-23 03:40

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h
Line
Count
Source
1
//===--- ASTMatchFinder.h - Structural query framework ----------*- C++ -*-===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
//  Provides a way to construct an ASTConsumer that runs given matchers
11
//  over the AST and invokes a given callback on every match.
12
//
13
//  The general idea is to construct a matcher expression that describes a
14
//  subtree match on the AST. Next, a callback that is executed every time the
15
//  expression matches is registered, and the matcher is run over the AST of
16
//  some code. Matched subexpressions can be bound to string IDs and easily
17
//  be accessed from the registered callback. The callback can than use the
18
//  AST nodes that the subexpressions matched on to output information about
19
//  the match or construct changes that can be applied to the code.
20
//
21
//  Example:
22
//  class HandleMatch : public MatchFinder::MatchCallback {
23
//  public:
24
//    virtual void Run(const MatchFinder::MatchResult &Result) {
25
//      const CXXRecordDecl *Class =
26
//          Result.Nodes.GetDeclAs<CXXRecordDecl>("id");
27
//      ...
28
//    }
29
//  };
30
//
31
//  int main(int argc, char **argv) {
32
//    ClangTool Tool(argc, argv);
33
//    MatchFinder finder;
34
//    finder.AddMatcher(Id("id", record(hasName("::a_namespace::AClass"))),
35
//                      new HandleMatch);
36
//    return Tool.Run(newFrontendActionFactory(&finder));
37
//  }
38
//
39
//===----------------------------------------------------------------------===//
40
41
#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
42
#define LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
43
44
#include "clang/ASTMatchers/ASTMatchers.h"
45
#include "llvm/ADT/SmallPtrSet.h"
46
#include "llvm/ADT/StringMap.h"
47
#include "llvm/Support/Timer.h"
48
49
namespace clang {
50
51
namespace ast_matchers {
52
53
/// A class to allow finding matches over the Clang AST.
54
///
55
/// After creation, you can add multiple matchers to the MatchFinder via
56
/// calls to addMatcher(...).
57
///
58
/// Once all matchers are added, newASTConsumer() returns an ASTConsumer
59
/// that will trigger the callbacks specified via addMatcher(...) when a match
60
/// is found.
61
///
62
/// The order of matches is guaranteed to be equivalent to doing a pre-order
63
/// traversal on the AST, and applying the matchers in the order in which they
64
/// were added to the MatchFinder.
65
///
66
/// See ASTMatchers.h for more information about how to create matchers.
67
///
68
/// Not intended to be subclassed.
69
class MatchFinder {
70
public:
71
  /// Contains all information for a given match.
72
  ///
73
  /// Every time a match is found, the MatchFinder will invoke the registered
74
  /// MatchCallback with a MatchResult containing information about the match.
75
  struct MatchResult {
76
    MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context);
77
78
    /// Contains the nodes bound on the current match.
79
    ///
80
    /// This allows user code to easily extract matched AST nodes.
81
    const BoundNodes Nodes;
82
83
    /// Utilities for interpreting the matched AST structures.
84
    /// @{
85
    clang::ASTContext * const Context;
86
    clang::SourceManager * const SourceManager;
87
    /// @}
88
  };
89
90
  /// Called when the Match registered for it was successfully found
91
  /// in the AST.
92
  class MatchCallback {
93
  public:
94
    virtual ~MatchCallback();
95
96
    /// Called on every match by the \c MatchFinder.
97
    virtual void run(const MatchResult &Result) = 0;
98
99
    /// Called at the start of each translation unit.
100
    ///
101
    /// Optionally override to do per translation unit tasks.
102
5.22k
    virtual void onStartOfTranslationUnit() {}
103
104
    /// Called at the end of each translation unit.
105
    ///
106
    /// Optionally override to do per translation unit tasks.
107
1.93k
    virtual void onEndOfTranslationUnit() {}
108
109
    /// An id used to group the matchers.
110
    ///
111
    /// This id is used, for example, for the profiling output.
112
    /// It defaults to "<unknown>".
113
    virtual StringRef getID() const;
114
  };
115
116
  /// Called when parsing is finished. Intended for testing only.
117
  class ParsingDoneTestCallback {
118
  public:
119
    virtual ~ParsingDoneTestCallback();
120
    virtual void run() = 0;
121
  };
122
123
  struct MatchFinderOptions {
124
    struct Profiling {
125
      Profiling(llvm::StringMap<llvm::TimeRecord> &Records)
126
          : Records(Records) {}
127
128
      /// Per bucket timing information.
129
      llvm::StringMap<llvm::TimeRecord> &Records;
130
    };
131
132
    /// Enables per-check timers.
133
    ///
134
    /// It prints a report after match.
135
    llvm::Optional<Profiling> CheckProfiling;
136
  };
137
138
  MatchFinder(MatchFinderOptions Options = MatchFinderOptions());
139
  ~MatchFinder();
140
141
  /// Adds a matcher to execute when running over the AST.
142
  ///
143
  /// Calls 'Action' with the BoundNodes on every match.
144
  /// Adding more than one 'NodeMatch' allows finding different matches in a
145
  /// single pass over the AST.
146
  ///
147
  /// Does not take ownership of 'Action'.
148
  /// @{
149
  void addMatcher(const DeclarationMatcher &NodeMatch,
150
                  MatchCallback *Action);
151
  void addMatcher(const TypeMatcher &NodeMatch,
152
                  MatchCallback *Action);
153
  void addMatcher(const StatementMatcher &NodeMatch,
154
                  MatchCallback *Action);
155
  void addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
156
                  MatchCallback *Action);
157
  void addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
158
                  MatchCallback *Action);
159
  void addMatcher(const TypeLocMatcher &NodeMatch,
160
                  MatchCallback *Action);
161
  void addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
162
                  MatchCallback *Action);
163
  /// @}
164
165
  /// Adds a matcher to execute when running over the AST.
166
  ///
167
  /// This is similar to \c addMatcher(), but it uses the dynamic interface. It
168
  /// is more flexible, but the lost type information enables a caller to pass
169
  /// a matcher that cannot match anything.
170
  ///
171
  /// \returns \c true if the matcher is a valid top-level matcher, \c false
172
  ///   otherwise.
173
  bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
174
                         MatchCallback *Action);
175
176
  /// Creates a clang ASTConsumer that finds all matches.
177
  std::unique_ptr<clang::ASTConsumer> newASTConsumer();
178
179
  /// Calls the registered callbacks on all matches on the given \p Node.
180
  ///
181
  /// Note that there can be multiple matches on a single node, for
182
  /// example when using decl(forEachDescendant(stmt())).
183
  ///
184
  /// @{
185
104
  template <typename T> void match(const T &Node, ASTContext &Context) {
186
104
    match(clang::ast_type_traits::DynTypedNode::create(Node), Context);
187
104
  }
188
  void match(const clang::ast_type_traits::DynTypedNode &Node,
189
             ASTContext &Context);
190
  /// @}
191
192
  /// Finds all matches in the given AST.
193
  void matchAST(ASTContext &Context);
194
195
  /// Registers a callback to notify the end of parsing.
196
  ///
197
  /// The provided closure is called after parsing is done, before the AST is
198
  /// traversed. Useful for benchmarking.
199
  /// Each call to FindAll(...) will call the closure once.
200
  void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
201
202
  /// For each \c Matcher<> a \c MatchCallback that will be called
203
  /// when it matches.
204
  struct MatchersByType {
205
    std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *>>
206
        DeclOrStmt;
207
    std::vector<std::pair<TypeMatcher, MatchCallback *>> Type;
208
    std::vector<std::pair<NestedNameSpecifierMatcher, MatchCallback *>>
209
        NestedNameSpecifier;
210
    std::vector<std::pair<NestedNameSpecifierLocMatcher, MatchCallback *>>
211
        NestedNameSpecifierLoc;
212
    std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc;
213
    std::vector<std::pair<CXXCtorInitializerMatcher, MatchCallback *>> CtorInit;
214
    /// All the callbacks in one container to simplify iteration.
215
    llvm::SmallPtrSet<MatchCallback *, 16> AllCallbacks;
216
  };
217
218
private:
219
  MatchersByType Matchers;
220
221
  MatchFinderOptions Options;
222
223
  /// Called when parsing is done.
224
  ParsingDoneTestCallback *ParsingDone;
225
};
226
227
/// Returns the results of matching \p Matcher on \p Node.
228
///
229
/// Collects the \c BoundNodes of all callback invocations when matching
230
/// \p Matcher on \p Node and returns the collected results.
231
///
232
/// Multiple results occur when using matchers like \c forEachDescendant,
233
/// which generate a result for each sub-match.
234
///
235
/// If you want to find all matches on the sub-tree rooted at \c Node (rather
236
/// than only the matches on \c Node itself), surround the \c Matcher with a
237
/// \c findAll().
238
///
239
/// \see selectFirst
240
/// @{
241
template <typename MatcherT, typename NodeT>
242
SmallVector<BoundNodes, 1>
243
match(MatcherT Matcher, const NodeT &Node, ASTContext &Context);
244
245
template <typename MatcherT>
246
SmallVector<BoundNodes, 1>
247
match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
248
      ASTContext &Context);
249
/// @}
250
251
/// Returns the results of matching \p Matcher on the translation unit of
252
/// \p Context and collects the \c BoundNodes of all callback invocations.
253
template <typename MatcherT>
254
SmallVector<BoundNodes, 1> match(MatcherT Matcher, ASTContext &Context);
255
256
/// Returns the first result of type \c NodeT bound to \p BoundTo.
257
///
258
/// Returns \c NULL if there is no match, or if the matching node cannot be
259
/// casted to \c NodeT.
260
///
261
/// This is useful in combanation with \c match():
262
/// \code
263
///   const Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"),
264
///                                                 Node, Context));
265
/// \endcode
266
template <typename NodeT>
267
const NodeT *
268
selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) {
269
  for (const BoundNodes &N : Results) {
270
    if (const NodeT *Node = N.getNodeAs<NodeT>(BoundTo))
271
      return Node;
272
  }
273
  return nullptr;
274
}
275
276
namespace internal {
277
class CollectMatchesCallback : public MatchFinder::MatchCallback {
278
public:
279
813
  void run(const MatchFinder::MatchResult &Result) override {
280
813
    Nodes.push_back(Result.Nodes);
281
813
  }
282
  SmallVector<BoundNodes, 1> Nodes;
283
};
284
}
285
286
template <typename MatcherT>
287
SmallVector<BoundNodes, 1>
288
match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
289
18.3k
      ASTContext &Context) {
290
18.3k
  internal::CollectMatchesCallback Callback;
291
18.3k
  MatchFinder Finder;
292
18.3k
  Finder.addMatcher(Matcher, &Callback);
293
18.3k
  Finder.match(Node, Context);
294
18.3k
  return std::move(Callback.Nodes);
295
18.3k
}
llvm::SmallVector<clang::ast_matchers::BoundNodes, 1u> clang::ast_matchers::match<clang::ast_matchers::internal::BindableMatcher<clang::Stmt> >(clang::ast_matchers::internal::BindableMatcher<clang::Stmt>, clang::ast_type_traits::DynTypedNode const&, clang::ASTContext&)
Line
Count
Source
289
16.2k
      ASTContext &Context) {
290
16.2k
  internal::CollectMatchesCallback Callback;
291
16.2k
  MatchFinder Finder;
292
16.2k
  Finder.addMatcher(Matcher, &Callback);
293
16.2k
  Finder.match(Node, Context);
294
16.2k
  return std::move(Callback.Nodes);
295
16.2k
}
llvm::SmallVector<clang::ast_matchers::BoundNodes, 1u> clang::ast_matchers::match<clang::ast_matchers::internal::BindableMatcher<clang::Decl> >(clang::ast_matchers::internal::BindableMatcher<clang::Decl>, clang::ast_type_traits::DynTypedNode const&, clang::ASTContext&)
Line
Count
Source
289
102
      ASTContext &Context) {
290
102
  internal::CollectMatchesCallback Callback;
291
102
  MatchFinder Finder;
292
102
  Finder.addMatcher(Matcher, &Callback);
293
102
  Finder.match(Node, Context);
294
102
  return std::move(Callback.Nodes);
295
102
}
llvm::SmallVector<clang::ast_matchers::BoundNodes, 1u> clang::ast_matchers::match<clang::ast_matchers::internal::Matcher<clang::Decl> >(clang::ast_matchers::internal::Matcher<clang::Decl>, clang::ast_type_traits::DynTypedNode const&, clang::ASTContext&)
Line
Count
Source
289
158
      ASTContext &Context) {
290
158
  internal::CollectMatchesCallback Callback;
291
158
  MatchFinder Finder;
292
158
  Finder.addMatcher(Matcher, &Callback);
293
158
  Finder.match(Node, Context);
294
158
  return std::move(Callback.Nodes);
295
158
}
llvm::SmallVector<clang::ast_matchers::BoundNodes, 1u> clang::ast_matchers::match<clang::ast_matchers::internal::Matcher<clang::Stmt> >(clang::ast_matchers::internal::Matcher<clang::Stmt>, clang::ast_type_traits::DynTypedNode const&, clang::ASTContext&)
Line
Count
Source
289
1.79k
      ASTContext &Context) {
290
1.79k
  internal::CollectMatchesCallback Callback;
291
1.79k
  MatchFinder Finder;
292
1.79k
  Finder.addMatcher(Matcher, &Callback);
293
1.79k
  Finder.match(Node, Context);
294
1.79k
  return std::move(Callback.Nodes);
295
1.79k
}
296
297
template <typename MatcherT, typename NodeT>
298
SmallVector<BoundNodes, 1>
299
18.3k
match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
300
18.3k
  return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context);
301
18.3k
}
llvm::SmallVector<clang::ast_matchers::BoundNodes, 1u> clang::ast_matchers::match<clang::ast_matchers::internal::BindableMatcher<clang::Stmt>, clang::Stmt>(clang::ast_matchers::internal::BindableMatcher<clang::Stmt>, clang::Stmt const&, clang::ASTContext&)
Line
Count
Source
299
16.2k
match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
300
16.2k
  return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context);
301
16.2k
}
llvm::SmallVector<clang::ast_matchers::BoundNodes, 1u> clang::ast_matchers::match<clang::ast_matchers::internal::BindableMatcher<clang::Decl>, clang::Decl>(clang::ast_matchers::internal::BindableMatcher<clang::Decl>, clang::Decl const&, clang::ASTContext&)
Line
Count
Source
299
100
match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
300
100
  return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context);
301
100
}
llvm::SmallVector<clang::ast_matchers::BoundNodes, 1u> clang::ast_matchers::match<clang::ast_matchers::internal::Matcher<clang::Decl>, clang::Decl>(clang::ast_matchers::internal::Matcher<clang::Decl>, clang::Decl const&, clang::ASTContext&)
Line
Count
Source
299
158
match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
300
158
  return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context);
301
158
}
llvm::SmallVector<clang::ast_matchers::BoundNodes, 1u> clang::ast_matchers::match<clang::ast_matchers::internal::Matcher<clang::Stmt>, clang::Stmt>(clang::ast_matchers::internal::Matcher<clang::Stmt>, clang::Stmt const&, clang::ASTContext&)
Line
Count
Source
299
1.79k
match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
300
1.79k
  return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context);
301
1.79k
}
302
303
template <typename MatcherT>
304
SmallVector<BoundNodes, 1>
305
match(MatcherT Matcher, ASTContext &Context) {
306
  internal::CollectMatchesCallback Callback;
307
  MatchFinder Finder;
308
  Finder.addMatcher(Matcher, &Callback);
309
  Finder.matchAST(Context);
310
  return std::move(Callback.Nodes);
311
}
312
313
} // end namespace ast_matchers
314
} // end namespace clang
315
316
#endif