Factor out a diagnostic options class.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86010 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Daniel Dunbar 2009-11-04 06:24:30 +00:00
Родитель 0360af5d61
Коммит eace874303
4 изменённых файлов: 107 добавлений и 78 удалений

Просмотреть файл

@ -0,0 +1,49 @@
//===--- DiagnosticOptions.h ------------------------------------*- 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_DIAGNOSTICOPTIONS_H
#define LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H
#include <string>
#include <vector>
namespace clang {
/// DiagnosticOptions - Options for controlling the compiler diagnostics
/// engine.
class DiagnosticOptions {
public:
unsigned ShowColumn : 1; /// Show column number on diagnostics.
unsigned ShowLocation : 1; /// Show source location information.
unsigned ShowCarets : 1; /// Show source location information.
unsigned ShowFixits : 1; /// Show fixit information.
unsigned ShowSourceRanges : 1; /// Show source ranges in numeric form.
unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable
/// diagnostics.
unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences.
/// Column limit for formatting message diagnostics, or 0 if unused.
unsigned MessageLength;
public:
DiagnosticOptions() {
ShowColumn = 1;
ShowLocation = 1;
ShowCarets = 1;
ShowFixits = 1;
ShowSourceRanges = 0;
ShowOptionNames = 0;
ShowColors = 0;
MessageLength = 0;
}
};
} // end namespace clang
#endif

Просмотреть файл

@ -23,42 +23,21 @@ namespace llvm {
} }
namespace clang { namespace clang {
class SourceManager; class DiagnosticOptions;
class LangOptions; class LangOptions;
class SourceManager;
class TextDiagnosticPrinter : public DiagnosticClient { class TextDiagnosticPrinter : public DiagnosticClient {
llvm::raw_ostream &OS; llvm::raw_ostream &OS;
const LangOptions *LangOpts; const LangOptions *LangOpts;
const DiagnosticOptions *DiagOpts;
SourceLocation LastWarningLoc; SourceLocation LastWarningLoc;
FullSourceLoc LastLoc; FullSourceLoc LastLoc;
bool LastCaretDiagnosticWasNote; bool LastCaretDiagnosticWasNote;
bool ShowColumn;
bool CaretDiagnostics;
bool ShowLocation;
bool PrintRangeInfo;
bool PrintDiagnosticOption;
bool PrintFixItInfo;
unsigned MessageLength;
bool UseColors;
public: public:
TextDiagnosticPrinter(llvm::raw_ostream &os, TextDiagnosticPrinter(llvm::raw_ostream &os, const DiagnosticOptions &diags);
bool showColumn = true,
bool caretDiagnistics = true, bool showLocation = true,
bool printRangeInfo = true,
bool printDiagnosticOption = true,
bool printFixItInfo = true,
unsigned messageLength = 0,
bool useColors = false)
: OS(os), LangOpts(0),
LastCaretDiagnosticWasNote(false), ShowColumn(showColumn),
CaretDiagnostics(caretDiagnistics), ShowLocation(showLocation),
PrintRangeInfo(printRangeInfo),
PrintDiagnosticOption(printDiagnosticOption),
PrintFixItInfo(printFixItInfo),
MessageLength(messageLength),
UseColors(useColors) {}
void setLangOptions(const LangOptions *LO) { void setLangOptions(const LangOptions *LO) {
LangOpts = LO; LangOpts = LO;

Просмотреть файл

@ -13,6 +13,7 @@
#include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManager.h"
#include "clang/Frontend/DiagnosticOptions.h"
#include "clang/Lex/Lexer.h" #include "clang/Lex/Lexer.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
@ -37,6 +38,12 @@ static const enum llvm::raw_ostream::Colors savedColor =
/// \brief Number of spaces to indent when word-wrapping. /// \brief Number of spaces to indent when word-wrapping.
const unsigned WordWrapIndentation = 6; const unsigned WordWrapIndentation = 6;
TextDiagnosticPrinter::TextDiagnosticPrinter(llvm::raw_ostream &os,
const DiagnosticOptions &diags)
: OS(os), LangOpts(0), DiagOpts(&diags),
LastCaretDiagnosticWasNote(false) {
}
void TextDiagnosticPrinter:: void TextDiagnosticPrinter::
PrintIncludeStack(SourceLocation Loc, const SourceManager &SM) { PrintIncludeStack(SourceLocation Loc, const SourceManager &SM) {
if (Loc.isInvalid()) return; if (Loc.isInvalid()) return;
@ -46,7 +53,7 @@ PrintIncludeStack(SourceLocation Loc, const SourceManager &SM) {
// Print out the other include frames first. // Print out the other include frames first.
PrintIncludeStack(PLoc.getIncludeLoc(), SM); PrintIncludeStack(PLoc.getIncludeLoc(), SM);
if (ShowLocation) if (DiagOpts->ShowLocation)
OS << "In file included from " << PLoc.getFilename() OS << "In file included from " << PLoc.getFilename()
<< ':' << PLoc.getLine() << ":\n"; << ':' << PLoc.getLine() << ":\n";
else else
@ -281,13 +288,13 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
Ranges[i] = SourceRange(S, E); Ranges[i] = SourceRange(S, E);
} }
if (ShowLocation) { if (DiagOpts->ShowLocation) {
std::pair<FileID, unsigned> IInfo = SM.getDecomposedInstantiationLoc(Loc); std::pair<FileID, unsigned> IInfo = SM.getDecomposedInstantiationLoc(Loc);
// Emit the file/line/column that this expansion came from. // Emit the file/line/column that this expansion came from.
OS << SM.getBuffer(IInfo.first)->getBufferIdentifier() << ':' OS << SM.getBuffer(IInfo.first)->getBufferIdentifier() << ':'
<< SM.getLineNumber(IInfo.first, IInfo.second) << ':'; << SM.getLineNumber(IInfo.first, IInfo.second) << ':';
if (ShowColumn) if (DiagOpts->ShowColumn)
OS << SM.getColumnNumber(IInfo.first, IInfo.second) << ':'; OS << SM.getColumnNumber(IInfo.first, IInfo.second) << ':';
OS << ' '; OS << ' ';
} }
@ -370,13 +377,13 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
// produce easily machine parsable output. Add a space before the source line // produce easily machine parsable output. Add a space before the source line
// and the caret to make it trivial to tell the main diagnostic line from what // and the caret to make it trivial to tell the main diagnostic line from what
// the user is intended to see. // the user is intended to see.
if (PrintRangeInfo) { if (DiagOpts->ShowSourceRanges) {
SourceLine = ' ' + SourceLine; SourceLine = ' ' + SourceLine;
CaretLine = ' ' + CaretLine; CaretLine = ' ' + CaretLine;
} }
std::string FixItInsertionLine; std::string FixItInsertionLine;
if (NumHints && PrintFixItInfo) { if (NumHints && DiagOpts->ShowFixits) {
for (const CodeModificationHint *Hint = Hints, *LastHint = Hints + NumHints; for (const CodeModificationHint *Hint = Hints, *LastHint = Hints + NumHints;
Hint != LastHint; ++Hint) { Hint != LastHint; ++Hint) {
if (Hint->InsertionLoc.isValid()) { if (Hint->InsertionLoc.isValid()) {
@ -417,20 +424,20 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
// Emit what we have computed. // Emit what we have computed.
OS << SourceLine << '\n'; OS << SourceLine << '\n';
if (UseColors) if (DiagOpts->ShowColors)
OS.changeColor(caretColor, true); OS.changeColor(caretColor, true);
OS << CaretLine << '\n'; OS << CaretLine << '\n';
if (UseColors) if (DiagOpts->ShowColors)
OS.resetColor(); OS.resetColor();
if (!FixItInsertionLine.empty()) { if (!FixItInsertionLine.empty()) {
if (UseColors) if (DiagOpts->ShowColors)
// Print fixit line in color // Print fixit line in color
OS.changeColor(fixitColor, false); OS.changeColor(fixitColor, false);
if (PrintRangeInfo) if (DiagOpts->ShowSourceRanges)
OS << ' '; OS << ' ';
OS << FixItInsertionLine << '\n'; OS << FixItInsertionLine << '\n';
if (UseColors) if (DiagOpts->ShowColors)
OS.resetColor(); OS.resetColor();
} }
} }
@ -627,15 +634,15 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
} }
// Compute the column number. // Compute the column number.
if (ShowLocation) { if (DiagOpts->ShowLocation) {
if (UseColors) if (DiagOpts->ShowColors)
OS.changeColor(savedColor, true); OS.changeColor(savedColor, true);
OS << PLoc.getFilename() << ':' << LineNo << ':'; OS << PLoc.getFilename() << ':' << LineNo << ':';
if (ShowColumn) if (DiagOpts->ShowColumn)
if (unsigned ColNo = PLoc.getColumn()) if (unsigned ColNo = PLoc.getColumn())
OS << ColNo << ':'; OS << ColNo << ':';
if (PrintRangeInfo && Info.getNumRanges()) { if (DiagOpts->ShowSourceRanges && Info.getNumRanges()) {
FileID CaretFileID = FileID CaretFileID =
SM.getFileID(SM.getInstantiationLoc(Info.getLocation())); SM.getFileID(SM.getInstantiationLoc(Info.getLocation()));
bool PrintedRange = false; bool PrintedRange = false;
@ -679,12 +686,12 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
OS << ':'; OS << ':';
} }
OS << ' '; OS << ' ';
if (UseColors) if (DiagOpts->ShowColors)
OS.resetColor(); OS.resetColor();
} }
} }
if (UseColors) { if (DiagOpts->ShowColors) {
// Print diagnostic category in bold and color // Print diagnostic category in bold and color
switch (Level) { switch (Level) {
case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type"); case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type");
@ -703,20 +710,20 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
case Diagnostic::Fatal: OS << "fatal error: "; break; case Diagnostic::Fatal: OS << "fatal error: "; break;
} }
if (UseColors) if (DiagOpts->ShowColors)
OS.resetColor(); OS.resetColor();
llvm::SmallString<100> OutStr; llvm::SmallString<100> OutStr;
Info.FormatDiagnostic(OutStr); Info.FormatDiagnostic(OutStr);
if (PrintDiagnosticOption) if (DiagOpts->ShowOptionNames)
if (const char *Opt = Diagnostic::getWarningOptionForDiag(Info.getID())) { if (const char *Opt = Diagnostic::getWarningOptionForDiag(Info.getID())) {
OutStr += " [-W"; OutStr += " [-W";
OutStr += Opt; OutStr += Opt;
OutStr += ']'; OutStr += ']';
} }
if (UseColors) { if (DiagOpts->ShowColors) {
// Print warnings, errors and fatal errors in bold, no color // Print warnings, errors and fatal errors in bold, no color
switch (Level) { switch (Level) {
case Diagnostic::Warning: OS.changeColor(savedColor, true); break; case Diagnostic::Warning: OS.changeColor(savedColor, true); break;
@ -726,17 +733,17 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
} }
} }
if (MessageLength) { if (DiagOpts->MessageLength) {
// We will be word-wrapping the error message, so compute the // We will be word-wrapping the error message, so compute the
// column number where we currently are (after printing the // column number where we currently are (after printing the
// location information). // location information).
unsigned Column = OS.tell() - StartOfLocationInfo; unsigned Column = OS.tell() - StartOfLocationInfo;
PrintWordWrapped(OS, OutStr, MessageLength, Column); PrintWordWrapped(OS, OutStr, DiagOpts->MessageLength, Column);
} else { } else {
OS.write(OutStr.begin(), OutStr.size()); OS.write(OutStr.begin(), OutStr.size());
} }
OS << '\n'; OS << '\n';
if (UseColors) if (DiagOpts->ShowColors)
OS.resetColor(); OS.resetColor();
// If caret diagnostics are enabled and we have location, we want to // If caret diagnostics are enabled and we have location, we want to
@ -745,7 +752,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
// was part of a different warning or error diagnostic, or if the // was part of a different warning or error diagnostic, or if the
// diagnostic has ranges. We don't want to emit the same caret // diagnostic has ranges. We don't want to emit the same caret
// multiple times if one loc has multiple diagnostics. // multiple times if one loc has multiple diagnostics.
if (CaretDiagnostics && Info.getLocation().isValid() && if (DiagOpts->ShowCarets && Info.getLocation().isValid() &&
((LastLoc != Info.getLocation()) || Info.getNumRanges() || ((LastLoc != Info.getLocation()) || Info.getNumRanges() ||
(LastCaretDiagnosticWasNote && Level != Diagnostic::Note) || (LastCaretDiagnosticWasNote && Level != Diagnostic::Note) ||
Info.getNumCodeModificationHints())) { Info.getNumCodeModificationHints())) {
@ -772,7 +779,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
EmitCaretDiagnostic(LastLoc, Ranges, NumRanges, LastLoc.getManager(), EmitCaretDiagnostic(LastLoc, Ranges, NumRanges, LastLoc.getManager(),
Info.getCodeModificationHints(), Info.getCodeModificationHints(),
Info.getNumCodeModificationHints(), Info.getNumCodeModificationHints(),
MessageLength); DiagOpts->MessageLength);
} }
OS.flush(); OS.flush();

Просмотреть файл

@ -26,6 +26,7 @@
#include "clang/Frontend/ASTConsumers.h" #include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompileOptions.h" #include "clang/Frontend/CompileOptions.h"
#include "clang/Frontend/DiagnosticOptions.h"
#include "clang/Frontend/FixItRewriter.h" #include "clang/Frontend/FixItRewriter.h"
#include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/InitHeaderSearch.h" #include "clang/Frontend/InitHeaderSearch.h"
@ -238,6 +239,8 @@ TokenCache("token-cache", llvm::cl::value_desc("path"),
// Diagnostic Options // Diagnostic Options
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
static DiagnosticOptions DiagOpts;
static llvm::cl::opt<bool> static llvm::cl::opt<bool>
VerifyDiagnostics("verify", VerifyDiagnostics("verify",
llvm::cl::desc("Verify emitted diagnostics and warnings")); llvm::cl::desc("Verify emitted diagnostics and warnings"));
@ -1566,14 +1569,7 @@ public:
// Output diags both where requested... // Output diags both where requested...
Chain1.reset(Normal); Chain1.reset(Normal);
// .. and to our log file. // .. and to our log file.
Chain2.reset(new TextDiagnosticPrinter(*BuildLogFile, Chain2.reset(new TextDiagnosticPrinter(*BuildLogFile, DiagOpts));
!NoShowColumn,
!NoCaretDiagnostics,
!NoShowLocation,
PrintSourceRangeInfo,
PrintDiagnosticOption,
!NoDiagnosticsFixIt,
MessageLength));
} }
virtual void setLangOptions(const LangOptions *LO) { virtual void setLangOptions(const LangOptions *LO) {
@ -2157,6 +2153,23 @@ int main(int argc, char **argv) {
if (InputFilenames.empty()) if (InputFilenames.empty())
InputFilenames.push_back("-"); InputFilenames.push_back("-");
// If -fmessage-length=N was not specified, determine whether this
// is a terminal and, if so, implicitly define -fmessage-length
// appropriately.
if (MessageLength.getNumOccurrences() == 0)
MessageLength.setValue(llvm::sys::Process::StandardErrColumns());
// Initialize the diagnostic options.
DiagOpts.ShowColumn = !NoShowColumn;
DiagOpts.ShowLocation = !NoShowLocation;
DiagOpts.ShowCarets = !NoCaretDiagnostics;
DiagOpts.ShowFixits = !NoDiagnosticsFixIt;
DiagOpts.ShowSourceRanges = PrintSourceRangeInfo;
DiagOpts.ShowOptionNames = PrintDiagnosticOption;
DiagOpts.ShowColors = (!NoColorDiagnostic &&
llvm::sys::Process::StandardErrHasColors());
DiagOpts.MessageLength = MessageLength;
// Create the diagnostic client for reporting errors or for // Create the diagnostic client for reporting errors or for
// implementing -verify. // implementing -verify.
llvm::OwningPtr<DiagnosticClient> DiagClient; llvm::OwningPtr<DiagnosticClient> DiagClient;
@ -2173,26 +2186,7 @@ int main(int argc, char **argv) {
} }
} else if (HTMLDiag.empty()) { } else if (HTMLDiag.empty()) {
// Print diagnostics to stderr by default. // Print diagnostics to stderr by default.
DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), DiagOpts));
// If -fmessage-length=N was not specified, determine whether this
// is a terminal and, if so, implicitly define -fmessage-length
// appropriately.
if (MessageLength.getNumOccurrences() == 0)
MessageLength.setValue(llvm::sys::Process::StandardErrColumns());
// Disable color diagnostics if not supported on stderr.
if (!NoColorDiagnostic && !llvm::sys::Process::StandardErrHasColors())
NoColorDiagnostic.setValue(true);
DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(),
!NoShowColumn,
!NoCaretDiagnostics,
!NoShowLocation,
PrintSourceRangeInfo,
PrintDiagnosticOption,
!NoDiagnosticsFixIt,
MessageLength,
!NoColorDiagnostic));
} else { } else {
DiagClient.reset(CreateHTMLDiagnosticClient(HTMLDiag)); DiagClient.reset(CreateHTMLDiagnosticClient(HTMLDiag));
} }