#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<const Diagnostic *,
+ const StoredDiagnostic *> DiagOrStoredDiag;
+
/// \brief Class to encapsulate the logic for formatting a diagnostic message.
/// Actual "printing" logic is implemented by subclasses.
///
DiagnosticsEngine::Level Level,
StringRef Message,
ArrayRef<CharSourceRange> Ranges,
- const Diagnostic *Info) = 0;
+ DiagOrStoredDiag Info) = 0;
virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level,
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) {}
void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level,
StringRef Message, ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> 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
DiagnosticsEngine::Level Level,
StringRef Message,
ArrayRef<CharSourceRange> Ranges,
- const Diagnostic *Info);
+ DiagOrStoredDiag D);
virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level,
StringRef Message,
ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> FixItHints,
- const Diagnostic *Info) {
+ DiagOrStoredDiag D) {
- beginDiagnostic(Info, Level);
+ beginDiagnostic(D, Level);
PresumedLoc PLoc = getDiagnosticPresumedLoc(SM, 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()) {
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
Ranges, ArrayRef<FixItHint>());
}
+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);
+}
+
class SDiagsWriter;
-class SDiagsRenderer : public DiagnosticRenderer {
+class SDiagsRenderer : public DiagnosticNoteRenderer {
SDiagsWriter &Writer;
RecordData &Record;
public:
const SourceManager &SM,
const LangOptions &LangOpts,
const DiagnosticOptions &DiagOpts)
- : DiagnosticRenderer(SM, LangOpts, DiagOpts),
+ : DiagnosticNoteRenderer(SM, LangOpts, DiagOpts),
Writer(Writer), Record(Record){}
virtual ~SDiagsRenderer() {}
DiagnosticsEngine::Level Level,
StringRef Message,
ArrayRef<CharSourceRange> Ranges,
- const Diagnostic *Info);
+ DiagOrStoredDiag D);
virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level,
ArrayRef<CharSourceRange> 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<CharSourceRange>& Ranges,
ArrayRef<FixItHint> 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);
};
DiagnosticsEngine::Level Level,
StringRef Message,
ArrayRef<clang::CharSourceRange> 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<const Diagnostic*>()) {
// Emit the category string lazily and get the category ID.
unsigned DiagID = DiagnosticIDs::getCategoryNumberForDiag(Info->getID());
Writer.Record.push_back(Writer.getEmitCategory(DiagID));
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();
}
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.
DiagnosticsEngine::Level Level,
StringRef Message,
ArrayRef<clang::CharSourceRange> Ranges,
- const Diagnostic *Info) {
+ DiagOrStoredDiag D) {
uint64_t StartOfLocationInfo = OS.tell();
// Emit the location of this particular diagnostic.