• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- ASTMatchFinder.h - Structural query framework ----------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  Provides a way to construct an ASTConsumer that runs given matchers
11 //  over the AST and invokes a given callback on every match.
12 //
13 //  The general idea is to construct a matcher expression that describes a
14 //  subtree match on the AST. Next, a callback that is executed every time the
15 //  expression matches is registered, and the matcher is run over the AST of
16 //  some code. Matched subexpressions can be bound to string IDs and easily
17 //  be accessed from the registered callback. The callback can than use the
18 //  AST nodes that the subexpressions matched on to output information about
19 //  the match or construct changes that can be applied to the code.
20 //
21 //  Example:
22 //  class HandleMatch : public MatchFinder::MatchCallback {
23 //  public:
24 //    virtual void Run(const MatchFinder::MatchResult &Result) {
25 //      const CXXRecordDecl *Class =
26 //          Result.Nodes.GetDeclAs<CXXRecordDecl>("id");
27 //      ...
28 //    }
29 //  };
30 //
31 //  int main(int argc, char **argv) {
32 //    ClangTool Tool(argc, argv);
33 //    MatchFinder finder;
34 //    finder.AddMatcher(Id("id", record(hasName("::a_namespace::AClass"))),
35 //                      new HandleMatch);
36 //    return Tool.Run(newFrontendActionFactory(&finder));
37 //  }
38 //
39 //===----------------------------------------------------------------------===//
40 
41 #ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
42 #define LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
43 
44 #include "clang/ASTMatchers/ASTMatchers.h"
45 #include "llvm/ADT/SmallPtrSet.h"
46 #include "llvm/ADT/StringMap.h"
47 #include "llvm/Support/Timer.h"
48 
49 namespace clang {
50 
51 namespace ast_matchers {
52 
53 /// \brief 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   /// \brief 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 {
76     MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context);
77 
78     /// \brief Contains the nodes bound on the current match.
79     ///
80     /// This allows user code to easily extract matched AST nodes.
81     const BoundNodes Nodes;
82 
83     /// \brief Utilities for interpreting the matched AST structures.
84     /// @{
85     clang::ASTContext * const Context;
86     clang::SourceManager * const SourceManager;
87     /// @}
88   };
89 
90   /// \brief Called when the Match registered for it was successfully found
91   /// in the AST.
92   class MatchCallback {
93   public:
94     virtual ~MatchCallback();
95 
96     /// \brief Called on every match by the \c MatchFinder.
97     virtual void run(const MatchResult &Result) = 0;
98 
99     /// \brief Called at the start of each translation unit.
100     ///
101     /// Optionally override to do per translation unit tasks.
onStartOfTranslationUnit()102     virtual void onStartOfTranslationUnit() {}
103 
104     /// \brief Called at the end of each translation unit.
105     ///
106     /// Optionally override to do per translation unit tasks.
onEndOfTranslationUnit()107     virtual void onEndOfTranslationUnit() {}
108 
109     /// \brief 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 
116   /// \brief Called when parsing is finished. Intended for testing only.
117   class ParsingDoneTestCallback {
118   public:
119     virtual ~ParsingDoneTestCallback();
120     virtual void run() = 0;
121   };
122 
123   struct MatchFinderOptions {
124     struct Profiling {
ProfilingMatchFinderOptions::Profiling125       Profiling(llvm::StringMap<llvm::TimeRecord> &Records)
126           : Records(Records) {}
127 
128       /// \brief Per bucket timing information.
129       llvm::StringMap<llvm::TimeRecord> &Records;
130     };
131 
132     /// \brief Enables per-check timers.
133     ///
134     /// It prints a report after match.
135     llvm::Optional<Profiling> CheckProfiling;
136   };
137 
138   MatchFinder(MatchFinderOptions Options = MatchFinderOptions());
139   ~MatchFinder();
140 
141   /// \brief Adds a matcher to execute when running over the AST.
142   ///
143   /// Calls 'Action' with the BoundNodes on every match.
144   /// Adding more than one 'NodeMatch' allows finding different matches in a
145   /// single pass over the AST.
146   ///
147   /// Does not take ownership of 'Action'.
148   /// @{
149   void addMatcher(const DeclarationMatcher &NodeMatch,
150                   MatchCallback *Action);
151   void addMatcher(const TypeMatcher &NodeMatch,
152                   MatchCallback *Action);
153   void addMatcher(const StatementMatcher &NodeMatch,
154                   MatchCallback *Action);
155   void addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
156                   MatchCallback *Action);
157   void addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
158                   MatchCallback *Action);
159   void addMatcher(const TypeLocMatcher &NodeMatch,
160                   MatchCallback *Action);
161   /// @}
162 
163   /// \brief Adds a matcher to execute when running over the AST.
164   ///
165   /// This is similar to \c addMatcher(), but it uses the dynamic interface. It
166   /// is more flexible, but the lost type information enables a caller to pass
167   /// a matcher that cannot match anything.
168   ///
169   /// \returns \c true if the matcher is a valid top-level matcher, \c false
170   ///   otherwise.
171   bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
172                          MatchCallback *Action);
173 
174   /// \brief Creates a clang ASTConsumer that finds all matches.
175   std::unique_ptr<clang::ASTConsumer> newASTConsumer();
176 
177   /// \brief Calls the registered callbacks on all matches on the given \p Node.
178   ///
179   /// Note that there can be multiple matches on a single node, for
180   /// example when using decl(forEachDescendant(stmt())).
181   ///
182   /// @{
match(const T & Node,ASTContext & Context)183   template <typename T> void match(const T &Node, ASTContext &Context) {
184     match(clang::ast_type_traits::DynTypedNode::create(Node), Context);
185   }
186   void match(const clang::ast_type_traits::DynTypedNode &Node,
187              ASTContext &Context);
188   /// @}
189 
190   /// \brief Finds all matches in the given AST.
191   void matchAST(ASTContext &Context);
192 
193   /// \brief Registers a callback to notify the end of parsing.
194   ///
195   /// The provided closure is called after parsing is done, before the AST is
196   /// traversed. Useful for benchmarking.
197   /// Each call to FindAll(...) will call the closure once.
198   void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
199 
200   /// \brief For each \c Matcher<> a \c MatchCallback that will be called
201   /// when it matches.
202   struct MatchersByType {
203     std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *>>
204         DeclOrStmt;
205     std::vector<std::pair<TypeMatcher, MatchCallback *>> Type;
206     std::vector<std::pair<NestedNameSpecifierMatcher, MatchCallback *>>
207         NestedNameSpecifier;
208     std::vector<std::pair<NestedNameSpecifierLocMatcher, MatchCallback *>>
209         NestedNameSpecifierLoc;
210     std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc;
211     /// \brief All the callbacks in one container to simplify iteration.
212     llvm::SmallPtrSet<MatchCallback *, 16> AllCallbacks;
213   };
214 
215 private:
216   MatchersByType Matchers;
217 
218   MatchFinderOptions Options;
219 
220   /// \brief Called when parsing is done.
221   ParsingDoneTestCallback *ParsingDone;
222 };
223 
224 /// \brief Returns the results of matching \p Matcher on \p Node.
225 ///
226 /// Collects the \c BoundNodes of all callback invocations when matching
227 /// \p Matcher on \p Node and returns the collected results.
228 ///
229 /// Multiple results occur when using matchers like \c forEachDescendant,
230 /// which generate a result for each sub-match.
231 ///
232 /// \see selectFirst
233 /// @{
234 template <typename MatcherT, typename NodeT>
235 SmallVector<BoundNodes, 1>
236 match(MatcherT Matcher, const NodeT &Node, ASTContext &Context);
237 
238 template <typename MatcherT>
239 SmallVector<BoundNodes, 1>
240 match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
241       ASTContext &Context);
242 /// @}
243 
244 /// \brief Returns the results of matching \p Matcher on the translation unit of
245 /// \p Context and collects the \c BoundNodes of all callback invocations.
246 template <typename MatcherT>
247 SmallVector<BoundNodes, 1> match(MatcherT Matcher, ASTContext &Context);
248 
249 /// \brief Returns the first result of type \c NodeT bound to \p BoundTo.
250 ///
251 /// Returns \c NULL if there is no match, or if the matching node cannot be
252 /// casted to \c NodeT.
253 ///
254 /// This is useful in combanation with \c match():
255 /// \code
256 ///   const Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"),
257 ///                                                 Node, Context));
258 /// \endcode
259 template <typename NodeT>
260 const NodeT *
selectFirst(StringRef BoundTo,const SmallVectorImpl<BoundNodes> & Results)261 selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) {
262   for (const BoundNodes &N : Results) {
263     if (const NodeT *Node = N.getNodeAs<NodeT>(BoundTo))
264       return Node;
265   }
266   return nullptr;
267 }
268 
269 namespace internal {
270 class CollectMatchesCallback : public MatchFinder::MatchCallback {
271 public:
run(const MatchFinder::MatchResult & Result)272   void run(const MatchFinder::MatchResult &Result) override {
273     Nodes.push_back(Result.Nodes);
274   }
275   SmallVector<BoundNodes, 1> Nodes;
276 };
277 }
278 
279 template <typename MatcherT>
280 SmallVector<BoundNodes, 1>
match(MatcherT Matcher,const ast_type_traits::DynTypedNode & Node,ASTContext & Context)281 match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
282       ASTContext &Context) {
283   internal::CollectMatchesCallback Callback;
284   MatchFinder Finder;
285   Finder.addMatcher(Matcher, &Callback);
286   Finder.match(Node, Context);
287   return std::move(Callback.Nodes);
288 }
289 
290 template <typename MatcherT, typename NodeT>
291 SmallVector<BoundNodes, 1>
match(MatcherT Matcher,const NodeT & Node,ASTContext & Context)292 match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
293   return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context);
294 }
295 
296 template <typename MatcherT>
297 SmallVector<BoundNodes, 1>
match(MatcherT Matcher,ASTContext & Context)298 match(MatcherT Matcher, ASTContext &Context) {
299   internal::CollectMatchesCallback Callback;
300   MatchFinder Finder;
301   Finder.addMatcher(Matcher, &Callback);
302   Finder.matchAST(Context);
303   return std::move(Callback.Nodes);
304 }
305 
306 } // end namespace ast_matchers
307 } // end namespace clang
308 
309 #endif
310