Author: mitchell
Date: 2026-02-24T00:52:04+08:00
New Revision: 174aaacf97e2ebb0de1203b1a2a719a3d509b946

URL: 
https://github.com/llvm/llvm-project/commit/174aaacf97e2ebb0de1203b1a2a719a3d509b946
DIFF: 
https://github.com/llvm/llvm-project/commit/174aaacf97e2ebb0de1203b1a2a719a3d509b946.diff

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

When `--serialize-diagnostics` is used, `SDiagsWriter` enters bitstream
blocks during its initialization. They are expected to be exited in the
`finish()` method.

However in LibTooling based tools (like `clang-tidy` or `clang-check`),
if a user provides an invalid command-line argument, the driver detects
the error and prepares for an early exit. The exit path leads directly
to destruction, skipping the call to `finish()` that would normally
occur in the main logic. Then the assertion detects this block imbalance
and triggers a crash.

As of AI Usage: Gemini 3 was used to rephrase part of the PR description
Closes https://github.com/llvm/llvm-project/issues/140433

Added: 
    clang/test/Tooling/serialize-diagnostics.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Tooling/Tooling.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 34448fd9927b4..8f4762587f34a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -289,6 +289,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)
 - Fixed an assertion failure caused by error recovery while extending a nested 
name specifier with results from ordinary lookup. (#GH181470)
 
 Bug Fixes to Compiler Builtins

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
new file mode 100644
index 0000000000000..85b364489e811
--- /dev/null
+++ b/clang/test/Tooling/serialize-diagnostics.cpp
@@ -0,0 +1,7 @@
+// RUN: clang-check %s -- -Wdoes-not-exist --serialize-diagnostics /dev/null 
2>&1 | FileCheck %s
+
+// CHECK: warning: unknown warning option '-Wdoes-not-exist'
+
+int main() {
+  return 0;
+}


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

Reply via email to