From: Daniel Dunbar Date: Thu, 7 Apr 2011 18:31:10 +0000 (+0000) Subject: Frontend: Sketch a LogDiagnosticPrinter object, and wire CC_LOG_DIAGNOSTICS to X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9df23493f5b8a223dfbc491e4b7de3850797c2e7;p=clang Frontend: Sketch a LogDiagnosticPrinter object, and wire CC_LOG_DIAGNOSTICS to it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129089 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Frontend/LogDiagnosticPrinter.h b/include/clang/Frontend/LogDiagnosticPrinter.h new file mode 100644 index 0000000000..b79fc95eb3 --- /dev/null +++ b/include/clang/Frontend/LogDiagnosticPrinter.h @@ -0,0 +1,48 @@ +//===--- LogDiagnosticPrinter.h - Log Diagnostic Client ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_LOG_DIAGNOSTIC_PRINTER_H_ +#define LLVM_CLANG_FRONTEND_LOG_DIAGNOSTIC_PRINTER_H_ + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" + +namespace clang { +class DiagnosticOptions; +class LangOptions; + +class LogDiagnosticPrinter : public DiagnosticClient { + llvm::raw_ostream &OS; + const LangOptions *LangOpts; + const DiagnosticOptions *DiagOpts; + + SourceLocation LastWarningLoc; + FullSourceLoc LastLoc; + unsigned OwnsOutputStream : 1; + +public: + LogDiagnosticPrinter(llvm::raw_ostream &OS, const DiagnosticOptions &Diags, + bool OwnsOutputStream = false); + virtual ~LogDiagnosticPrinter(); + + void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) { + LangOpts = &LO; + } + + void EndSourceFile() { + LangOpts = 0; + } + + virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, + const DiagnosticInfo &Info); +}; + +} // end namespace clang + +#endif diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt index 68ce61445d..9d49e9039d 100644 --- a/lib/Frontend/CMakeLists.txt +++ b/lib/Frontend/CMakeLists.txt @@ -26,6 +26,7 @@ add_clang_library(clangFrontend InitHeaderSearch.cpp InitPreprocessor.cpp LangStandards.cpp + LogDiagnosticPrinter.cpp MultiplexConsumer.cpp PrintPreprocessedOutput.cpp TextDiagnosticBuffer.cpp diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index bbdfcaf57e..94271d3b32 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -22,6 +22,7 @@ #include "clang/Frontend/ChainedDiagnosticClient.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/LogDiagnosticPrinter.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Frontend/VerifyDiagnosticsClient.h" #include "clang/Frontend/Utils.h" @@ -106,6 +107,33 @@ static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts, Diags.setClient(new ChainedDiagnosticClient(Diags.takeClient(), Logger)); } +static void SetUpDiagnosticLog(const DiagnosticOptions &DiagOpts, + Diagnostic &Diags) { + std::string ErrorInfo; + bool OwnsStream = false; + llvm::raw_ostream *OS = &llvm::errs(); + if (DiagOpts.DiagnosticLogFile != "-") { + // Create the output stream. + llvm::raw_fd_ostream *FileOS( + new llvm::raw_fd_ostream(DiagOpts.DiagnosticLogFile.c_str(), + ErrorInfo)); + if (!ErrorInfo.empty()) { + Diags.Report(diag::warn_fe_cc_log_diagnostics_failure) + << DiagOpts.DumpBuildInformation << ErrorInfo; + } else { + FileOS->SetUnbuffered(); + FileOS->SetUseAtomicWrites(true); + OS = FileOS; + OwnsStream = true; + } + } + + // Chain in the diagnostic client which will log the diagnostics. + DiagnosticClient *Logger = new LogDiagnosticPrinter(*OS, DiagOpts, + OwnsStream); + Diags.setClient(new ChainedDiagnosticClient(Diags.takeClient(), Logger)); +} + void CompilerInstance::createDiagnostics(int Argc, const char* const *Argv, DiagnosticClient *Client) { Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv, Client); @@ -129,6 +157,10 @@ CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, if (Opts.VerifyDiagnostics) Diags->setClient(new VerifyDiagnosticsClient(*Diags, Diags->takeClient())); + // Chain in -diagnostic-log-file dumper, if requested. + if (!Opts.DiagnosticLogFile.empty()) + SetUpDiagnosticLog(Opts, *Diags); + if (!Opts.DumpBuildInformation.empty()) SetUpBuildDumpLog(Opts, Argc, Argv, *Diags); diff --git a/lib/Frontend/LogDiagnosticPrinter.cpp b/lib/Frontend/LogDiagnosticPrinter.cpp new file mode 100644 index 0000000000..f148d5e6a2 --- /dev/null +++ b/lib/Frontend/LogDiagnosticPrinter.cpp @@ -0,0 +1,39 @@ +//===--- 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 "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; +} + +void LogDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, + const DiagnosticInfo &Info) { + // Default implementation (Warnings/errors count). + DiagnosticClient::HandleDiagnostic(Level, Info); + + // 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"; + + this->OS << OS.str(); +}