Skip to content

Commit 10439ff

Browse files
committed
[clang] Apply internal buffering to clang diagnostics printing
To stabilize output of clang when clang is run in multiple build threads the whole diagnostic message is written first to internal buffer and then the whole message is put to the output stream which usually points to stderr to avoid printing to stderr with small chunks and interleaving of multiple diagnostic messages.
1 parent ac5a201 commit 10439ff

File tree

3 files changed

+31
-7
lines changed

3 files changed

+31
-7
lines changed

clang/include/clang/Frontend/TextDiagnostic.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define LLVM_CLANG_FRONTEND_TEXTDIAGNOSTIC_H
1717

1818
#include "clang/Frontend/DiagnosticRenderer.h"
19+
#include "llvm/ADT/SmallString.h"
1920
#include "llvm/Support/raw_ostream.h"
2021

2122
namespace clang {
@@ -33,8 +34,15 @@ namespace clang {
3334
/// DiagnosticClient is implemented through this class as is diagnostic
3435
/// printing coming out of libclang.
3536
class TextDiagnostic : public DiagnosticRenderer {
36-
raw_ostream &OS;
37+
raw_ostream &Out;
3738
const Preprocessor *PP;
39+
// To stabilize output of clang when clang is run in multiple build threads
40+
// the whole diagnostic message is written first to internal buffer and then
41+
// the whole message is put to the output stream Out which usually points to
42+
// stderr to avoid printing to stderr with small chunks and interleaving of
43+
// multiple diagnostic messages.
44+
SmallString<1024> InternalBuffer;
45+
llvm::raw_svector_ostream OS;
3846

3947
public:
4048
TextDiagnostic(raw_ostream &OS, const LangOptions &LangOpts,
@@ -104,6 +112,8 @@ class TextDiagnostic : public DiagnosticRenderer {
104112

105113
void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc,
106114
StringRef ModuleName) override;
115+
void endDiagnostic(DiagOrStoredDiag D,
116+
DiagnosticsEngine::Level Level) override;
107117

108118
private:
109119
void emitFilename(StringRef Filename, const SourceManager &SM);

clang/lib/Frontend/TextDiagnostic.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -656,15 +656,19 @@ static bool printWordWrapped(raw_ostream &OS, StringRef Str, unsigned Columns,
656656
TextDiagnostic::TextDiagnostic(raw_ostream &OS, const LangOptions &LangOpts,
657657
DiagnosticOptions *DiagOpts,
658658
const Preprocessor *PP)
659-
: DiagnosticRenderer(LangOpts, DiagOpts), OS(OS), PP(PP) {}
659+
: DiagnosticRenderer(LangOpts, DiagOpts), Out(OS), PP(PP),
660+
OS(InternalBuffer) {
661+
this->OS.buffer().clear();
662+
this->OS.enable_colors(true);
663+
}
660664

661665
TextDiagnostic::~TextDiagnostic() {}
662666

663667
void TextDiagnostic::emitDiagnosticMessage(
664668
FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level,
665669
StringRef Message, ArrayRef<clang::CharSourceRange> Ranges,
666670
DiagOrStoredDiag D) {
667-
uint64_t StartOfLocationInfo = OS.tell();
671+
uint64_t StartOfLocationInfo = Out.tell();
668672

669673
// Emit the location of this particular diagnostic.
670674
if (Loc.isValid())
@@ -677,7 +681,7 @@ void TextDiagnostic::emitDiagnosticMessage(
677681
printDiagnosticLevel(OS, Level, DiagOpts->ShowColors);
678682
printDiagnosticMessage(OS,
679683
/*IsSupplemental*/ Level == DiagnosticsEngine::Note,
680-
Message, OS.tell() - StartOfLocationInfo,
684+
Message, Out.tell() - StartOfLocationInfo,
681685
DiagOpts->MessageLength, DiagOpts->ShowColors);
682686
}
683687

@@ -1545,3 +1549,9 @@ void TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints,
15451549
OS << "\"\n";
15461550
}
15471551
}
1552+
1553+
void TextDiagnostic::endDiagnostic(DiagOrStoredDiag D,
1554+
DiagnosticsEngine::Level Level) {
1555+
Out << OS.str();
1556+
OS.buffer().clear();
1557+
}

clang/lib/Frontend/TextDiagnosticPrinter.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,16 @@ void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
133133
// diagnostics in a context that lacks language options, a source manager, or
134134
// other infrastructure necessary when emitting more rich diagnostics.
135135
if (!Info.getLocation().isValid()) {
136-
TextDiagnostic::printDiagnosticLevel(OS, Level, DiagOpts->ShowColors);
136+
SmallString<1000> OutText;
137+
llvm::raw_svector_ostream OutputBuffer(OutText);
138+
OutputBuffer.enable_colors(true);
139+
TextDiagnostic::printDiagnosticLevel(OutputBuffer, Level,
140+
DiagOpts->ShowColors);
137141
TextDiagnostic::printDiagnosticMessage(
138-
OS, /*IsSupplemental=*/Level == DiagnosticsEngine::Note,
142+
OutputBuffer, /*IsSupplemental=*/Level == DiagnosticsEngine::Note,
139143
DiagMessageStream.str(), OS.tell() - StartOfLocationInfo,
140144
DiagOpts->MessageLength, DiagOpts->ShowColors);
141-
OS.flush();
145+
OS << OutputBuffer.str();
142146
return;
143147
}
144148

0 commit comments

Comments
 (0)