https://github.com/joeedh updated 
https://github.com/llvm/llvm-project/pull/182912

>From 17490a6a4e39b0b3a2ddee48d2d2c5b0fd1257ae Mon Sep 17 00:00:00 2001
From: Joe Eagar <[email protected]>
Date: Mon, 23 Feb 2026 10:09:50 -0800
Subject: [PATCH] [clangd] Pull suppression logic into common path, apply for
 driver diagnostics Rebase of https://reviews.llvm.org/D127844# Fixes #1142

---
 clang-tools-extra/clangd/Diagnostics.cpp      | 26 +++++++++++++------
 clang-tools-extra/clangd/Diagnostics.h        |  6 ++---
 clang-tools-extra/clangd/ParsedAST.cpp        |  5 ----
 clang-tools-extra/clangd/Preamble.cpp         |  5 ----
 .../clangd/unittests/CompilerTests.cpp        | 15 +++++++++++
 .../clangd/unittests/DiagnosticsTests.cpp     | 21 +++++++++++++++
 6 files changed, 57 insertions(+), 21 deletions(-)

diff --git a/clang-tools-extra/clangd/Diagnostics.cpp 
b/clang-tools-extra/clangd/Diagnostics.cpp
index e10960ca5850f..f04995740b129 100644
--- a/clang-tools-extra/clangd/Diagnostics.cpp
+++ b/clang-tools-extra/clangd/Diagnostics.cpp
@@ -9,6 +9,7 @@
 #include "Diagnostics.h"
 #include "../clang-tidy/ClangTidyDiagnosticConsumer.h"
 #include "Compiler.h"
+#include "Config.h"
 #include "Protocol.h"
 #include "SourceCode.h"
 #include "support/Logger.h"
@@ -695,6 +696,19 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level 
DiagLevel,
       Info.getDiags()->getDiagnosticIDs()->isDefaultMappingAsError(
           Info.getID());
 
+  if (!isNote(DiagLevel)) {
+    const Config &Cfg = Config::current();
+    // Check if diagnostics is suppressed (possibly by user), before doing any
+    // adjustments.
+    if (Cfg.Diagnostics.SuppressAll ||
+        isDiagnosticSuppressed(Info, Cfg.Diagnostics.Suppress, LangOpts)) {
+      DiagLevel = DiagnosticsEngine::Ignored;
+    } else if (Adjuster) {
+      // FIXME: Merge with feature modules.
+      DiagLevel = Adjuster(DiagLevel, Info);
+    }
+  }
+
   if (Info.getLocation().isInvalid()) {
     // Handle diagnostics coming from command-line arguments. The source 
manager
     // is *not* available at this point, so we cannot use it.
@@ -805,8 +819,7 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level 
DiagLevel,
     }
     if (Message.empty()) // either !SyntheticMessage, or we failed to make one.
       Info.FormatDiagnostic(Message);
-    LastDiag->Fixes.push_back(
-        Fix{std::string(Message), std::move(Edits), {}});
+    LastDiag->Fixes.push_back(Fix{std::string(Message), std::move(Edits), {}});
     return true;
   };
 
@@ -815,9 +828,6 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level 
DiagLevel,
     flushLastDiag();
 
     LastDiag = Diag();
-    // FIXME: Merge with feature modules.
-    if (Adjuster)
-      DiagLevel = Adjuster(DiagLevel, Info);
 
     FillDiagBase(*LastDiag);
     if (isExcluded(LastDiag->ID))
@@ -906,12 +916,12 @@ void StoreDiags::flushLastDiag() {
 
 bool isDiagnosticSuppressed(const clang::Diagnostic &Diag,
                             const llvm::StringSet<> &Suppress,
-                            const LangOptions &LangOpts) {
+                            const std::optional<LangOptions> &LangOpts) {
   // Don't complain about header-only stuff in mainfiles if it's a header.
   // FIXME: would be cleaner to suppress in clang, once we decide whether the
   //        behavior should be to silently-ignore or respect the pragma.
-  if (Diag.getID() == diag::pp_pragma_sysheader_in_main_file &&
-      LangOpts.IsHeaderFile)
+  if (LangOpts && Diag.getID() == diag::pp_pragma_sysheader_in_main_file &&
+      LangOpts->IsHeaderFile)
     return true;
 
   if (const char *CodePtr = getDiagnosticCode(Diag.getID())) {
diff --git a/clang-tools-extra/clangd/Diagnostics.h 
b/clang-tools-extra/clangd/Diagnostics.h
index c45d8dc3aa6ce..95f3da8bd0e47 100644
--- a/clang-tools-extra/clangd/Diagnostics.h
+++ b/clang-tools-extra/clangd/Diagnostics.h
@@ -173,8 +173,8 @@ class StoreDiags : public DiagnosticConsumer {
   std::vector<Diag> Output;
   std::optional<LangOptions> LangOpts;
   std::optional<Diag> LastDiag;
-  std::optional<FullSourceLoc> LastDiagLoc;  // Valid only when LastDiag is 
set.
-  bool LastDiagOriginallyError = false;      // Valid only when LastDiag is 
set.
+  std::optional<FullSourceLoc> LastDiagLoc; // Valid only when LastDiag is set.
+  bool LastDiagOriginallyError = false;     // Valid only when LastDiag is set.
   SourceManager *OrigSrcMgr = nullptr;
 
   llvm::DenseSet<std::pair<unsigned, unsigned>> IncludedErrorLocations;
@@ -183,7 +183,7 @@ class StoreDiags : public DiagnosticConsumer {
 /// Determine whether a (non-clang-tidy) diagnostic is suppressed by config.
 bool isDiagnosticSuppressed(const clang::Diagnostic &Diag,
                             const llvm::StringSet<> &Suppressed,
-                            const LangOptions &);
+                            const std::optional<LangOptions> &);
 /// Take a user-specified diagnostic code, and convert it to a normalized form
 /// stored in the config and consumed by isDiagnosticsSuppressed.
 ///
diff --git a/clang-tools-extra/clangd/ParsedAST.cpp 
b/clang-tools-extra/clangd/ParsedAST.cpp
index c23b5d7a38d37..4e873f1257a17 100644
--- a/clang-tools-extra/clangd/ParsedAST.cpp
+++ b/clang-tools-extra/clangd/ParsedAST.cpp
@@ -585,11 +585,6 @@ ParsedAST::build(llvm::StringRef Filename, const 
ParseInputs &Inputs,
 
     ASTDiags.setLevelAdjuster([&](DiagnosticsEngine::Level DiagLevel,
                                   const clang::Diagnostic &Info) {
-      if (Cfg.Diagnostics.SuppressAll ||
-          isDiagnosticSuppressed(Info, Cfg.Diagnostics.Suppress,
-                                 Clang->getLangOpts()))
-        return DiagnosticsEngine::Ignored;
-
       auto It = OverriddenSeverity.find(Info.getID());
       if (It != OverriddenSeverity.end())
         DiagLevel = It->second;
diff --git a/clang-tools-extra/clangd/Preamble.cpp 
b/clang-tools-extra/clangd/Preamble.cpp
index cdda0208a96d6..f5e512793e98e 100644
--- a/clang-tools-extra/clangd/Preamble.cpp
+++ b/clang-tools-extra/clangd/Preamble.cpp
@@ -598,13 +598,8 @@ buildPreamble(PathRef FileName, CompilerInvocation CI,
       CompilerInstance::createDiagnostics(*VFS, CI.getDiagnosticOpts(),
                                           &PreambleDiagnostics,
                                           /*ShouldOwnClient=*/false);
-  const Config &Cfg = Config::current();
   PreambleDiagnostics.setLevelAdjuster([&](DiagnosticsEngine::Level DiagLevel,
                                            const clang::Diagnostic &Info) {
-    if (Cfg.Diagnostics.SuppressAll ||
-        isDiagnosticSuppressed(Info, Cfg.Diagnostics.Suppress,
-                               CI.getLangOpts()))
-      return DiagnosticsEngine::Ignored;
     switch (Info.getID()) {
     case diag::warn_no_newline_eof:
       // If the preamble doesn't span the whole file, drop the no newline at
diff --git a/clang-tools-extra/clangd/unittests/CompilerTests.cpp 
b/clang-tools-extra/clangd/unittests/CompilerTests.cpp
index ab9e85e983d1c..9c8ad8d70b47b 100644
--- a/clang-tools-extra/clangd/unittests/CompilerTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CompilerTests.cpp
@@ -7,6 +7,8 @@
 
//===----------------------------------------------------------------------===//
 
 #include "Compiler.h"
+#include "Config.h"
+#include "Diagnostics.h"
 #include "TestTU.h"
 #include "clang/Frontend/DependencyOutputOptions.h"
 #include "clang/Frontend/FrontendOptions.h"
@@ -113,6 +115,19 @@ TEST(BuildCompilerInvocation, EmptyArgs) {
   // No crash.
   EXPECT_EQ(buildCompilerInvocation(Inputs, Diags), nullptr);
 }
+TEST(BuildCompilerInvocation, SuppressDiags) {
+  MockFS FS;
+  StoreDiags Diags;
+  TestTU TU;
+  TU.ExtraArgs = {"-funknown-arg"};
+  auto Inputs = TU.inputs(FS);
+
+  Config Cfg;
+  Cfg.Diagnostics.Suppress = {"drv_unknown_argument"};
+  WithContextValue SuppressFilterWithCfg(Config::Key, std::move(Cfg));
+  EXPECT_NE(buildCompilerInvocation(Inputs, Diags), nullptr);
+  EXPECT_THAT(Diags.take(), IsEmpty());
+}
 } // namespace
 } // namespace clangd
 } // namespace clang
diff --git a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp 
b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
index 84ceddbd4fc4b..6fe48478e1175 100644
--- a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -2170,6 +2170,27 @@ TEST(DiagnosticsTest, UnusedInHeader) {
   EXPECT_THAT(TU.build().getDiagnostics(), IsEmpty());
 }
 
+TEST(DiagnosticsTest, DontSuppressSubcategories) {
+  Annotations Source(R"cpp(
+  /*error-ok*/
+    void bar(int x) {
+      switch(x) {
+      default:
+        break;
+        break;
+      }
+    })cpp");
+  TestTU TU;
+  TU.ExtraArgs.push_back("-Wunreachable-code-aggressive");
+  TU.Code = Source.code().str();
+  Config Cfg;
+  // This shouldn't suppress subcategory unreachable-break.
+  Cfg.Diagnostics.Suppress = {"unreachable-code"};
+  WithContextValue SuppressFilterWithCfg(Config::Key, std::move(Cfg));
+  EXPECT_THAT(TU.build().getDiagnostics(),
+              ElementsAre(diagName("-Wunreachable-code-break")));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to