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