//===--- ASTMatchFinder.h - Structural query framework ----------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Provides a way to construct an ASTConsumer that runs given matchers // over the AST and invokes a given callback on every match. // // The general idea is to construct a matcher expression that describes a // subtree match on the AST. Next, a callback that is executed every time the // expression matches is registered, and the matcher is run over the AST of // some code. Matched subexpressions can be bound to string IDs and easily // be accessed from the registered callback. The callback can than use the // AST nodes that the subexpressions matched on to output information about // the match or construct changes that can be applied to the code. // // Example: // class HandleMatch : public MatchFinder::MatchCallback { // public: // virtual void Run(const MatchFinder::MatchResult &Result) { // const CXXRecordDecl *Class = // Result.Nodes.GetDeclAs<CXXRecordDecl>("id"); // ... // } // }; // // int main(int argc, char **argv) { // ClangTool Tool(argc, argv); // MatchFinder finder; // finder.AddMatcher(Id("id", record(hasName("::a_namespace::AClass"))), // new HandleMatch); // return Tool.Run(newFrontendActionFactory(&finder)); // } // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H #define LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H #include "clang/ASTMatchers/ASTMatchers.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/Timer.h" #include <optional> namespace clang { namespace ast_matchers { /// A class to allow finding matches over the Clang AST. /// /// After creation, you can add multiple matchers to the MatchFinder via /// calls to addMatcher(...). /// /// Once all matchers are added, newASTConsumer() returns an ASTConsumer /// that will trigger the callbacks specified via addMatcher(...) when a match /// is found. /// /// The order of matches is guaranteed to be equivalent to doing a pre-order /// traversal on the AST, and applying the matchers in the order in which they /// were added to the MatchFinder. /// /// See ASTMatchers.h for more information about how to create matchers. /// /// Not intended to be subclassed. class MatchFinder { … }; /// Returns the results of matching \p Matcher on \p Node. /// /// Collects the \c BoundNodes of all callback invocations when matching /// \p Matcher on \p Node and returns the collected results. /// /// Multiple results occur when using matchers like \c forEachDescendant, /// which generate a result for each sub-match. /// /// If you want to find all matches on the sub-tree rooted at \c Node (rather /// than only the matches on \c Node itself), surround the \c Matcher with a /// \c findAll(). /// /// \see selectFirst /// @{ template <typename MatcherT, typename NodeT> SmallVector<BoundNodes, 1> match(MatcherT Matcher, const NodeT &Node, ASTContext &Context); template <typename MatcherT> SmallVector<BoundNodes, 1> match(MatcherT Matcher, const DynTypedNode &Node, ASTContext &Context); /// @} /// Returns the results of matching \p Matcher on the translation unit of /// \p Context and collects the \c BoundNodes of all callback invocations. template <typename MatcherT> SmallVector<BoundNodes, 1> match(MatcherT Matcher, ASTContext &Context); /// Returns the first result of type \c NodeT bound to \p BoundTo. /// /// Returns \c NULL if there is no match, or if the matching node cannot be /// casted to \c NodeT. /// /// This is useful in combanation with \c match(): /// \code /// const Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"), /// Node, Context)); /// \endcode template <typename NodeT> const NodeT * selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) { … } namespace internal { class CollectMatchesCallback : public MatchFinder::MatchCallback { … }; } template <typename MatcherT> SmallVector<BoundNodes, 1> match(MatcherT Matcher, const DynTypedNode &Node, ASTContext &Context) { … } template <typename MatcherT, typename NodeT> SmallVector<BoundNodes, 1> match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) { … } template <typename MatcherT> SmallVector<BoundNodes, 1> match(MatcherT Matcher, ASTContext &Context) { … } inline SmallVector<BoundNodes, 1> matchDynamic(internal::DynTypedMatcher Matcher, const DynTypedNode &Node, ASTContext &Context) { … } template <typename NodeT> SmallVector<BoundNodes, 1> matchDynamic(internal::DynTypedMatcher Matcher, const NodeT &Node, ASTContext &Context) { … } inline SmallVector<BoundNodes, 1> matchDynamic(internal::DynTypedMatcher Matcher, ASTContext &Context) { … } } // end namespace ast_matchers } // end namespace clang #endif