diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -119,6 +119,9 @@ def warn_fe_serialized_diag_failure : Warning< "unable to open file %0 for serializing diagnostics (%1)">, InGroup; +def warn_fe_serialized_diag_failure_during_finalisation : Warning< + "Received warning after diagnostic serialization teardown was underway: %0">, + InGroup; def err_verify_missing_line : Error< "missing or invalid line number following '@' in expected %0">; diff --git a/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp b/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp --- a/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp +++ b/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp @@ -239,6 +239,9 @@ /// generated from child processes. bool MergeChildRecords; + /// Whether we've started finishing and tearing down this instance. + bool IsFinishing = false; + /// State that is shared among the various clones of this diagnostic /// consumer. struct SharedState { @@ -568,6 +571,17 @@ void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) { + assert(!IsFinishing && + "Received a diagnostic after we've already started teardown."); + if (IsFinishing) { + SmallString<256> diagnostic; + Info.FormatDiagnostic(diagnostic); + getMetaDiags()->Report( + diag::warn_fe_serialized_diag_failure_during_finalisation) + << diagnostic; + return; + } + // Enter the block for a non-note diagnostic immediately, rather than waiting // for beginDiagnostic, in case associated notes are emitted before we get // there. @@ -761,6 +775,9 @@ } void SDiagsWriter::finish() { + assert(!IsFinishing); + IsFinishing = true; + // The original instance is responsible for writing the file. if (!OriginalInstance) return; @@ -786,12 +803,20 @@ if (EC) { getMetaDiags()->Report(diag::warn_fe_serialized_diag_failure) << State->OutputFile << EC.message(); + OS->clear_error(); return; } // Write the generated bitstream to "Out". OS->write((char *)&State->Buffer.front(), State->Buffer.size()); OS->flush(); + + assert(!OS->has_error()); + if (OS->has_error()) { + getMetaDiags()->Report(diag::warn_fe_serialized_diag_failure) + << State->OutputFile << OS->error().message(); + OS->clear_error(); + } } std::error_code SDiagsMerger::visitStartOfDiagnostic() {