@@ -44,7 +44,9 @@ bool HelpQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
4444 " set bind-root (true|false) "
4545 " Set whether to bind the root matcher to \" root\" .\n "
4646 " set print-matcher (true|false) "
47- " Set whether to print the current matcher,\n "
47+ " Set whether to print the current matcher.\n "
48+ " set enable-profile (true|false) "
49+ " Set whether to enable matcher profiling.\n "
4850 " set traversal <kind> "
4951 " Set traversal kind of clang-query session. Available kinds are:\n "
5052 " AsIs "
@@ -82,27 +84,53 @@ namespace {
8284
8385struct CollectBoundNodes : MatchFinder::MatchCallback {
8486 std::vector<BoundNodes> &Bindings;
85- CollectBoundNodes (std::vector<BoundNodes> &Bindings) : Bindings(Bindings) {}
87+ StringRef Unit;
88+ CollectBoundNodes (std::vector<BoundNodes> &Bindings, StringRef Unit)
89+ : Bindings(Bindings), Unit(Unit) {}
8690 void run (const MatchFinder::MatchResult &Result) override {
8791 Bindings.push_back (Result.Nodes );
8892 }
93+ StringRef getID () const override { return Unit; }
94+ };
95+
96+ struct QueryProfiler {
97+ llvm::StringMap<llvm::TimeRecord> Records;
98+
99+ ~QueryProfiler () {
100+ llvm::TimerGroup TG (" clang-query" , " clang-query matcher profiling" ,
101+ Records);
102+ TG.print (llvm::errs ());
103+ llvm::errs ().flush ();
104+ }
89105};
90106
91107} // namespace
92108
93109bool MatchQuery::run (llvm::raw_ostream &OS, QuerySession &QS) const {
94110 unsigned MatchCount = 0 ;
95111
112+ std::optional<QueryProfiler> Profiler;
113+ if (QS.EnableProfile )
114+ Profiler.emplace ();
115+
96116 for (auto &AST : QS.ASTs ) {
97- MatchFinder Finder;
117+ ast_matchers::MatchFinder::MatchFinderOptions FinderOptions;
118+ std::optional<llvm::StringMap<llvm::TimeRecord>> Records;
119+ if (QS.EnableProfile ) {
120+ Records.emplace ();
121+ FinderOptions.CheckProfiling .emplace (*Records);
122+ }
123+
124+ MatchFinder Finder (FinderOptions);
98125 std::vector<BoundNodes> Matches;
99126 DynTypedMatcher MaybeBoundMatcher = Matcher;
100127 if (QS.BindRoot ) {
101128 std::optional<DynTypedMatcher> M = Matcher.tryBind (" root" );
102129 if (M)
103130 MaybeBoundMatcher = *M;
104131 }
105- CollectBoundNodes Collect (Matches);
132+ StringRef OrigSrcName = AST->getOriginalSourceFileName ();
133+ CollectBoundNodes Collect (Matches, OrigSrcName);
106134 if (!Finder.addDynamicMatcher (MaybeBoundMatcher, &Collect)) {
107135 OS << " Not a valid top-level matcher.\n " ;
108136 return false ;
@@ -111,6 +139,8 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
111139 ASTContext &Ctx = AST->getASTContext ();
112140 Ctx.getParentMapContext ().setTraversalKind (QS.TK );
113141 Finder.matchAST (Ctx);
142+ if (QS.EnableProfile )
143+ Profiler->Records [OrigSrcName] += (*Records)[OrigSrcName];
114144
115145 if (QS.PrintMatcher ) {
116146 SmallVector<StringRef, 4 > Lines;
0 commit comments