clang 22.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
49namespace clang {
50
51namespace 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.
70public:
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.
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
139
140 /// Enables per-check timers.
141 ///
142 /// It prints a report after match.
143 std::optional<Profiling> CheckProfiling;
144
145 /// Avoids matching declarations in system headers.
147 };
148
149 MatchFinder(MatchFinderOptions Options = MatchFinderOptions());
150 ~MatchFinder();
151
152 /// Adds a matcher to execute when running over the AST.
153 ///
154 /// Calls 'Action' with the BoundNodes on every match.
155 /// Adding more than one 'NodeMatch' allows finding different matches in a
156 /// single pass over the AST.
157 ///
158 /// Does not take ownership of 'Action'.
159 /// @{
160 void addMatcher(const DeclarationMatcher &NodeMatch,
161 MatchCallback *Action);
162 void addMatcher(const TypeMatcher &NodeMatch,
163 MatchCallback *Action);
164 void addMatcher(const StatementMatcher &NodeMatch,
165 MatchCallback *Action);
166 void addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
167 MatchCallback *Action);
168 void addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
169 MatchCallback *Action);
170 void addMatcher(const TypeLocMatcher &NodeMatch,
171 MatchCallback *Action);
172 void addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
173 MatchCallback *Action);
174 void addMatcher(const TemplateArgumentLocMatcher &NodeMatch,
175 MatchCallback *Action);
176 void addMatcher(const AttrMatcher &NodeMatch, MatchCallback *Action);
177 /// @}
178
179 /// Adds a matcher to execute when running over the AST.
180 ///
181 /// This is similar to \c addMatcher(), but it uses the dynamic interface. It
182 /// is more flexible, but the lost type information enables a caller to pass
183 /// a matcher that cannot match anything.
184 ///
185 /// \returns \c true if the matcher is a valid top-level matcher, \c false
186 /// otherwise.
187 bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
188 MatchCallback *Action);
189
190 /// Creates a clang ASTConsumer that finds all matches.
191 std::unique_ptr<clang::ASTConsumer> newASTConsumer();
192
193 /// Calls the registered callbacks on all matches on the given \p Node.
194 ///
195 /// Note that there can be multiple matches on a single node, for
196 /// example when using decl(forEachDescendant(stmt())).
197 ///
198 /// @{
199 template <typename T> void match(const T &Node, ASTContext &Context) {
201 }
202 void match(const clang::DynTypedNode &Node, ASTContext &Context);
203 /// @}
204
205 /// Finds all matches in the given AST.
206 void matchAST(ASTContext &Context);
207
208 /// Registers a callback to notify the end of parsing.
209 ///
210 /// The provided closure is called after parsing is done, before the AST is
211 /// traversed. Useful for benchmarking.
212 /// Each call to FindAll(...) will call the closure once.
213 void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
214
215 /// For each \c Matcher<> a \c MatchCallback that will be called
216 /// when it matches.
218 std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *>>
220 std::vector<std::pair<TypeMatcher, MatchCallback *>> Type;
221 std::vector<std::pair<NestedNameSpecifierMatcher, MatchCallback *>>
223 std::vector<std::pair<NestedNameSpecifierLocMatcher, MatchCallback *>>
225 std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc;
226 std::vector<std::pair<CXXCtorInitializerMatcher, MatchCallback *>> CtorInit;
227 std::vector<std::pair<TemplateArgumentLocMatcher, MatchCallback *>>
229 std::vector<std::pair<AttrMatcher, MatchCallback *>> Attr;
230 /// All the callbacks in one container to simplify iteration.
232 };
233
234private:
235 MatchersByType Matchers;
236
237 MatchFinderOptions Options;
238
239 /// Called when parsing is done.
240 ParsingDoneTestCallback *ParsingDone;
241};
242
243/// Returns the results of matching \p Matcher on \p Node.
244///
245/// Collects the \c BoundNodes of all callback invocations when matching
246/// \p Matcher on \p Node and returns the collected results.
247///
248/// Multiple results occur when using matchers like \c forEachDescendant,
249/// which generate a result for each sub-match.
250///
251/// If you want to find all matches on the sub-tree rooted at \c Node (rather
252/// than only the matches on \c Node itself), surround the \c Matcher with a
253/// \c findAll().
254///
255/// \see selectFirst
256/// @{
257template <typename MatcherT, typename NodeT>
259match(MatcherT Matcher, const NodeT &Node, ASTContext &Context);
260
261template <typename MatcherT>
262SmallVector<BoundNodes, 1> match(MatcherT Matcher, const DynTypedNode &Node,
263 ASTContext &Context);
264/// @}
265
266/// Returns the results of matching \p Matcher on the translation unit of
267/// \p Context and collects the \c BoundNodes of all callback invocations.
268template <typename MatcherT>
269SmallVector<BoundNodes, 1> match(MatcherT Matcher, ASTContext &Context);
270
271/// Returns the first result of type \c NodeT bound to \p BoundTo.
272///
273/// Returns \c NULL if there is no match, or if the matching node cannot be
274/// casted to \c NodeT.
275///
276/// This is useful in combination with \c match():
277/// \code
278/// const Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"),
279/// Node, Context));
280/// \endcode
281template <typename NodeT>
282const NodeT *
283selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) {
284 for (const BoundNodes &N : Results) {
285 if (const NodeT *Node = N.getNodeAs<NodeT>(BoundTo))
286 return Node;
287 }
288 return nullptr;
289}
290
291namespace internal {
293public:
294 void run(const MatchFinder::MatchResult &Result) override {
295 Nodes.push_back(Result.Nodes);
296 }
297
298 std::optional<TraversalKind> getCheckTraversalKind() const override {
299 return std::nullopt;
300 }
301
303};
304}
305
306template <typename MatcherT>
308 ASTContext &Context) {
310 MatchFinder Finder;
311 Finder.addMatcher(Matcher, &Callback);
312 Finder.match(Node, Context);
313 return std::move(Callback.Nodes);
314}
315
316template <typename MatcherT, typename NodeT>
318match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
319 return match(Matcher, DynTypedNode::create(Node), Context);
320}
321
322template <typename MatcherT>
324match(MatcherT Matcher, ASTContext &Context) {
326 MatchFinder Finder;
327 Finder.addMatcher(Matcher, &Callback);
328 Finder.matchAST(Context);
329 return std::move(Callback.Nodes);
330}
331
333matchDynamic(internal::DynTypedMatcher Matcher, const DynTypedNode &Node,
334 ASTContext &Context) {
336 MatchFinder Finder;
337 Finder.addDynamicMatcher(Matcher, &Callback);
338 Finder.match(Node, Context);
339 return std::move(Callback.Nodes);
340}
341
342template <typename NodeT>
343SmallVector<BoundNodes, 1> matchDynamic(internal::DynTypedMatcher Matcher,
344 const NodeT &Node,
345 ASTContext &Context) {
346 return matchDynamic(Matcher, DynTypedNode::create(Node), Context);
347}
348
350matchDynamic(internal::DynTypedMatcher Matcher, ASTContext &Context) {
352 MatchFinder Finder;
353 Finder.addDynamicMatcher(Matcher, &Callback);
354 Finder.matchAST(Context);
355 return std::move(Callback.Nodes);
356}
357
358} // end namespace ast_matchers
359} // end namespace clang
360
361#endif
DynTypedNode Node
llvm::MachO::Records Records
Definition: MachO.h:40
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
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:111
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.
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.
void run(const MatchFinder::MatchResult &Result) override
Called on every match by the MatchFinder.
std::optional< TraversalKind > getCheckTraversalKind() const override
TraversalKind to use while matching and processing the result nodes.
internal::Matcher< QualType > TypeMatcher
Definition: ASTMatchers.h:147
internal::Matcher< Decl > DeclarationMatcher
Types of matchers for the top-level classes in the AST class hierarchy.
Definition: ASTMatchers.h:145
internal::Matcher< NestedNameSpecifier > NestedNameSpecifierMatcher
Definition: ASTMatchers.h:149
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
internal::Matcher< CXXCtorInitializer > CXXCtorInitializerMatcher
Definition: ASTMatchers.h:152
const NodeT * selectFirst(StringRef BoundTo, const SmallVectorImpl< BoundNodes > &Results)
Returns the first result of type NodeT bound to BoundTo.
internal::Matcher< Stmt > StatementMatcher
Definition: ASTMatchers.h:146
internal::Matcher< TypeLoc > TypeLocMatcher
Definition: ASTMatchers.h:148
internal::Matcher< TemplateArgumentLoc > TemplateArgumentLocMatcher
Definition: ASTMatchers.h:154
SmallVector< BoundNodes, 1 > matchDynamic(internal::DynTypedMatcher Matcher, const DynTypedNode &Node, ASTContext &Context)
internal::Matcher< Attr > AttrMatcher
Definition: ASTMatchers.h:156
internal::Matcher< NestedNameSpecifierLoc > NestedNameSpecifierLocMatcher
Definition: ASTMatchers.h:150
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
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.
bool IgnoreSystemHeaders
Avoids matching declarations in system headers.
Contains all information for a given match.
clang::SourceManager *const SourceManager
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