Skip to content

Conversation

@vbvictor
Copy link
Contributor

@vbvictor vbvictor commented Aug 17, 2025

Before this change, -quiet mode in clang-tidy generated meaningless messages xxx warnings generated in output:

// main.cpp
#include <iostream>

int main() {
  std::cout << 42;
}
> clang-tidy -checks='-*,readability-magic-numbers' -quiet main.cpp

82 warnings generated.
main.cpp:4:16: warning: 42 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
    4 |   std::cout << 42;
      |                ^

As you can see, 82 warnings generated. does not say much quiet mode, this patch removes this message completely:

> ./build/bin/clang-tidy -p build -checks='-*,readability-magic-numbers' -quiet main.cpp

main.cpp:4:16: warning: 42 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
    4 |   std::cout << 42;
      |                ^

In contrast, when running without quiet, It gives some meaningful information because we know how many messages were suppressed thus calculating total messages count:

> clang-tidy -checks='-*,readability-magic-numbers' main.cpp

82 warnings generated.
main.cpp:4:16: warning: 42 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
    4 |   std::cout << 42;
      |                ^
Suppressed 81 warnings (81 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.

Fixes #47042

@llvmbot
Copy link
Member

llvmbot commented Aug 17, 2025

@llvm/pr-subscribers-clang-tidy

@llvm/pr-subscribers-clang-tools-extra

Author: Baranov Victor (vbvictor)

Changes

Before this change, -quiet mode in clang-tidy generated meaningless messages xxx warnings generated in output:

// main.cpp
#include &lt;iostream&gt;

int main() {
  std::cout &lt;&lt; 42;
}
&gt; clang-tidy -checks='-*,readability-magic-numbers' -quiet main.cpp

82 warnings generated.
main.cpp:4:16: warning: 42 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
    4 |   std::cout &lt;&lt; 42;
      |                ^

As you can see, 82 warnings generated. does not say much quiet mode, this patch removes this message completely:

&gt; ./build/bin/clang-tidy -p build -checks='-*,readability-magic-numbers' -quiet main.cpp

main.cpp:4:16: warning: 42 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
    4 |   std::cout &lt;&lt; 42;
      |                ^

In contrast, when running without quiet, It gives some meaningful information because we know how many messages were suppressed thus calculating total messages count:

&gt; clang-tidy -checks='-*,readability-magic-numbers' main.cpp

82 warnings generated.
main.cpp:4:16: warning: 42 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
    4 |   std::cout &lt;&lt; 42;
      |                ^
Suppressed 81 warnings (81 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.

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

6 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/ClangTidy.cpp (+8-4)
  • (modified) clang-tools-extra/clang-tidy/ClangTidy.h (+2-1)
  • (modified) clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp (+1-1)
  • (modified) clang-tools-extra/docs/ReleaseNotes.rst (+3)
  • (modified) clang-tools-extra/test/clang-tidy/infrastructure/file-filter-symlinks.cpp (+1-1)
  • (added) clang-tools-extra/test/clang-tidy/infrastructure/quiet-flag.cpp (+14)
diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp
index 4ae2864d310d0..8f5728dea8c2a 100644
--- a/clang-tools-extra/clang-tidy/ClangTidy.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp
@@ -540,7 +540,7 @@ runClangTidy(clang::tidy::ClangTidyContext &Context,
              ArrayRef<std::string> InputFiles,
              llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> BaseFS,
              bool ApplyAnyFix, bool EnableCheckProfile,
-             llvm::StringRef StoreCheckProfile) {
+             llvm::StringRef StoreCheckProfile, bool Quiet) {
   ClangTool Tool(Compilations, InputFiles,
                  std::make_shared<PCHContainerOperations>(), BaseFS);
 
@@ -577,8 +577,9 @@ runClangTidy(clang::tidy::ClangTidyContext &Context,
   class ActionFactory : public FrontendActionFactory {
   public:
     ActionFactory(ClangTidyContext &Context,
-                  IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> BaseFS)
-        : ConsumerFactory(Context, std::move(BaseFS)) {}
+                  IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> BaseFS,
+                  bool Quiet)
+        : ConsumerFactory(Context, std::move(BaseFS)), Quiet(Quiet) {}
     std::unique_ptr<FrontendAction> create() override {
       return std::make_unique<Action>(&ConsumerFactory);
     }
@@ -589,6 +590,8 @@ runClangTidy(clang::tidy::ClangTidyContext &Context,
                        DiagnosticConsumer *DiagConsumer) override {
       // Explicitly ask to define __clang_analyzer__ macro.
       Invocation->getPreprocessorOpts().SetUpStaticAnalyzer = true;
+      if (Quiet)
+        Invocation->getDiagnosticOpts().ShowCarets = false;
       return FrontendActionFactory::runInvocation(
           Invocation, Files, PCHContainerOps, DiagConsumer);
     }
@@ -607,9 +610,10 @@ runClangTidy(clang::tidy::ClangTidyContext &Context,
     };
 
     ClangTidyASTConsumerFactory ConsumerFactory;
+    bool Quiet;
   };
 
-  ActionFactory Factory(Context, std::move(BaseFS));
+  ActionFactory Factory(Context, std::move(BaseFS), Quiet);
   Tool.run(&Factory);
   return DiagConsumer.take();
 }
diff --git a/clang-tools-extra/clang-tidy/ClangTidy.h b/clang-tools-extra/clang-tidy/ClangTidy.h
index 454261bbd6840..d37d68ec0a5b9 100644
--- a/clang-tools-extra/clang-tidy/ClangTidy.h
+++ b/clang-tools-extra/clang-tidy/ClangTidy.h
@@ -94,7 +94,8 @@ runClangTidy(clang::tidy::ClangTidyContext &Context,
              ArrayRef<std::string> InputFiles,
              llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> BaseFS,
              bool ApplyAnyFix, bool EnableCheckProfile = false,
-             llvm::StringRef StoreCheckProfile = StringRef());
+             llvm::StringRef StoreCheckProfile = StringRef(),
+             bool Quiet = false);
 
 /// Controls what kind of fixes clang-tidy is allowed to apply.
 enum FixBehaviour {
diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
index df3a8b22b1e24..bef3b938b5afd 100644
--- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
+++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
@@ -717,7 +717,7 @@ int clangTidyMain(int argc, const char **argv) {
                            EnableModuleHeadersParsing);
   std::vector<ClangTidyError> Errors =
       runClangTidy(Context, OptionsParser->getCompilations(), PathList, BaseFS,
-                   FixNotes, EnableCheckProfile, ProfilePrefix);
+                   FixNotes, EnableCheckProfile, ProfilePrefix, Quiet);
   bool FoundErrors = llvm::any_of(Errors, [](const ClangTidyError &E) {
     return E.DiagLevel == ClangTidyError::Error;
   });
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index b481c56c262c4..e4b470026ef08 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -112,6 +112,9 @@ Improvements to clang-tidy
 - Improved documentation of the `-line-filter` command-line flag of
   :program:`clang-tidy` and :program:`run-clang-tidy.py`.
 
+- Improved :program:`clang-tidy` option `quiet` to suppresses diagnostic count
+  messages.
+
 New checks
 ^^^^^^^^^^
 
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/file-filter-symlinks.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/file-filter-symlinks.cpp
index 7efa7d070f69f..58f3b23cb1dbf 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/file-filter-symlinks.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/file-filter-symlinks.cpp
@@ -10,7 +10,7 @@
 // RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='header_alias\.h' %s -- -I %t 2>&1 | FileCheck --check-prefix=CHECK_HEADER_ALIAS %s
 // RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='header_alias\.h' -quiet %s -- -I %t 2>&1 | FileCheck --check-prefix=CHECK_HEADER_ALIAS %s
 // RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='header\.h' %s -- -I %t 2>&1 | FileCheck --check-prefix=CHECK_HEADER %s
-// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='header\.h' -quiet %s -- -I %t 2>&1 | FileCheck --check-prefix=CHECK_HEADER %s
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='header\.h' -quiet %s -- -I %t 2>&1 | FileCheck --check-prefix=CHECK_HEADER --allow-empty %s
 
 // Check that `-header-filter` operates on the same file paths as paths in
 // diagnostics printed by ClangTidy.
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/quiet-flag.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/quiet-flag.cpp
new file mode 100644
index 0000000000000..0e3d6164163a4
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/quiet-flag.cpp
@@ -0,0 +1,14 @@
+// RUN: clang-tidy -checks=-*,readability-magic-numbers %t.cpp -- 2>&1 | FileCheck %s --check-prefix=CHECK-NORMAL
+// RUN: clang-tidy -checks=-*,readability-magic-numbers -quiet %t.cpp -- 2>&1 | FileCheck %s --check-prefix=CHECK-QUIET
+
+// Normal mode should show warning count
+// CHECK-NORMAL: 1 warning generated
+// CHECK-NORMAL: warning: 42 is a magic number
+
+// Quiet mode should suppress warning count 
+// CHECK-QUIET-NOT: 1 warning generated
+// CHECK-QUIET: warning: 42 is a magic number
+
+int main() {
+  int x = 42;
+}

@vbvictor vbvictor changed the title [clang-tidy] Improve "-quiet" option by suppressing warnings generated count [clang-tidy] Improve "-quiet" option by suppressing "xxx warnings generated" Aug 17, 2025
Copy link
Contributor

@carlosgalvezp carlosgalvezp left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for fixing!

It might be worth double-checking the comment I wrote about this carets option (which I guess is equivalent to passing the command line flag):

#47042 (comment)

In particular the fact that part of the diagnostic is removed. But perhaps it's only for compiler warnings and it's not a problem for clang-tidy.

@vbvictor
Copy link
Contributor Author

vbvictor commented Aug 17, 2025

LGTM, thanks for fixing!

It might be worth double-checking the comment I wrote about this carets option (which I guess is equivalent to passing the command line flag):

#47042 (comment)

In particular the fact that part of the diagnostic is removed. But perhaps it's only for compiler warnings and it's not a problem for clang-tidy.

Thanks for the issue link and concerns!

Yes, it looks to don't affect clang-tidy because there are 2 separate DiagnosticOptions we can set in clang-tidy.
The first ClangTidyDiagnosticConsumer that has one set of DiagnosticOptions is left unchanged:

ClangTidyDiagnosticConsumer DiagConsumer(Context, nullptr, true, ApplyAnyFix);
auto DiagOpts = std::make_unique<DiagnosticOptions>();
DiagnosticsEngine DE(DiagnosticIDs::create(), *DiagOpts, &DiagConsumer,
/*ShouldOwnClient=*/false);
Context.setDiagnosticsEngine(std::move(DiagOpts), &DE);

And second one for CompilerInvocation that handles warnings generated but passes all actual diagnostics to consumer. This part I changed in PR and it handles.

I've added tests with carets (hopefully correctly) so this feature will be tracked in the future.

@vbvictor
Copy link
Contributor Author

P.S.
One of the comments in the original issue was right about annoyance with CI integration.
I started tinkering with clang-tidy CI for LLVM and stumbled upon this. I'd need to also enhance -quiet mode in scripts because for now it gives such output:

Running clang-tidy for 446 files out of 5099 in compilation database ...
[  1/446][3.6s] clang-tidy-21 -p=build/ -quiet /home/victor/llvm2/llvm-project/clang-tools-extra/clang-tidy/misc/ConfusableTable/BuildConfusableTable.cpp
33046 warnings generated.

The last string will be suppressed in this PR and the first and second lines should be suppressed inside run-clang-tidy

@carlosgalvezp
Copy link
Contributor

Great, thanks for checking and adding this use case to the unit test! LGTM

@vbvictor vbvictor merged commit ed26993 into llvm:main Aug 19, 2025
10 checks passed
@vbvictor vbvictor deleted the suppress-xxx-warnings-generated-in-quite-mode branch August 19, 2025 18:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

--quiet does not silence 'x warnings generated'

3 participants