clang  19.0.0git
ASTMatchFinder.h
Go to the documentation of this file.
1 //===--- ASTMatchFinder.h - Structural query framework ----------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Provides a way to construct an ASTConsumer that runs given matchers
10 // over the AST and invokes a given callback on every match.
11 //
12 // The general idea is to construct a matcher expression that describes a
13 // subtree match on the AST. Next, a callback that is executed every time the
14 // expression matches is registered, and the matcher is run over the AST of
15 // some code. Matched subexpressions can be bound to string IDs and easily
16 // be accessed from the registered callback. The callback can than use the
17 // AST nodes that the subexpressions matched on to output information about
18 // the match or construct changes that can be applied to the code.
19 //
20 // Example:
21 // class HandleMatch : public MatchFinder::MatchCallback {
22 // public:
23 // virtual void Run(const MatchFinder::MatchResult &Result) {
24 // const CXXRecordDecl *Class =
25 // Result.Nodes.GetDeclAs<CXXRecordDecl>("id");
26 // ...
27 // }
28 // };
29 //
30 // int main(int argc, char **argv) {
31 // ClangTool Tool(argc, argv);
32 // MatchFinder finder;
33 // finder.AddMatcher(Id("id", record(hasName("::a_namespace::AClass"))),
34 // new HandleMatch);
35 // return Tool.Run(newFrontendActionFactory(&finder));
36 // }
37 //
38 //===----------------------------------------------------------------------===//
39 
40 #ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
41 #define LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
42 
44 #include "llvm/ADT/SmallPtrSet.h"
45 #include "llvm/ADT/StringMap.h"
46 #include "llvm/Support/Timer.h"
47 #include <optional>
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 {
77 
78  /// Contains the nodes bound on the current match.
79  ///
80  /// This allows user code to easily extract matched AST nodes.
82 
83  /// Utilities for interpreting the matched AST structures.
84  /// @{
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  virtual void onStartOfTranslationUnit() {}
103 
104  /// Called at the end of each translation unit.
105  ///
106  /// Optionally override to do per translation unit tasks.
107  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  /// TraversalKind to use while matching and processing
116  /// the result nodes. This API is temporary to facilitate
117  /// third parties porting existing code to the default
118  /// behavior of clang-tidy.
119  virtual std::optional<TraversalKind> getCheckTraversalKind() const;
120  };
121 
122  /// Called when parsing is finished. Intended for testing only.
124  public:
125  virtual ~ParsingDoneTestCallback();
126  virtual void run() = 0;
127  };
128 
130  struct Profiling {
131  Profiling(llvm::StringMap<llvm::TimeRecord> &Records)
132  : Records(Records) {}
133 
134  /// Per bucket timing information.
135  llvm::StringMap<llvm::TimeRecord> &Records;
136  };
137 
138  /// Enables per-check timers.
139  ///
140  /// It prints a report after match.
141  std::optional<Profiling> CheckProfiling;
142  };
143 
145  ~MatchFinder();
146 
147  /// Adds a matcher to execute when running over the AST.
148  ///
149  /// Calls 'Action' with the BoundNodes on every match.
150  /// Adding more than one 'NodeMatch' allows finding different matches in a
151  /// single pass over the AST.
152  ///
153  /// Does not take ownership of 'Action'.
154  /// @{
155  void addMatcher(const DeclarationMatcher &NodeMatch,
156  MatchCallback *Action);
157  void addMatcher(const TypeMatcher &NodeMatch,
158  MatchCallback *Action);
159  void addMatcher(const StatementMatcher &NodeMatch,
160  MatchCallback *Action);
161  void addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
162  MatchCallback *Action);
163  void addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
164  MatchCallback *Action);
165  void addMatcher(const TypeLocMatcher &NodeMatch,
166  MatchCallback *Action);
167  void addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
168  MatchCallback *Action);
169  void addMatcher(const TemplateArgumentLocMatcher &NodeMatch,
170  MatchCallback *Action);
171  void addMatcher(const AttrMatcher &NodeMatch, MatchCallback *Action);
172  /// @}
173 
174  /// Adds a matcher to execute when running over the AST.
175  ///
176  /// This is similar to \c addMatcher(), but it uses the dynamic interface. It
177  /// is more flexible, but the lost type information enables a caller to pass
178  /// a matcher that cannot match anything.
179  ///
180  /// \returns \c true if the matcher is a valid top-level matcher, \c false
181  /// otherwise.
182  bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
183  MatchCallback *Action);
184 
185  /// Creates a clang ASTConsumer that finds all matches.
186  std::unique_ptr<clang::ASTConsumer> newASTConsumer();
187 
188  /// Calls the registered callbacks on all matches on the given \p Node.
189  ///
190  /// Note that there can be multiple matches on a single node, for
191  /// example when using decl(forEachDescendant(stmt())).
192  ///
193  /// @{
194  template <typename T> void match(const T &Node, ASTContext &Context) {
196  }
197  void match(const clang::DynTypedNode &Node, ASTContext &Context);
198  /// @}
199 
200  /// Finds all matches in the given AST.
201  void matchAST(ASTContext &Context);
202 
203  /// Registers a callback to notify the end of parsing.
204  ///
205  /// The provided closure is called after parsing is done, before the AST is
206  /// traversed. Useful for benchmarking.
207  /// Each call to FindAll(...) will call the closure once.
208  void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
209 
210  /// For each \c Matcher<> a \c MatchCallback that will be called
211  /// when it matches.
212  struct MatchersByType {
213  std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *>>
215  std::vector<std::pair<TypeMatcher, MatchCallback *>> Type;
216  std::vector<std::pair<NestedNameSpecifierMatcher, MatchCallback *>>
218  std::vector<std::pair<NestedNameSpecifierLocMatcher, MatchCallback *>>
220  std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc;
221  std::vector<std::pair<CXXCtorInitializerMatcher, MatchCallback *>> CtorInit;
222  std::vector<std::pair<TemplateArgumentLocMatcher, MatchCallback *>>
224  std::vector<std::pair<AttrMatcher, MatchCallback *>> Attr;
225  /// All the callbacks in one container to simplify iteration.
227  };
228 
229 private:
230  MatchersByType Matchers;
231 
232  MatchFinderOptions Options;
233 
234  /// Called when parsing is done.
235  ParsingDoneTestCallback *ParsingDone;
236 };
237 
238 /// Returns the results of matching \p Matcher on \p Node.
239 ///
240 /// Collects the \c BoundNodes of all callback invocations when matching
241 /// \p Matcher on \p Node and returns the collected results.
242 ///
243 /// Multiple results occur when using matchers like \c forEachDescendant,
244 /// which generate a result for each sub-match.
245 ///
246 /// If you want to find all matches on the sub-tree rooted at \c Node (rather
247 /// than only the matches on \c Node itself), surround the \c Matcher with a
248 /// \c findAll().
249 ///
250 /// \see selectFirst
251 /// @{
252 template <typename MatcherT, typename NodeT>
254 match(MatcherT Matcher, const NodeT &Node, ASTContext &Context);
255 
256 template <typename MatcherT>
257 SmallVector<BoundNodes, 1> match(MatcherT Matcher, const DynTypedNode &Node,
258  ASTContext &Context);
259 /// @}
260 
261 /// Returns the results of matching \p Matcher on the translation unit of
262 /// \p Context and collects the \c BoundNodes of all callback invocations.
263 template <typename MatcherT>
264 SmallVector<BoundNodes, 1> match(MatcherT Matcher, ASTContext &Context);
265 
266 /// Returns the first result of type \c NodeT bound to \p BoundTo.
267 ///
268 /// Returns \c NULL if there is no match, or if the matching node cannot be
269 /// casted to \c NodeT.
270 ///
271 /// This is useful in combanation with \c match():
272 /// \code
273 /// const Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"),
274 /// Node, Context));
275 /// \endcode
276 template <typename NodeT>
277 const NodeT *
278 selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) {
279  for (const BoundNodes &N : Results) {
280  if (const NodeT *Node = N.getNodeAs<NodeT>(BoundTo))
281  return Node;
282  }
283  return nullptr;
284 }
285 
286 namespace internal {
288 public:
289  void run(const MatchFinder::MatchResult &Result) override {
290  Nodes.push_back(Result.Nodes);
291  }
292 
293  std::optional<TraversalKind> getCheckTraversalKind() const override {
294  return std::nullopt;
295  }
296 
298 };
299 }
300 
301 template <typename MatcherT>
303  ASTContext &Context) {
305  MatchFinder Finder;
306  Finder.addMatcher(Matcher, &Callback);
307  Finder.match(Node, Context);
308  return std::move(Callback.Nodes);
309 }
310 
311 template <typename MatcherT, typename NodeT>
313 match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
314  return match(Matcher, DynTypedNode::create(Node), Context);
315 }
316 
317 template <typename MatcherT>
319 match(MatcherT Matcher, ASTContext &Context) {
321  MatchFinder Finder;
322  Finder.addMatcher(Matcher, &Callback);
323  Finder.matchAST(Context);
324  return std::move(Callback.Nodes);
325 }
326 
328 matchDynamic(internal::DynTypedMatcher Matcher, const DynTypedNode &Node,
329  ASTContext &Context) {
331  MatchFinder Finder;
332  Finder.addDynamicMatcher(Matcher, &Callback);
333  Finder.match(Node, Context);
334  return std::move(Callback.Nodes);
335 }
336 
337 template <typename NodeT>
338 SmallVector<BoundNodes, 1> matchDynamic(internal::DynTypedMatcher Matcher,
339  const NodeT &Node,
340  ASTContext &Context) {
341  return matchDynamic(Matcher, DynTypedNode::create(Node), Context);
342 }
343 
345 matchDynamic(internal::DynTypedMatcher Matcher, ASTContext &Context) {
347  MatchFinder Finder;
348  Finder.addDynamicMatcher(Matcher, &Callback);
349  Finder.matchAST(Context);
350  return std::move(Callback.Nodes);
351 }
352 
353 } // end namespace ast_matchers
354 } // end namespace clang
355 
356 #endif
DynTypedNode Node
llvm::MachO::Records Records
Definition: MachO.h:39
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:185
A dynamically typed AST node container.
static DynTypedNode create(const T &Node)
Creates a DynTypedNode from Node.
This class handles loading and caching of source files into memory.
Maps string IDs to AST nodes matched by parts of a matcher.
Definition: ASTMatchers.h:109
Called when the Match registered for it was successfully found in the AST.
virtual std::optional< TraversalKind > getCheckTraversalKind() const
TraversalKind to use while matching and processing the result nodes.
virtual StringRef getID() const
An id used to group the matchers.
virtual void onEndOfTranslationUnit()
Called at the end of each translation unit.
virtual void run(const MatchResult &Result)=0
Called on every match by the MatchFinder.
virtual void onStartOfTranslationUnit()
Called at the start of each translation unit.
Called when parsing is finished. Intended for testing only.
A class to allow finding matches over the Clang AST.
MatchFinder(MatchFinderOptions Options=MatchFinderOptions())
bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch, MatchCallback *Action)
Adds a matcher to execute when running over the AST.
void addMatcher(const DeclarationMatcher &NodeMatch, MatchCallback *Action)
Adds a matcher to execute when running over the AST.
void match(const T &Node, ASTContext &Context)
Calls the registered callbacks on all matches on the given Node.
void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone)
Registers a callback to notify the end of parsing.
std::unique_ptr< clang::ASTConsumer > newASTConsumer()
Creates a clang ASTConsumer that finds all matches.
void matchAST(ASTContext &Context)
Finds all matches in the given AST.
std::optional< TraversalKind > getCheckTraversalKind() const override
TraversalKind to use while matching and processing the result nodes.
void run(const MatchFinder::MatchResult &Result) override
Called on every match by the MatchFinder.
internal::Matcher< QualType > TypeMatcher
Definition: ASTMatchers.h:145
internal::Matcher< Decl > DeclarationMatcher
Types of matchers for the top-level classes in the AST class hierarchy.
Definition: ASTMatchers.h:143
internal::Matcher< NestedNameSpecifier > NestedNameSpecifierMatcher
Definition: ASTMatchers.h:147
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
const NodeT * selectFirst(StringRef BoundTo, const SmallVectorImpl< BoundNodes > &Results)
Returns the first result of type NodeT bound to BoundTo.
internal::Matcher< CXXCtorInitializer > CXXCtorInitializerMatcher
Definition: ASTMatchers.h:150
internal::Matcher< Stmt > StatementMatcher
Definition: ASTMatchers.h:144
internal::Matcher< TypeLoc > TypeLocMatcher
Definition: ASTMatchers.h:146
internal::Matcher< TemplateArgumentLoc > TemplateArgumentLocMatcher
Definition: ASTMatchers.h:152
internal::Matcher< Attr > AttrMatcher
Definition: ASTMatchers.h:154
internal::Matcher< NestedNameSpecifierLoc > NestedNameSpecifierLocMatcher
Definition: ASTMatchers.h:148
SmallVector< BoundNodes, 1 > matchDynamic(internal::DynTypedMatcher Matcher, const DynTypedNode &Node, ASTContext &Context)
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
Profiling(llvm::StringMap< llvm::TimeRecord > &Records)
llvm::StringMap< llvm::TimeRecord > & Records
Per bucket timing information.
std::optional< Profiling > CheckProfiling
Enables per-check timers.
Contains all information for a given match.
clang::SourceManager *const SourceManager
MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context)
const BoundNodes Nodes
Contains the nodes bound on the current match.
clang::ASTContext *const Context
Utilities for interpreting the matched AST structures.
For each Matcher<> a MatchCallback that will be called when it matches.
std::vector< std::pair< CXXCtorInitializerMatcher, MatchCallback * > > CtorInit
std::vector< std::pair< TemplateArgumentLocMatcher, MatchCallback * > > TemplateArgumentLoc
std::vector< std::pair< internal::DynTypedMatcher, MatchCallback * > > DeclOrStmt
std::vector< std::pair< NestedNameSpecifierMatcher, MatchCallback * > > NestedNameSpecifier
std::vector< std::pair< TypeMatcher, MatchCallback * > > Type
std::vector< std::pair< NestedNameSpecifierLocMatcher, MatchCallback * > > NestedNameSpecifierLoc
llvm::SmallPtrSet< MatchCallback *, 16 > AllCallbacks
All the callbacks in one container to simplify iteration.
std::vector< std::pair< TypeLocMatcher, MatchCallback * > > TypeLoc
std::vector< std::pair< AttrMatcher, MatchCallback * > > Attr