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. 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. 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 { 125 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 void addMatcher(const CXXCtorInitializerMatcher &NodeMatch, 162 MatchCallback *Action); 163 /// @} 164 165 /// \brief Adds a matcher to execute when running over the AST. 166 /// 167 /// This is similar to \c addMatcher(), but it uses the dynamic interface. It 168 /// is more flexible, but the lost type information enables a caller to pass 169 /// a matcher that cannot match anything. 170 /// 171 /// \returns \c true if the matcher is a valid top-level matcher, \c false 172 /// otherwise. 173 bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch, 174 MatchCallback *Action); 175 176 /// \brief Creates a clang ASTConsumer that finds all matches. 177 std::unique_ptr<clang::ASTConsumer> newASTConsumer(); 178 179 /// \brief Calls the registered callbacks on all matches on the given \p Node. 180 /// 181 /// Note that there can be multiple matches on a single node, for 182 /// example when using decl(forEachDescendant(stmt())). 183 /// 184 /// @{ 185 template <typename T> void match(const T &Node, ASTContext &Context) { 186 match(clang::ast_type_traits::DynTypedNode::create(Node), Context); 187 } 188 void match(const clang::ast_type_traits::DynTypedNode &Node, 189 ASTContext &Context); 190 /// @} 191 192 /// \brief Finds all matches in the given AST. 193 void matchAST(ASTContext &Context); 194 195 /// \brief Registers a callback to notify the end of parsing. 196 /// 197 /// The provided closure is called after parsing is done, before the AST is 198 /// traversed. Useful for benchmarking. 199 /// Each call to FindAll(...) will call the closure once. 200 void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone); 201 202 /// \brief For each \c Matcher<> a \c MatchCallback that will be called 203 /// when it matches. 204 struct MatchersByType { 205 std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *>> 206 DeclOrStmt; 207 std::vector<std::pair<TypeMatcher, MatchCallback *>> Type; 208 std::vector<std::pair<NestedNameSpecifierMatcher, MatchCallback *>> 209 NestedNameSpecifier; 210 std::vector<std::pair<NestedNameSpecifierLocMatcher, MatchCallback *>> 211 NestedNameSpecifierLoc; 212 std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc; 213 std::vector<std::pair<CXXCtorInitializerMatcher, MatchCallback *>> CtorInit; 214 /// \brief All the callbacks in one container to simplify iteration. 215 llvm::SmallPtrSet<MatchCallback *, 16> AllCallbacks; 216 }; 217 218 private: 219 MatchersByType Matchers; 220 221 MatchFinderOptions Options; 222 223 /// \brief Called when parsing is done. 224 ParsingDoneTestCallback *ParsingDone; 225 }; 226 227 /// \brief Returns the results of matching \p Matcher on \p Node. 228 /// 229 /// Collects the \c BoundNodes of all callback invocations when matching 230 /// \p Matcher on \p Node and returns the collected results. 231 /// 232 /// Multiple results occur when using matchers like \c forEachDescendant, 233 /// which generate a result for each sub-match. 234 /// 235 /// If you want to find all matches on the sub-tree rooted at \c Node (rather 236 /// than only the matches on \c Node itself), surround the \c Matcher with a 237 /// \c findAll(). 238 /// 239 /// \see selectFirst 240 /// @{ 241 template <typename MatcherT, typename NodeT> 242 SmallVector<BoundNodes, 1> 243 match(MatcherT Matcher, const NodeT &Node, ASTContext &Context); 244 245 template <typename MatcherT> 246 SmallVector<BoundNodes, 1> 247 match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node, 248 ASTContext &Context); 249 /// @} 250 251 /// \brief Returns the results of matching \p Matcher on the translation unit of 252 /// \p Context and collects the \c BoundNodes of all callback invocations. 253 template <typename MatcherT> 254 SmallVector<BoundNodes, 1> match(MatcherT Matcher, ASTContext &Context); 255 256 /// \brief Returns the first result of type \c NodeT bound to \p BoundTo. 257 /// 258 /// Returns \c NULL if there is no match, or if the matching node cannot be 259 /// casted to \c NodeT. 260 /// 261 /// This is useful in combanation with \c match(): 262 /// \code 263 /// const Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"), 264 /// Node, Context)); 265 /// \endcode 266 template <typename NodeT> 267 const NodeT * 268 selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) { 269 for (const BoundNodes &N : Results) { 270 if (const NodeT *Node = N.getNodeAs<NodeT>(BoundTo)) 271 return Node; 272 } 273 return nullptr; 274 } 275 276 namespace internal { 277 class CollectMatchesCallback : public MatchFinder::MatchCallback { 278 public: 279 void run(const MatchFinder::MatchResult &Result) override { 280 Nodes.push_back(Result.Nodes); 281 } 282 SmallVector<BoundNodes, 1> Nodes; 283 }; 284 } 285 286 template <typename MatcherT> 287 SmallVector<BoundNodes, 1> 288 match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node, 289 ASTContext &Context) { 290 internal::CollectMatchesCallback Callback; 291 MatchFinder Finder; 292 Finder.addMatcher(Matcher, &Callback); 293 Finder.match(Node, Context); 294 return std::move(Callback.Nodes); 295 } 296 297 template <typename MatcherT, typename NodeT> 298 SmallVector<BoundNodes, 1> 299 match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) { 300 return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context); 301 } 302 303 template <typename MatcherT> 304 SmallVector<BoundNodes, 1> 305 match(MatcherT Matcher, ASTContext &Context) { 306 internal::CollectMatchesCallback Callback; 307 MatchFinder Finder; 308 Finder.addMatcher(Matcher, &Callback); 309 Finder.matchAST(Context); 310 return std::move(Callback.Nodes); 311 } 312 313 } // end namespace ast_matchers 314 } // end namespace clang 315 316 #endif 317