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 
43 #include "clang/ASTMatchers/ASTMatchers.h"
44 #include "llvm/ADT/SmallPtrSet.h"
45 #include "llvm/ADT/StringMap.h"
46 #include "llvm/Support/Timer.h"
47 
48 namespace clang {
49 
50 namespace ast_matchers {
51 
52 /// A class to allow finding matches over the Clang AST.
53 ///
54 /// After creation, you can add multiple matchers to the MatchFinder via
55 /// calls to addMatcher(...).
56 ///
57 /// Once all matchers are added, newASTConsumer() returns an ASTConsumer
58 /// that will trigger the callbacks specified via addMatcher(...) when a match
59 /// is found.
60 ///
61 /// The order of matches is guaranteed to be equivalent to doing a pre-order
62 /// traversal on the AST, and applying the matchers in the order in which they
63 /// were added to the MatchFinder.
64 ///
65 /// See ASTMatchers.h for more information about how to create matchers.
66 ///
67 /// Not intended to be subclassed.
68 class MatchFinder {
69 public:
70   /// Contains all information for a given match.
71   ///
72   /// Every time a match is found, the MatchFinder will invoke the registered
73   /// MatchCallback with a MatchResult containing information about the match.
74   struct MatchResult {
75     MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context);
76 
77     /// Contains the nodes bound on the current match.
78     ///
79     /// This allows user code to easily extract matched AST nodes.
80     const BoundNodes Nodes;
81 
82     /// Utilities for interpreting the matched AST structures.
83     /// @{
84     clang::ASTContext * const Context;
85     clang::SourceManager * const SourceManager;
86     /// @}
87   };
88 
89   /// Called when the Match registered for it was successfully found
90   /// in the AST.
91   class MatchCallback {
92   public:
93     virtual ~MatchCallback();
94 
95     /// Called on every match by the \c MatchFinder.
96     virtual void run(const MatchResult &Result) = 0;
97 
98     /// Called at the start of each translation unit.
99     ///
100     /// Optionally override to do per translation unit tasks.
onStartOfTranslationUnit()101     virtual void onStartOfTranslationUnit() {}
102 
103     /// Called at the end of each translation unit.
104     ///
105     /// Optionally override to do per translation unit tasks.
onEndOfTranslationUnit()106     virtual void onEndOfTranslationUnit() {}
107 
108     /// An id used to group the matchers.
109     ///
110     /// This id is used, for example, for the profiling output.
111     /// It defaults to "<unknown>".
112     virtual StringRef getID() const;
113 
114     /// TraversalKind to use while matching and processing
115     /// the result nodes. This API is temporary to facilitate
116     /// third parties porting existing code to the default
117     /// behavior of clang-tidy.
118     virtual llvm::Optional<TraversalKind> getCheckTraversalKind() const;
119   };
120 
121   /// Called when parsing is finished. Intended for testing only.
122   class ParsingDoneTestCallback {
123   public:
124     virtual ~ParsingDoneTestCallback();
125     virtual void run() = 0;
126   };
127 
128   struct MatchFinderOptions {
129     struct Profiling {
ProfilingMatchFinderOptions::Profiling130       Profiling(llvm::StringMap<llvm::TimeRecord> &Records)
131           : Records(Records) {}
132 
133       /// Per bucket timing information.
134       llvm::StringMap<llvm::TimeRecord> &Records;
135     };
136 
137     /// Enables per-check timers.
138     ///
139     /// It prints a report after match.
140     llvm::Optional<Profiling> CheckProfiling;
141   };
142 
143   MatchFinder(MatchFinderOptions Options = MatchFinderOptions());
144   ~MatchFinder();
145 
146   /// Adds a matcher to execute when running over the AST.
147   ///
148   /// Calls 'Action' with the BoundNodes on every match.
149   /// Adding more than one 'NodeMatch' allows finding different matches in a
150   /// single pass over the AST.
151   ///
152   /// Does not take ownership of 'Action'.
153   /// @{
154   void addMatcher(const DeclarationMatcher &NodeMatch,
155                   MatchCallback *Action);
156   void addMatcher(const TypeMatcher &NodeMatch,
157                   MatchCallback *Action);
158   void addMatcher(const StatementMatcher &NodeMatch,
159                   MatchCallback *Action);
160   void addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
161                   MatchCallback *Action);
162   void addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
163                   MatchCallback *Action);
164   void addMatcher(const TypeLocMatcher &NodeMatch,
165                   MatchCallback *Action);
166   void addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
167                   MatchCallback *Action);
168   void addMatcher(const TemplateArgumentLocMatcher &NodeMatch,
169                   MatchCallback *Action);
170   /// @}
171 
172   /// Adds a matcher to execute when running over the AST.
173   ///
174   /// This is similar to \c addMatcher(), but it uses the dynamic interface. It
175   /// is more flexible, but the lost type information enables a caller to pass
176   /// a matcher that cannot match anything.
177   ///
178   /// \returns \c true if the matcher is a valid top-level matcher, \c false
179   ///   otherwise.
180   bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
181                          MatchCallback *Action);
182 
183   /// Creates a clang ASTConsumer that finds all matches.
184   std::unique_ptr<clang::ASTConsumer> newASTConsumer();
185 
186   /// Calls the registered callbacks on all matches on the given \p Node.
187   ///
188   /// Note that there can be multiple matches on a single node, for
189   /// example when using decl(forEachDescendant(stmt())).
190   ///
191   /// @{
match(const T & Node,ASTContext & Context)192   template <typename T> void match(const T &Node, ASTContext &Context) {
193     match(clang::DynTypedNode::create(Node), Context);
194   }
195   void match(const clang::DynTypedNode &Node, ASTContext &Context);
196   /// @}
197 
198   /// Finds all matches in the given AST.
199   void matchAST(ASTContext &Context);
200 
201   /// Registers a callback to notify the end of parsing.
202   ///
203   /// The provided closure is called after parsing is done, before the AST is
204   /// traversed. Useful for benchmarking.
205   /// Each call to FindAll(...) will call the closure once.
206   void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
207 
208   /// For each \c Matcher<> a \c MatchCallback that will be called
209   /// when it matches.
210   struct MatchersByType {
211     std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *>>
212         DeclOrStmt;
213     std::vector<std::pair<TypeMatcher, MatchCallback *>> Type;
214     std::vector<std::pair<NestedNameSpecifierMatcher, MatchCallback *>>
215         NestedNameSpecifier;
216     std::vector<std::pair<NestedNameSpecifierLocMatcher, MatchCallback *>>
217         NestedNameSpecifierLoc;
218     std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc;
219     std::vector<std::pair<CXXCtorInitializerMatcher, MatchCallback *>> CtorInit;
220     std::vector<std::pair<TemplateArgumentLocMatcher, MatchCallback *>>
221         TemplateArgumentLoc;
222     /// All the callbacks in one container to simplify iteration.
223     llvm::SmallPtrSet<MatchCallback *, 16> AllCallbacks;
224   };
225 
226 private:
227   MatchersByType Matchers;
228 
229   MatchFinderOptions Options;
230 
231   /// Called when parsing is done.
232   ParsingDoneTestCallback *ParsingDone;
233 };
234 
235 /// Returns the results of matching \p Matcher on \p Node.
236 ///
237 /// Collects the \c BoundNodes of all callback invocations when matching
238 /// \p Matcher on \p Node and returns the collected results.
239 ///
240 /// Multiple results occur when using matchers like \c forEachDescendant,
241 /// which generate a result for each sub-match.
242 ///
243 /// If you want to find all matches on the sub-tree rooted at \c Node (rather
244 /// than only the matches on \c Node itself), surround the \c Matcher with a
245 /// \c findAll().
246 ///
247 /// \see selectFirst
248 /// @{
249 template <typename MatcherT, typename NodeT>
250 SmallVector<BoundNodes, 1>
251 match(MatcherT Matcher, const NodeT &Node, ASTContext &Context);
252 
253 template <typename MatcherT>
254 SmallVector<BoundNodes, 1> match(MatcherT Matcher, const DynTypedNode &Node,
255                                  ASTContext &Context);
256 /// @}
257 
258 /// Returns the results of matching \p Matcher on the translation unit of
259 /// \p Context and collects the \c BoundNodes of all callback invocations.
260 template <typename MatcherT>
261 SmallVector<BoundNodes, 1> match(MatcherT Matcher, ASTContext &Context);
262 
263 /// Returns the first result of type \c NodeT bound to \p BoundTo.
264 ///
265 /// Returns \c NULL if there is no match, or if the matching node cannot be
266 /// casted to \c NodeT.
267 ///
268 /// This is useful in combanation with \c match():
269 /// \code
270 ///   const Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"),
271 ///                                                 Node, Context));
272 /// \endcode
273 template <typename NodeT>
274 const NodeT *
selectFirst(StringRef BoundTo,const SmallVectorImpl<BoundNodes> & Results)275 selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) {
276   for (const BoundNodes &N : Results) {
277     if (const NodeT *Node = N.getNodeAs<NodeT>(BoundTo))
278       return Node;
279   }
280   return nullptr;
281 }
282 
283 namespace internal {
284 class CollectMatchesCallback : public MatchFinder::MatchCallback {
285 public:
run(const MatchFinder::MatchResult & Result)286   void run(const MatchFinder::MatchResult &Result) override {
287     Nodes.push_back(Result.Nodes);
288   }
289 
getCheckTraversalKind()290   llvm::Optional<TraversalKind> getCheckTraversalKind() const override {
291     return llvm::None;
292   }
293 
294   SmallVector<BoundNodes, 1> Nodes;
295 };
296 }
297 
298 template <typename MatcherT>
match(MatcherT Matcher,const DynTypedNode & Node,ASTContext & Context)299 SmallVector<BoundNodes, 1> match(MatcherT Matcher, const DynTypedNode &Node,
300                                  ASTContext &Context) {
301   internal::CollectMatchesCallback Callback;
302   MatchFinder Finder;
303   Finder.addMatcher(Matcher, &Callback);
304   Finder.match(Node, Context);
305   return std::move(Callback.Nodes);
306 }
307 
308 template <typename MatcherT, typename NodeT>
309 SmallVector<BoundNodes, 1>
match(MatcherT Matcher,const NodeT & Node,ASTContext & Context)310 match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
311   return match(Matcher, DynTypedNode::create(Node), Context);
312 }
313 
314 template <typename MatcherT>
315 SmallVector<BoundNodes, 1>
match(MatcherT Matcher,ASTContext & Context)316 match(MatcherT Matcher, ASTContext &Context) {
317   internal::CollectMatchesCallback Callback;
318   MatchFinder Finder;
319   Finder.addMatcher(Matcher, &Callback);
320   Finder.matchAST(Context);
321   return std::move(Callback.Nodes);
322 }
323 
324 inline SmallVector<BoundNodes, 1>
matchDynamic(internal::DynTypedMatcher Matcher,const DynTypedNode & Node,ASTContext & Context)325 matchDynamic(internal::DynTypedMatcher Matcher, const DynTypedNode &Node,
326              ASTContext &Context) {
327   internal::CollectMatchesCallback Callback;
328   MatchFinder Finder;
329   Finder.addDynamicMatcher(Matcher, &Callback);
330   Finder.match(Node, Context);
331   return std::move(Callback.Nodes);
332 }
333 
334 template <typename NodeT>
matchDynamic(internal::DynTypedMatcher Matcher,const NodeT & Node,ASTContext & Context)335 SmallVector<BoundNodes, 1> matchDynamic(internal::DynTypedMatcher Matcher,
336                                         const NodeT &Node,
337                                         ASTContext &Context) {
338   return matchDynamic(Matcher, DynTypedNode::create(Node), Context);
339 }
340 
341 inline SmallVector<BoundNodes, 1>
matchDynamic(internal::DynTypedMatcher Matcher,ASTContext & Context)342 matchDynamic(internal::DynTypedMatcher Matcher, ASTContext &Context) {
343   internal::CollectMatchesCallback Callback;
344   MatchFinder Finder;
345   Finder.addDynamicMatcher(Matcher, &Callback);
346   Finder.matchAST(Context);
347   return std::move(Callback.Nodes);
348 }
349 
350 } // end namespace ast_matchers
351 } // end namespace clang
352 
353 #endif
354