Skip to content

Commit 94a78de

Browse files
committed
[clang] Make serialized diagnostics more reliable
`SDiagsWriter` currently requires clients to call `DiagnosticConsumer::finish()` before it is destroyed if `CompilerInstance::ExecuteAction()` has not been called. The problem with this is that it makes it much harder for clients to properly call `finish()` for cases such as errors from running the driver, or clients that want to emit diagnostics after executing an action, as they need to be careful to not call it twice. This patch removes the call in `CompilerInstance::ExecuteAction()`, and instead adds a call to finish in `SDiagsWriter`'s destructor if it was not already called, but leaves the explicit calls that occur when DisableFree is set, as that skips most destructors. No test because the issues this caused were in not yet upstreamed code.
1 parent 25f9415 commit 94a78de

File tree

3 files changed

+14
-10
lines changed

3 files changed

+14
-10
lines changed

clang/include/clang/Basic/Diagnostic.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,8 +1776,12 @@ class DiagnosticConsumer {
17761776
/// BeginSourceFile() are inaccessible.
17771777
virtual void EndSourceFile() {}
17781778

1779-
/// Callback to inform the diagnostic client that processing of all
1780-
/// source files has ended.
1779+
/// Callback to inform the diagnostic client that processing of all source
1780+
/// files has ended, and that no more diagnostics will be emitted.
1781+
///
1782+
/// This is only called when the DiagnosticConsumer's destructor would not
1783+
/// otherwise be called. Subclasses that require this to be called must ensure
1784+
/// that in their destructor.
17811785
virtual void finish() {}
17821786

17831787
/// Indicates whether the diagnostics handled by this

clang/lib/Frontend/CompilerInstance.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,12 +1016,6 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
10161016
// better. We generally expect frontend actions to be invoked with (nearly)
10171017
// DesiredStackSpace available.
10181018
noteBottomOfStack();
1019-
1020-
auto FinishDiagnosticClient = llvm::make_scope_exit([&]() {
1021-
// Notify the diagnostic client that all files were processed.
1022-
getDiagnosticClient().finish();
1023-
});
1024-
10251019
raw_ostream &OS = getVerboseOutputStream();
10261020

10271021
if (!Act.PrepareToExecute(*this))

clang/lib/Frontend/SerializedDiagnosticPrinter.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class SDiagsMerger : SerializedDiagnosticReader {
129129
void writeRecordWithBlob(unsigned ID, RecordData &Record, StringRef Blob);
130130
};
131131

132-
class SDiagsWriter : public DiagnosticConsumer {
132+
class SDiagsWriter final : public DiagnosticConsumer {
133133
friend class SDiagsRenderer;
134134
friend class SDiagsMerger;
135135

@@ -149,7 +149,13 @@ class SDiagsWriter : public DiagnosticConsumer {
149149
EmitPreamble();
150150
}
151151

152-
~SDiagsWriter() override {}
152+
~SDiagsWriter() override {
153+
// Not all uses of DiagnosticConsumer call finish, and not all uses invoke
154+
// the destructor. This makes calling finish optional for cases where it
155+
// is properly destructed.
156+
if (!IsFinishing)
157+
finish();
158+
}
153159

154160
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
155161
const Diagnostic &Info) override;

0 commit comments

Comments
 (0)