Switch the emission of diagnostics without a source location to

a dedicated path. The logic for such diagnostics is much simpler than
for others.

This begins to make an important separation in this routine. We expect
most (and most interesting) textual diagnostics to be made in the
presence of at least *some* source locations and a source manager.
However the DiagnosticConsumer must be prepared to diagnose errors even
when the source manager doesn't (yet) exist or when there is no location
information at all. In order to sink more and more logic into the
TextDiagnostic class while minimizing its complexity, my plan is to
force the DiagnosticConsumer to special case diagnosing any locationless
messages and then hand the rest to the TextDiagnostic class. I'd
appreciate any comments on this design. It requires a bit of code
duplication in order to keep interfaces simple. Alternatively, if we
really need TextDiagnostic to be capable of handling diagnostics even in
the absence of a viable SourceManager, then this split isn't necessary.

llvm-svn: 140525
This commit is contained in:
Chandler Carruth 2011-09-26 11:25:30 +00:00
parent c0fe585e0c
commit 2be992d570
1 changed files with 34 additions and 24 deletions

View File

@ -1168,6 +1168,17 @@ void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
// Default implementation (Warnings/errors count).
DiagnosticConsumer::HandleDiagnostic(Level, Info);
// Render the diagnostic message into a temporary buffer eagerly. We'll use
// this later as we print out the diagnostic to the terminal.
llvm::SmallString<100> OutStr;
Info.FormatDiagnostic(OutStr);
llvm::raw_svector_ostream DiagMessageStream(OutStr);
if (DiagOpts->ShowNames)
printDiagnosticName(DiagMessageStream, Info);
printDiagnosticOptions(DiagMessageStream, Level, Info, *DiagOpts);
// Keeps track of the the starting position of the location
// information (e.g., "foo.c:10:4:") that precedes the error
// message. We use this information to determine how long the
@ -1177,7 +1188,16 @@ void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
if (!Prefix.empty())
OS << Prefix << ": ";
if (Info.getLocation().isValid()) {
// Use a dedicated, simpler path for diagnostics without a valid location.
if (!Info.getLocation().isValid()) {
printDiagnosticLevel(OS, Level, DiagOpts->ShowColors);
printDiagnosticMessage(OS, Level, DiagMessageStream.str(),
OS.tell() - StartOfLocationInfo,
DiagOpts->MessageLength, DiagOpts->ShowColors);
OS.flush();
return;
}
const SourceManager &SM = Info.getSourceManager();
PresumedLoc PLoc = getDiagnosticPresumedLoc(SM, Info.getLocation());
@ -1191,18 +1211,8 @@ void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
if (DiagOpts->ShowColors)
OS.resetColor();
}
printDiagnosticLevel(OS, Level, DiagOpts->ShowColors);
llvm::SmallString<100> OutStr;
Info.FormatDiagnostic(OutStr);
llvm::raw_svector_ostream DiagMessageStream(OutStr);
if (DiagOpts->ShowNames)
printDiagnosticName(DiagMessageStream, Info);
printDiagnosticOptions(DiagMessageStream, Level, Info, *DiagOpts);
printDiagnosticMessage(OS, Level, DiagMessageStream.str(),
OS.tell() - StartOfLocationInfo,
DiagOpts->MessageLength, DiagOpts->ShowColors);
@ -1213,7 +1223,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
// was part of a different warning or error diagnostic, or if the
// diagnostic has ranges. We don't want to emit the same caret
// multiple times if one loc has multiple diagnostics.
if (DiagOpts->ShowCarets && Info.getLocation().isValid() &&
if (DiagOpts->ShowCarets &&
((LastLoc != Info.getLocation()) || Info.getNumRanges() ||
(LastCaretDiagnosticWasNote && Level != DiagnosticsEngine::Note) ||
Info.getNumFixItHints())) {