From 64bfbf573e625c04abc3d40faa9b695fe21ebdbb Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Thu, 7 Apr 2011 18:37:34 +0000 Subject: [PATCH] Frontend: Continue flushing out LogDiagnosticPrinter. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129091 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Frontend/LogDiagnosticPrinter.h | 27 +++++- lib/Frontend/LogDiagnosticPrinter.cpp | 86 +++++++++++++++++-- 2 files changed, 105 insertions(+), 8 deletions(-) diff --git a/include/clang/Frontend/LogDiagnosticPrinter.h b/include/clang/Frontend/LogDiagnosticPrinter.h index b79fc95eb3..8ac6093318 100644 --- a/include/clang/Frontend/LogDiagnosticPrinter.h +++ b/include/clang/Frontend/LogDiagnosticPrinter.h @@ -12,12 +12,33 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/SmallVector.h" namespace clang { class DiagnosticOptions; class LangOptions; class LogDiagnosticPrinter : public DiagnosticClient { + struct DiagEntry { + /// The primary message line of the diagnostic. + std::string Message; + + /// The source file name, if available. + std::string Filename; + + /// The source file line number, if available. + unsigned Line; + + /// The source file column number, if available. + unsigned Column; + + /// The ID of the diagnostic. + unsigned DiagnosticID; + + /// The level of the diagnostic. + Diagnostic::Level DiagnosticLevel; + }; + llvm::raw_ostream &OS; const LangOptions *LangOpts; const DiagnosticOptions *DiagOpts; @@ -26,6 +47,8 @@ class LogDiagnosticPrinter : public DiagnosticClient { FullSourceLoc LastLoc; unsigned OwnsOutputStream : 1; + llvm::SmallVector Entries; + public: LogDiagnosticPrinter(llvm::raw_ostream &OS, const DiagnosticOptions &Diags, bool OwnsOutputStream = false); @@ -35,9 +58,7 @@ public: LangOpts = &LO; } - void EndSourceFile() { - LangOpts = 0; - } + void EndSourceFile(); virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, const DiagnosticInfo &Info); diff --git a/lib/Frontend/LogDiagnosticPrinter.cpp b/lib/Frontend/LogDiagnosticPrinter.cpp index f148d5e6a2..ca661a6af7 100644 --- a/lib/Frontend/LogDiagnosticPrinter.cpp +++ b/lib/Frontend/LogDiagnosticPrinter.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/LogDiagnosticPrinter.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceManager.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -24,16 +26,90 @@ LogDiagnosticPrinter::~LogDiagnosticPrinter() { delete &OS; } -void LogDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, - const DiagnosticInfo &Info) { - // Default implementation (Warnings/errors count). - DiagnosticClient::HandleDiagnostic(Level, Info); +static llvm::StringRef getLevelName(Diagnostic::Level Level) { + switch (Level) { + default: + return ""; + case Diagnostic::Ignored: return "ignored"; + case Diagnostic::Note: return "note"; + case Diagnostic::Warning: return "warning"; + case Diagnostic::Error: return "error"; + case Diagnostic::Fatal: return "fatal error"; + } +} + +void LogDiagnosticPrinter::EndSourceFile() { + // We emit all the diagnostics in EndSourceFile. However, we don't emit any + // entry if no diagnostics were present. + // + // Note that DiagnosticClient has no "end-of-compilation" callback, so we will + // miss any diagnostics which are emitted after and outside the translation + // unit processing. + if (Entries.empty()) + return; // Write to a temporary string to ensure atomic write of diagnostic object. llvm::SmallString<512> Msg; llvm::raw_svector_ostream OS(Msg); - OS << "hello!\n"; + OS << "{\n"; + // FIXME: Output main translation unit file name. + // FIXME: Include the invocation, if dwarf-debug-flags is available. + OS << " \"diagnostics\" : [\n"; + for (unsigned i = 0, e = Entries.size(); i != e; ++i) { + DiagEntry &DE = Entries[i]; + + OS << " {\n"; + OS << " \"filename\" : \"" << DE.Filename << "\",\n"; + OS << " \"line\" : " << DE.Line << ",\n"; + OS << " \"column\" : " << DE.Column << ",\n"; + OS << " \"message\" : \"" << DE.Message << "\",\n"; + OS << " \"level\" : \"" << getLevelName(DE.DiagnosticLevel) << "\"\n"; + OS << " }" << ((i + 1 != e) ? "," : "") << '\n'; + } + OS << " ]\n"; + OS << "},\n"; this->OS << OS.str(); } + +void LogDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, + const DiagnosticInfo &Info) { + // Default implementation (Warnings/errors count). + DiagnosticClient::HandleDiagnostic(Level, Info); + + // Create the diag entry. + DiagEntry DE; + DE.DiagnosticID = Info.getID(); + DE.DiagnosticLevel = Level; + + // Format the message. + llvm::SmallString<100> MessageStr; + Info.FormatDiagnostic(MessageStr); + DE.Message = MessageStr.str(); + + // Set the location information. + DE.Filename = ""; + DE.Line = DE.Column = 0; + if (Info.getLocation().isValid()) { + const SourceManager &SM = Info.getSourceManager(); + PresumedLoc PLoc = SM.getPresumedLoc(Info.getLocation()); + + if (PLoc.isInvalid()) { + // At least print the file name if available: + FileID FID = SM.getFileID(Info.getLocation()); + if (!FID.isInvalid()) { + const FileEntry *FE = SM.getFileEntryForID(FID); + if (FE && FE->getName()) + DE.Filename = FE->getName(); + } + } else { + DE.Filename = PLoc.getFilename(); + DE.Line = PLoc.getLine(); + DE.Column = PLoc.getColumn(); + } + } + + // Record the diagnostic entry. + Entries.push_back(DE); +} -- 2.40.0