From 01af97d3b23bded2b2b21af19bbc6e4cce49e5b3 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Mon, 2 May 2011 19:39:53 +0000 Subject: Vendor import of clang trunk r130700: http://llvm.org/svn/llvm-project/cfe/trunk@130700 --- lib/Frontend/LogDiagnosticPrinter.cpp | 146 ++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 lib/Frontend/LogDiagnosticPrinter.cpp (limited to 'lib/Frontend/LogDiagnosticPrinter.cpp') diff --git a/lib/Frontend/LogDiagnosticPrinter.cpp b/lib/Frontend/LogDiagnosticPrinter.cpp new file mode 100644 index 000000000000..954bad4e7c54 --- /dev/null +++ b/lib/Frontend/LogDiagnosticPrinter.cpp @@ -0,0 +1,146 @@ +//===--- LogDiagnosticPrinter.cpp - Log Diagnostic Printer ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#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; + +LogDiagnosticPrinter::LogDiagnosticPrinter(llvm::raw_ostream &os, + const DiagnosticOptions &diags, + bool _OwnsOutputStream) + : OS(os), LangOpts(0), DiagOpts(&diags), + OwnsOutputStream(_OwnsOutputStream) { +} + +LogDiagnosticPrinter::~LogDiagnosticPrinter() { + if (OwnsOutputStream) + delete &OS; +} + +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 << "\n"; + if (!MainFilename.empty()) { + OS << " main-file\n" + << " " << MainFilename << "\n"; + } + if (!DwarfDebugFlags.empty()) { + OS << " dwarf-debug-flags\n" + << " " << DwarfDebugFlags << "\n"; + } + OS << " diagnostics\n"; + OS << " \n"; + for (unsigned i = 0, e = Entries.size(); i != e; ++i) { + DiagEntry &DE = Entries[i]; + + OS << " \n"; + OS << " level\n" + << " " << getLevelName(DE.DiagnosticLevel) << "\n"; + if (!DE.Filename.empty()) { + OS << " filename\n" + << " " << DE.Filename << "\n"; + } + if (DE.Line != 0) { + OS << " line\n" + << " " << DE.Line << "\n"; + } + if (DE.Column != 0) { + OS << " column\n" + << " " << DE.Column << "\n"; + } + if (!DE.Message.empty()) { + OS << " message\n" + << " " << DE.Message << "\n"; + } + OS << " \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); + + // Initialize the main file name, if we haven't already fetched it. + if (MainFilename.empty()) { + const SourceManager &SM = Info.getSourceManager(); + FileID FID = SM.getMainFileID(); + if (!FID.isInvalid()) { + const FileEntry *FE = SM.getFileEntryForID(FID); + if (FE && FE->getName()) + MainFilename = FE->getName(); + } + } + + // 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); +} -- cgit v1.3