[clang] [Clang] Fix assertion failure in SDiagsWriter when finish() is not called (PR #181712)

via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 17 22:21:42 PST 2026


https://github.com/zeyi2 updated https://github.com/llvm/llvm-project/pull/181712

>From 58ef46e8d18ae14aed22c59e227380b121bac1f4 Mon Sep 17 00:00:00 2001
From: mtx <mitchell.xu2 at gmail.com>
Date: Tue, 17 Feb 2026 02:04:52 +0800
Subject: [PATCH 1/4] [Clang] Fix assertion failure in SDiagsWriter when
 finish() is not called

---
 clang/docs/ReleaseNotes.rst                        | 1 +
 clang/lib/Frontend/SerializedDiagnosticPrinter.cpp | 5 ++++-
 clang/test/Tooling/serialize-diagnostics.cpp       | 6 ++++++
 3 files changed, 11 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/Tooling/serialize-diagnostics.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 6063c3fbf48c8..01da9a3104e2f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -265,6 +265,7 @@ Bug Fixes in This Version
 - Clang now outputs relative paths of embeds for dependency output. (#GH161950)
 - Fixed an assertion failure when evaluating ``_Countof`` on invalid ``void``-typed operands. (#GH180893)
 - Fixed a ``-Winvalid-noreturn`` false positive for unreachable ``try`` blocks following an unconditional ``throw``. (#GH174822)
+- Fixed an assertion failure in the serialized diagnostic printer when it is destroyed without calling ``finish()``. (#GH140433)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp b/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
index 1dffe7cb2b9f0..fe2dca090b09e 100644
--- a/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ b/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -146,7 +146,10 @@ class SDiagsWriter : public DiagnosticConsumer {
     EmitPreamble();
   }
 
-  ~SDiagsWriter() override {}
+  ~SDiagsWriter() override {
+    if (OriginalInstance && !IsFinishing)
+      finish();
+  }
 
   void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                         const Diagnostic &Info) override;
diff --git a/clang/test/Tooling/serialize-diagnostics.cpp b/clang/test/Tooling/serialize-diagnostics.cpp
new file mode 100644
index 0000000000000..fbf5554fc90a2
--- /dev/null
+++ b/clang/test/Tooling/serialize-diagnostics.cpp
@@ -0,0 +1,6 @@
+// RUN: clang-check %s -- -Wunknown-warning-option --serialize-diagnostics %t.dia 2>&1 | FileCheck %s --allow-empty
+// RUN: ls %t.dia
+
+int main() {
+  return 0;
+}

>From 820bf60c666e2e0c08dd75e3f55b7fa08144680b Mon Sep 17 00:00:00 2001
From: mtx <mitchell.xu2 at gmail.com>
Date: Tue, 17 Feb 2026 02:22:28 +0800
Subject: [PATCH 2/4] fixup the testcases...

---
 clang/test/Tooling/serialize-diagnostics.cpp | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/clang/test/Tooling/serialize-diagnostics.cpp b/clang/test/Tooling/serialize-diagnostics.cpp
index fbf5554fc90a2..7b2a6e3c2fdd5 100644
--- a/clang/test/Tooling/serialize-diagnostics.cpp
+++ b/clang/test/Tooling/serialize-diagnostics.cpp
@@ -1,6 +1,10 @@
-// RUN: clang-check %s -- -Wunknown-warning-option --serialize-diagnostics %t.dia 2>&1 | FileCheck %s --allow-empty
+// RUN: clang-check %s -- -Wdoes-not-exist --serialize-diagnostics %t.dia 2>&1 | FileCheck %s
 // RUN: ls %t.dia
 
+// CHECK: warning: unknown warning option '-Wdoes-not-exist'
+// CHECK-NOT: Assertion failed
+// CHECK-NOT: Stack dump
+
 int main() {
   return 0;
 }

>From 780d426e467153517cbc5783763b0462fc72ebe1 Mon Sep 17 00:00:00 2001
From: mtx <mitchell.xu2 at gmail.com>
Date: Tue, 17 Feb 2026 22:15:23 +0800
Subject: [PATCH 3/4] Cleanup unnecessary CHECK-NOT

---
 clang/test/Tooling/serialize-diagnostics.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/clang/test/Tooling/serialize-diagnostics.cpp b/clang/test/Tooling/serialize-diagnostics.cpp
index 7b2a6e3c2fdd5..204c35113bcaa 100644
--- a/clang/test/Tooling/serialize-diagnostics.cpp
+++ b/clang/test/Tooling/serialize-diagnostics.cpp
@@ -2,8 +2,6 @@
 // RUN: ls %t.dia
 
 // CHECK: warning: unknown warning option '-Wdoes-not-exist'
-// CHECK-NOT: Assertion failed
-// CHECK-NOT: Stack dump
 
 int main() {
   return 0;

>From 17b8413fc56f22bae7ed8564cc72fca19289a0ab Mon Sep 17 00:00:00 2001
From: mtx <mitchell.xu2 at gmail.com>
Date: Wed, 18 Feb 2026 14:21:21 +0800
Subject: [PATCH 4/4] better?

---
 .../Frontend/SerializedDiagnosticPrinter.cpp  |  5 +---
 clang/lib/Tooling/Tooling.cpp                 | 25 +++++++++++++------
 clang/test/Tooling/serialize-diagnostics.cpp  |  3 +--
 3 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp b/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
index fe2dca090b09e..1dffe7cb2b9f0 100644
--- a/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ b/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -146,10 +146,7 @@ class SDiagsWriter : public DiagnosticConsumer {
     EmitPreamble();
   }
 
-  ~SDiagsWriter() override {
-    if (OriginalInstance && !IsFinishing)
-      finish();
-  }
+  ~SDiagsWriter() override {}
 
   void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                         const Diagnostic &Info) override;
diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp
index 9830096c2d0b9..1e9c21bef3d34 100644
--- a/clang/lib/Tooling/Tooling.cpp
+++ b/clang/lib/Tooling/Tooling.cpp
@@ -397,10 +397,14 @@ bool ToolInvocation::run() {
     ArrayRef<const char *> CC1Args = ArrayRef(Argv).drop_front();
     std::unique_ptr<CompilerInvocation> Invocation(
         newInvocation(&*Diagnostics, CC1Args, BinaryName));
-    if (Diagnostics->hasErrorOccurred())
+    if (Diagnostics->hasErrorOccurred()) {
+      Diagnostics->getClient()->finish();
       return false;
-    return Action->runInvocation(std::move(Invocation), Files,
-                                 std::move(PCHContainerOps), DiagConsumer);
+    }
+    const bool Success = Action->runInvocation(
+        std::move(Invocation), Files, std::move(PCHContainerOps), DiagConsumer);
+    Diagnostics->getClient()->finish();
+    return Success;
   }
 
   const std::unique_ptr<driver::Driver> Driver(
@@ -413,16 +417,23 @@ bool ToolInvocation::run() {
     Driver->setCheckInputsExist(false);
   const std::unique_ptr<driver::Compilation> Compilation(
       Driver->BuildCompilation(llvm::ArrayRef(Argv)));
-  if (!Compilation)
+  if (!Compilation) {
+    Diagnostics->getClient()->finish();
     return false;
+  }
   const llvm::opt::ArgStringList *const CC1Args =
       getCC1Arguments(&*Diagnostics, Compilation.get());
-  if (!CC1Args)
+  if (!CC1Args) {
+    Diagnostics->getClient()->finish();
     return false;
+  }
   std::unique_ptr<CompilerInvocation> Invocation(
       newInvocation(&*Diagnostics, *CC1Args, BinaryName));
-  return runInvocation(BinaryName, Compilation.get(), std::move(Invocation),
-                       std::move(PCHContainerOps));
+  const bool Success =
+      runInvocation(BinaryName, Compilation.get(), std::move(Invocation),
+                    std::move(PCHContainerOps));
+  Diagnostics->getClient()->finish();
+  return Success;
 }
 
 bool ToolInvocation::runInvocation(
diff --git a/clang/test/Tooling/serialize-diagnostics.cpp b/clang/test/Tooling/serialize-diagnostics.cpp
index 204c35113bcaa..85b364489e811 100644
--- a/clang/test/Tooling/serialize-diagnostics.cpp
+++ b/clang/test/Tooling/serialize-diagnostics.cpp
@@ -1,5 +1,4 @@
-// RUN: clang-check %s -- -Wdoes-not-exist --serialize-diagnostics %t.dia 2>&1 | FileCheck %s
-// RUN: ls %t.dia
+// RUN: clang-check %s -- -Wdoes-not-exist --serialize-diagnostics /dev/null 2>&1 | FileCheck %s
 
 // CHECK: warning: unknown warning option '-Wdoes-not-exist'
 



More information about the cfe-commits mailing list