diff --git a/include/clang/Frontend/DiagnosticRenderer.h b/include/clang/Frontend/DiagnosticRenderer.h index fc9131b4bd..5ad88a8a53 100644 --- a/include/clang/Frontend/DiagnosticRenderer.h +++ b/include/clang/Frontend/DiagnosticRenderer.h @@ -19,12 +19,17 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/PointerUnion.h" namespace clang { - class DiagnosticOptions; - class LangOptions; - class SourceManager; +class DiagnosticOptions; +class LangOptions; +class SourceManager; + +typedef llvm::PointerUnion DiagOrStoredDiag; + /// \brief Class to encapsulate the logic for formatting a diagnostic message. /// Actual "printing" logic is implemented by subclasses. /// @@ -71,7 +76,7 @@ protected: DiagnosticsEngine::Level Level, StringRef Message, ArrayRef Ranges, - const Diagnostic *Info) = 0; + DiagOrStoredDiag Info) = 0; virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, @@ -86,9 +91,9 @@ protected: virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc) = 0; - virtual void beginDiagnostic(const Diagnostic *Info, + virtual void beginDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level) {} - virtual void endDiagnostic(const Diagnostic *Info, + virtual void endDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level) {} @@ -117,7 +122,28 @@ public: void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef Ranges, ArrayRef FixItHints, - const Diagnostic *Info = 0); + DiagOrStoredDiag D = (Diagnostic *)0); + + void emitStoredDiagnostic(StoredDiagnostic &Diag); +}; + +/// Subclass of DiagnosticRender that turns all subdiagostics into explicit +/// notes. It is up to subclasses to further define the behavior. +class DiagnosticNoteRenderer : public DiagnosticRenderer { +public: + DiagnosticNoteRenderer(const SourceManager &SM, + const LangOptions &LangOpts, + const DiagnosticOptions &DiagOpts) + : DiagnosticRenderer(SM, LangOpts, DiagOpts) {} + + virtual ~DiagnosticNoteRenderer(); + + virtual void emitBasicNote(StringRef Message); + + virtual void emitIncludeLocation(SourceLocation Loc, + PresumedLoc PLoc); + + virtual void emitNote(SourceLocation Loc, StringRef Message) = 0; }; } // end clang namespace #endif diff --git a/include/clang/Frontend/TextDiagnostic.h b/include/clang/Frontend/TextDiagnostic.h index 4c71752c6f..519d3b61ce 100644 --- a/include/clang/Frontend/TextDiagnostic.h +++ b/include/clang/Frontend/TextDiagnostic.h @@ -81,7 +81,7 @@ protected: DiagnosticsEngine::Level Level, StringRef Message, ArrayRef Ranges, - const Diagnostic *Info); + DiagOrStoredDiag D); virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp index 548a4a833c..29f9ed5a7d 100644 --- a/lib/Frontend/DiagnosticRenderer.cpp +++ b/lib/Frontend/DiagnosticRenderer.cpp @@ -133,9 +133,9 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, StringRef Message, ArrayRef Ranges, ArrayRef FixItHints, - const Diagnostic *Info) { + DiagOrStoredDiag D) { - beginDiagnostic(Info, Level); + beginDiagnostic(D, Level); PresumedLoc PLoc = getDiagnosticPresumedLoc(SM, Loc); @@ -144,7 +144,7 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, emitIncludeStack(PLoc.getIncludeLoc(), Level); // Next, emit the actual diagnostic message. - emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, Info); + emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, D); // Only recurse if we have a valid location. if (Loc.isValid()) { @@ -166,7 +166,14 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, LastLoc = Loc; LastLevel = Level; - endDiagnostic(Info, Level); + endDiagnostic(D, Level); +} + + +void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) { + emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(), + Diag.getRanges(), Diag.getFixIts(), + &Diag); } /// \brief Prints an include stack when appropriate for a particular @@ -304,3 +311,19 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets( Ranges, ArrayRef()); } +DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {} + +void DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc, + PresumedLoc PLoc) { + // Generate a note indicating the include location. + SmallString<200> MessageStorage; + llvm::raw_svector_ostream Message(MessageStorage); + Message << "in file included from " << PLoc.getFilename() << ':' + << PLoc.getLine() << ":"; + emitNote(Loc, Message.str()); +} + +void DiagnosticNoteRenderer::emitBasicNote(StringRef Message) { + emitNote(SourceLocation(), Message); +} + diff --git a/lib/Frontend/SerializedDiagnosticPrinter.cpp b/lib/Frontend/SerializedDiagnosticPrinter.cpp index 649f294bf8..7a8edf7f5c 100644 --- a/lib/Frontend/SerializedDiagnosticPrinter.cpp +++ b/lib/Frontend/SerializedDiagnosticPrinter.cpp @@ -48,7 +48,7 @@ typedef llvm::SmallVectorImpl RecordDataImpl; class SDiagsWriter; -class SDiagsRenderer : public DiagnosticRenderer { +class SDiagsRenderer : public DiagnosticNoteRenderer { SDiagsWriter &Writer; RecordData &Record; public: @@ -56,7 +56,7 @@ public: const SourceManager &SM, const LangOptions &LangOpts, const DiagnosticOptions &DiagOpts) - : DiagnosticRenderer(SM, LangOpts, DiagOpts), + : DiagnosticNoteRenderer(SM, LangOpts, DiagOpts), Writer(Writer), Record(Record){} virtual ~SDiagsRenderer() {} @@ -67,27 +67,22 @@ protected: DiagnosticsEngine::Level Level, StringRef Message, ArrayRef Ranges, - const Diagnostic *Info); + DiagOrStoredDiag D); virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, ArrayRef Ranges) {} - virtual void emitBasicNote(StringRef Message); - void emitNote(SourceLocation Loc, StringRef Message); - virtual void emitIncludeLocation(SourceLocation Loc, - PresumedLoc PLoc); - virtual void emitCodeContext(SourceLocation Loc, DiagnosticsEngine::Level Level, SmallVectorImpl& Ranges, ArrayRef Hints); - virtual void beginDiagnostic(const Diagnostic *Info, + virtual void beginDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level); - virtual void endDiagnostic(const Diagnostic *Info, + virtual void endDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level); }; @@ -505,14 +500,14 @@ SDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef Ranges, - const Diagnostic *Info) { + DiagOrStoredDiag D) { // Emit the RECORD_DIAG record. Writer.Record.clear(); Writer.Record.push_back(RECORD_DIAG); Writer.Record.push_back(Level); Writer.AddLocToRecord(Loc, SM, PLoc, Record); - if (Info) { + if (const Diagnostic *Info = D.dyn_cast()) { // Emit the category string lazily and get the category ID. unsigned DiagID = DiagnosticIDs::getCategoryNumberForDiag(Info->getID()); Writer.Record.push_back(Writer.getEmitCategory(DiagID)); @@ -529,14 +524,14 @@ SDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc, Writer.Record, Message); } -void SDiagsRenderer::beginDiagnostic(const Diagnostic *Info, +void SDiagsRenderer::beginDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level) { Writer.Stream.EnterSubblock(BLOCK_DIAG, 4); } -void SDiagsRenderer::endDiagnostic(const Diagnostic *Info, +void SDiagsRenderer::endDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level) { - if (Info && Level != DiagnosticsEngine::Note) + if (D && Level != DiagnosticsEngine::Note) return; Writer.Stream.ExitBlock(); } @@ -581,20 +576,6 @@ void SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message) { Writer.Stream.ExitBlock(); } -void SDiagsRenderer::emitIncludeLocation(SourceLocation Loc, - PresumedLoc PLoc) { - // Generate a note indicating the include location. - SmallString<200> MessageStorage; - llvm::raw_svector_ostream Message(MessageStorage); - Message << "in file included from " << PLoc.getFilename() << ':' - << PLoc.getLine() << ":"; - emitNote(Loc, Message.str()); -} - -void SDiagsRenderer::emitBasicNote(StringRef Message) { - emitNote(SourceLocation(), Message); -} - void SDiagsWriter::finish() { if (inNonNoteDiagnostic) { // Finish off any diagnostics we were in the process of emitting. diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp index 5b8fd5675d..9f5dcb4838 100644 --- a/lib/Frontend/TextDiagnostic.cpp +++ b/lib/Frontend/TextDiagnostic.cpp @@ -339,7 +339,7 @@ TextDiagnostic::emitDiagnosticMessage(SourceLocation Loc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef Ranges, - const Diagnostic *Info) { + DiagOrStoredDiag D) { uint64_t StartOfLocationInfo = OS.tell(); // Emit the location of this particular diagnostic.