Skip to content

Conversation

@zeyi2
Copy link
Member

@zeyi2 zeyi2 commented Nov 26, 2025

This patch fixes an issue in progress reporting where the processed item counter could exceed the total item count, leading to confusing outputs like [22/18].

Closes #169168

@llvmbot llvmbot added the clang Clang issues not falling into any other category label Nov 26, 2025
@llvmbot
Copy link
Member

llvmbot commented Nov 26, 2025

@llvm/pr-subscribers-clang

Author: mitchell (zeyi2)

Changes

This patch fixes an issue in progress reporting where the processed item counter could exceed the total item count, leading to confusing outputs like [22/18].


Full diff: https://github.com/llvm/llvm-project/pull/169640.diff

1 Files Affected:

  • (modified) clang/lib/Tooling/Tooling.cpp (+16-11)
diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp
index 9bae12454d2dc..491294b731e85 100644
--- a/clang/lib/Tooling/Tooling.cpp
+++ b/clang/lib/Tooling/Tooling.cpp
@@ -37,6 +37,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/OptTable.h"
@@ -96,7 +97,7 @@ static bool ignoreExtraCC1Commands(const driver::Compilation *Compilation) {
       OffloadCompilation = true;
 
   if (Jobs.size() > 1) {
-    for (auto *A : Actions){
+    for (auto *A : Actions) {
       // On MacOSX real actions may end up being wrapped in BindArchAction
       if (isa<driver::BindArchAction>(A))
         A = *A->input_begin();
@@ -413,8 +414,8 @@ bool ToolInvocation::run() {
       Driver->BuildCompilation(llvm::ArrayRef(Argv)));
   if (!Compilation)
     return false;
-  const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments(
-      &*Diagnostics, Compilation.get());
+  const llvm::opt::ArgStringList *const CC1Args =
+      getCC1Arguments(&*Diagnostics, Compilation.get());
   if (!CC1Args)
     return false;
   std::unique_ptr<CompilerInvocation> Invocation(
@@ -497,9 +498,7 @@ void ClangTool::appendArgumentsAdjuster(ArgumentsAdjuster Adjuster) {
   ArgsAdjuster = combineAdjusters(std::move(ArgsAdjuster), std::move(Adjuster));
 }
 
-void ClangTool::clearArgumentsAdjusters() {
-  ArgsAdjuster = nullptr;
-}
+void ClangTool::clearArgumentsAdjusters() { ArgsAdjuster = nullptr; }
 
 static void injectResourceDir(CommandLineArguments &Args, const char *Argv0,
                               void *MainAddr) {
@@ -555,8 +554,9 @@ int ClangTool::run(ToolAction *Action) {
   }
 
   size_t NumOfTotalFiles = AbsolutePaths.size();
-  unsigned ProcessedFileCounter = 0;
+  unsigned CurrentFileIndex = 0;
   for (llvm::StringRef File : AbsolutePaths) {
+    ++CurrentFileIndex; // Increment file counter once per file.
     // Currently implementations of CompilationDatabase::getCompileCommands can
     // change the state of the file system (e.g.  prepare generated headers), so
     // this method needs to run right before we invoke the tool, as the next
@@ -571,6 +571,7 @@ int ClangTool::run(ToolAction *Action) {
       FileSkipped = true;
       continue;
     }
+    unsigned CurrentCommandIndexForFile = 0;
     for (CompileCommand &CompileCommand : CompileCommandsForFile) {
       // If the 'directory' field of the compilation database is empty, display
       // an error and use the working directory instead.
@@ -617,12 +618,16 @@ int ClangTool::run(ToolAction *Action) {
       // pass in made-up names here. Make sure this works on other platforms.
       injectResourceDir(CommandLine, "clang_tool", &StaticSymbol);
 
+      ++CurrentCommandIndexForFile;
+
       // FIXME: We need a callback mechanism for the tool writer to output a
       // customized message for each file.
-      if (NumOfTotalFiles > 1)
-        llvm::errs() << "[" + std::to_string(++ProcessedFileCounter) + "/" +
-                            std::to_string(NumOfTotalFiles) +
-                            "] Processing file " + File
+      if (NumOfTotalFiles > 1 || CompileCommandsForFile.size() > 1)
+        llvm::errs() << "[" + std::to_string(CurrentFileIndex) + "/" +
+                            std::to_string(NumOfTotalFiles) + "] (" +
+                            std::to_string(CurrentCommandIndexForFile) + "/" +
+                            std::to_string(CompileCommandsForFile.size()) +
+                            ") Processing file " + File
                      << ".\n";
       ToolInvocation Invocation(std::move(CommandLine), Action, Files.get(),
                                 PCHContainerOps);

@zeyi2
Copy link
Member Author

zeyi2 commented Nov 26, 2025

I believe this patch needs some discussion, for it introduces a new format:

[1/5] (1/1) Processing file ...
[2/5] (1/2) Processing file ...
[2/5] (2/2) Processing file ...
[3/5] (1/2) Processing file ...

I initially considered (and implemented) a solution that does normal printing like [n/TotalActions]. But I discarded it and chose this way of printing due to two main reasons:

  • Complexity: Calculating the exact number of compile actions requires calling getCompileCommands for every input files. Which is O(N) and may cause startup delay for large projects.
  • API usage: getCompileCommands may be stateful. Pre-scanning the database violates the requirement of "this method needs to run right before we invoke the tool", and it may trigger unnecessary side effects.

The current patch maintains the O(1) complexity and doesn't violate the API usage, while still reflect the correct progress without misleading users.

I understand that this may not be an ideal way of solving this problem. I highly value any thoughts or feedback on this implementation or potential alternative strategies.

Thanks in advance.

@zeyi2 zeyi2 requested a review from hokein November 26, 2025 11:41
@zwuis zwuis added the clang:tooling LibTooling label Nov 27, 2025
@zwuis
Copy link
Contributor

zwuis commented Nov 27, 2025

[1/5] (1/1) Processing file ...
[2/5] (1/2) Processing file ...
[2/5] (2/2) Processing file ...
[3/5] (1/2) Processing file ...

It seems that removing (1/1) ((X/Y), Y is 1) can reduce confusion.

@zeyi2
Copy link
Member Author

zeyi2 commented Nov 27, 2025

Thanks for feedback! I've changed the printing to:

[1/9] Processing file ...
[2/9] (1/2) Processing file ...
[2/9] (2/2) Processing file ...
[3/9] Processing file ...
[4/9] Processing file ...

@zeyi2
Copy link
Member Author

zeyi2 commented Dec 2, 2025

Friendly ping, please take a look at this small PR when you have a time :)

Thanks!

Copy link
Contributor

@vbvictor vbvictor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make any tests for this new format?
If the user can see it - we should be able to cover it, could be test in clang-tidy infrastructure/ (test different scenarios).

@zeyi2
Copy link
Member Author

zeyi2 commented Dec 7, 2025

Looks like there is a path separators issue. I'm trying to fix it, will ping for another review after the fix is done :)

@zeyi2 zeyi2 requested a review from vbvictor December 7, 2025 14:33
@zeyi2
Copy link
Member Author

zeyi2 commented Dec 9, 2025

The failed testcase seems unrelated to this PR, I'll try rebase onto main again later.

Fixed now.

@github-actions
Copy link

github-actions bot commented Dec 9, 2025

🐧 Linux x64 Test Results

  • 111859 tests passed
  • 4506 tests skipped

✅ The build succeeded and all tests passed.

@github-actions
Copy link

github-actions bot commented Dec 9, 2025

🪟 Windows x64 Test Results

  • 52932 tests passed
  • 2068 tests skipped

✅ The build succeeded and all tests passed.

@vbvictor
Copy link
Contributor

I didn't find an immediate maintainer of core tooling files; could you look at git log to see who reviewed/committed in these files.

@zeyi2 zeyi2 requested a review from AaronBallman December 10, 2025 16:36
@zeyi2
Copy link
Member Author

zeyi2 commented Dec 10, 2025

Hi, Aaron.

Could you please review this patch? It fixes a misleading progress report issue in Tooling (e.g. [22/18]) when files have multiple compile commands.

I have addressed previous feedback from vbvictor and zwuis, could you do some furthur reviews?

Thanks for your time.

@zeyi2
Copy link
Member Author

zeyi2 commented Dec 10, 2025

The failed testcase seems unrelated to this PR (again), I'll try rebase onto main later.

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes seem pretty reasonable but there's a fair amount of unrelated formatting changes. It'd be easier on reviewers to back those unrelated changes out so we can more easily see just what's been materially modified.

@zeyi2 zeyi2 force-pushed the fix-misreport-progress branch from 66079d8 to 1df1da5 Compare December 10, 2025 17:14
@zeyi2
Copy link
Member Author

zeyi2 commented Dec 10, 2025

It'd be easier on reviewers to back those unrelated changes out so we can more easily see just what's been materially modified.

Sorry for the noise, I've cleanup the modification in ToolingTest.cpp. Please take another look when you have time. Thanks for your time and patience.

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:tooling LibTooling clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

clang-tidy misreports progress when duplicating files due to multiple targets

5 participants