clang 20.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
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.
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
229private:
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/// @{
252template <typename MatcherT, typename NodeT>
254match(MatcherT Matcher, const NodeT &Node, ASTContext &Context);
255
256template <typename MatcherT>
257SmallVector<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.
263template <typename MatcherT>
264SmallVector<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
276template <typename NodeT>
277const NodeT *
278selectFirst(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
286namespace internal {
288public:
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
301template <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
311template <typename MatcherT, typename NodeT>
313match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
314 return match(Matcher, DynTypedNode::create(Node), Context);
315}
316
317template <typename MatcherT>
319match(MatcherT Matcher, ASTContext &Context) {
321 MatchFinder Finder;
322 Finder.addMatcher(Matcher, &Callback);
323 Finder.matchAST(Context);
324 return std::move(Callback.Nodes);
325}
326
328matchDynamic(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
337template <typename NodeT>
338SmallVector<BoundNodes, 1> matchDynamic(internal::DynTypedMatcher Matcher,
339 const NodeT &Node,
340 ASTContext &Context) {
341 return matchDynamic(Matcher, DynTypedNode::create(Node), Context);
342}
343
345matchDynamic(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:40
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:187
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.
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: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.
internal::Matcher< CXXCtorInitializer > CXXCtorInitializerMatcher
Definition: ASTMatchers.h:150
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:144
internal::Matcher< TypeLoc > TypeLocMatcher
Definition: ASTMatchers.h:146
internal::Matcher< TemplateArgumentLoc > TemplateArgumentLocMatcher
Definition: ASTMatchers.h:152
SmallVector< BoundNodes, 1 > matchDynamic(internal::DynTypedMatcher Matcher, const DynTypedNode &Node, ASTContext &Context)
internal::Matcher< Attr > AttrMatcher
Definition: ASTMatchers.h:154
internal::Matcher< NestedNameSpecifierLoc > NestedNameSpecifierLocMatcher
Definition: ASTMatchers.h:148
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.
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