[Clang] Refactor and consolidate color diagnostic handling (#202441)
Summary: This PR tries to consolidate the color output handling in Clang. The motivation was noticing that `-Xclang -ast-dump` would not behave like `-fcolor-diagnostics` and would output ANSI codes to a file when I tried to pipe it. This PR primarily turns the handling into a tri-state enum keyed off of `-f[no]-color-diagnostics`. The default/auto case will be if the target stream supports colors. Getting this to work required a lot of seemingly unrelated plumbing. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
971a872cfa
commit
2a215f473f
18 changed files with 148 additions and 67 deletions
|
|
@ -105,10 +105,13 @@ public:
|
|||
DiagPrinter(new TextDiagnosticPrinter(llvm::outs(), DiagOpts)),
|
||||
Diags(DiagnosticIDs::create(), DiagOpts, DiagPrinter),
|
||||
SourceMgr(Diags, Files), Context(Context), ApplyFixes(ApplyFixes) {
|
||||
DiagOpts.ShowColors = Context.getOptions().UseColor.value_or(
|
||||
llvm::sys::Process::StandardOutHasColors());
|
||||
DiagOpts.setShowColors(Context.getOptions().UseColor.value_or(
|
||||
llvm::sys::Process::StandardOutHasColors())
|
||||
? ShowColorsKind::On
|
||||
: ShowColorsKind::Off);
|
||||
DiagPrinter->BeginSourceFile(LangOpts);
|
||||
if (DiagOpts.ShowColors && !llvm::sys::Process::StandardOutIsDisplayed())
|
||||
if (DiagOpts.showColors(llvm::sys::Process::StandardOutHasColors()) &&
|
||||
!llvm::sys::Process::StandardOutIsDisplayed())
|
||||
llvm::sys::Process::UseANSIEscapeCodes(true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ void disableUnsupportedOptions(CompilerInvocation &CI) {
|
|||
// our compiler invocation set-up doesn't seem to work with it (leading
|
||||
// assertions in VerifyDiagnosticConsumer).
|
||||
CI.getDiagnosticOpts().VerifyDiagnostics = false;
|
||||
CI.getDiagnosticOpts().ShowColors = false;
|
||||
CI.getDiagnosticOpts().setShowColors(ShowColorsKind::Off);
|
||||
|
||||
// Disable any dependency outputting, we don't want to generate files or write
|
||||
// to stdout/stderr.
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ VALUE_DIAGOPT(ShowCategories, 2, 0) /// Show categories: 0 -> none, 1 -> Number,
|
|||
|
||||
ENUM_DIAGOPT(Format, TextDiagnosticFormat, 2, Clang) /// Format for diagnostics:
|
||||
|
||||
DIAGOPT(ShowColors, 1, 0) /// Show diagnostics with ANSI color sequences.
|
||||
ENUM_DIAGOPT(ShowColors, ShowColorsKind, 2, ShowColorsKind::Auto)
|
||||
DIAGOPT(UseANSIEscapeCodes, 1, 0)
|
||||
ENUM_DIAGOPT(ShowOverloads, OverloadsShown, 1,
|
||||
Ovl_All) /// Overload candidates to show.
|
||||
|
|
|
|||
|
|
@ -23,6 +23,16 @@ class ArgList;
|
|||
namespace clang {
|
||||
class DiagnosticsEngine;
|
||||
|
||||
/// Controls whether to show colors in diagnostic output.
|
||||
enum class ShowColorsKind : unsigned {
|
||||
/// Emit colors only if the output stream is detected to support them.
|
||||
Auto,
|
||||
/// Always emit colors regardless of the output stream.
|
||||
On,
|
||||
/// Never emit colors regardless of the output stream.
|
||||
Off,
|
||||
};
|
||||
|
||||
/// Specifies which overload candidates to display when overload
|
||||
/// resolution fails.
|
||||
enum OverloadsShown : unsigned {
|
||||
|
|
@ -143,6 +153,19 @@ public:
|
|||
#define ENUM_DIAGOPT(Name, Type, Bits, Default) set##Name(Default);
|
||||
#include "clang/Basic/DiagnosticOptions.def"
|
||||
}
|
||||
|
||||
/// Resolve the color mode against a stream's capability.
|
||||
bool showColors(bool StreamHasColors) const {
|
||||
switch (getShowColors()) {
|
||||
case ShowColorsKind::On:
|
||||
return true;
|
||||
case ShowColorsKind::Off:
|
||||
return false;
|
||||
case ShowColorsKind::Auto:
|
||||
return StreamHasColors;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
using TextDiagnosticFormat = DiagnosticOptions::TextDiagnosticFormat;
|
||||
|
|
|
|||
|
|
@ -2093,7 +2093,7 @@ def fcolor_diagnostics : Flag<["-"], "fcolor-diagnostics">, Group<f_Group>,
|
|||
Visibility<[ClangOption, CLOption, DXCOption, CC1Option, FlangOption, FC1Option]>,
|
||||
HelpText<"Enable colors in diagnostics">;
|
||||
def fno_color_diagnostics : Flag<["-"], "fno-color-diagnostics">, Group<f_Group>,
|
||||
Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,
|
||||
Visibility<[ClangOption, CLOption, DXCOption, CC1Option, FlangOption, FC1Option]>,
|
||||
HelpText<"Disable colors in diagnostics">;
|
||||
def : Flag<["-"], "fdiagnostics-color">, Group<f_Group>,
|
||||
Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,
|
||||
|
|
|
|||
|
|
@ -16,12 +16,18 @@
|
|||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/DeclLookups.h"
|
||||
#include "clang/AST/JSONNodeDumper.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::comments;
|
||||
|
||||
static bool showColorsForStream(const ASTContext &Ctx, raw_ostream &OS) {
|
||||
return Ctx.getDiagnostics().getDiagnosticOptions().showColors(
|
||||
OS.has_colors());
|
||||
}
|
||||
|
||||
void ASTDumper::dumpInvalidDeclContext(const DeclContext *DC) {
|
||||
NodeDumper.AddChild([=] {
|
||||
if (!DC) {
|
||||
|
|
@ -189,7 +195,7 @@ LLVM_DUMP_METHOD void QualType::dump() const {
|
|||
|
||||
LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS,
|
||||
const ASTContext &Context) const {
|
||||
ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
|
||||
ASTDumper Dumper(OS, Context, showColorsForStream(Context, OS));
|
||||
Dumper.Visit(*this);
|
||||
}
|
||||
|
||||
|
|
@ -210,7 +216,7 @@ LLVM_DUMP_METHOD void TypeLoc::dump() const {
|
|||
|
||||
LLVM_DUMP_METHOD void TypeLoc::dump(llvm::raw_ostream &OS,
|
||||
const ASTContext &Context) const {
|
||||
ASTDumper(OS, Context, Context.getDiagnostics().getShowColors()).Visit(*this);
|
||||
ASTDumper(OS, Context, showColorsForStream(Context, OS)).Visit(*this);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
@ -230,7 +236,7 @@ LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize,
|
|||
(void)Deserialize; // FIXME?
|
||||
P.Visit(this);
|
||||
} else {
|
||||
ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
|
||||
ASTDumper P(OS, Ctx, showColorsForStream(Ctx, OS));
|
||||
P.setDeserialize(Deserialize);
|
||||
P.Visit(this);
|
||||
}
|
||||
|
|
@ -261,7 +267,7 @@ LLVM_DUMP_METHOD void DeclContext::dumpAsDecl(const ASTContext *Ctx) const {
|
|||
// If an ASTContext is not available, a less capable ASTDumper is
|
||||
// constructed for which color diagnostics are, regrettably, disabled.
|
||||
ASTDumper P = Ctx ? ASTDumper(llvm::errs(), *Ctx,
|
||||
Ctx->getDiagnostics().getShowColors())
|
||||
showColorsForStream(*Ctx, llvm::errs()))
|
||||
: ASTDumper(llvm::errs(), /*ShowColors*/ false);
|
||||
P.dumpInvalidDeclContext(this);
|
||||
}
|
||||
|
|
@ -278,7 +284,7 @@ LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,
|
|||
while (!DC->isTranslationUnit())
|
||||
DC = DC->getParent();
|
||||
const ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
|
||||
ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
|
||||
ASTDumper P(OS, Ctx, showColorsForStream(Ctx, OS));
|
||||
P.setDeserialize(Deserialize);
|
||||
P.dumpLookups(this, DumpDecls);
|
||||
}
|
||||
|
|
@ -294,7 +300,7 @@ LLVM_DUMP_METHOD void Stmt::dump() const {
|
|||
|
||||
LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS,
|
||||
const ASTContext &Context) const {
|
||||
ASTDumper P(OS, Context, Context.getDiagnostics().getShowColors());
|
||||
ASTDumper P(OS, Context, showColorsForStream(Context, OS));
|
||||
P.Visit(this);
|
||||
}
|
||||
|
||||
|
|
@ -320,7 +326,7 @@ LLVM_DUMP_METHOD void Comment::dump(raw_ostream &OS,
|
|||
const auto *FC = dyn_cast<FullComment>(this);
|
||||
if (!FC)
|
||||
return;
|
||||
ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
|
||||
ASTDumper Dumper(OS, Context, showColorsForStream(Context, OS));
|
||||
Dumper.Visit(FC, FC);
|
||||
}
|
||||
|
||||
|
|
@ -343,7 +349,7 @@ LLVM_DUMP_METHOD void APValue::dump() const {
|
|||
|
||||
LLVM_DUMP_METHOD void APValue::dump(raw_ostream &OS,
|
||||
const ASTContext &Context) const {
|
||||
ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
|
||||
ASTDumper Dumper(OS, Context, showColorsForStream(Context, OS));
|
||||
Dumper.Visit(*this, /*Ty=*/Context.getPointerType(Context.CharTy));
|
||||
}
|
||||
|
||||
|
|
@ -357,7 +363,7 @@ LLVM_DUMP_METHOD void ConceptReference::dump() const {
|
|||
|
||||
LLVM_DUMP_METHOD void ConceptReference::dump(raw_ostream &OS) const {
|
||||
auto &Ctx = getNamedConcept()->getASTContext();
|
||||
ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
|
||||
ASTDumper P(OS, Ctx, showColorsForStream(Ctx, OS));
|
||||
P.Visit(this);
|
||||
}
|
||||
|
||||
|
|
@ -376,7 +382,7 @@ LLVM_DUMP_METHOD void TemplateName::dump() const {
|
|||
|
||||
LLVM_DUMP_METHOD void TemplateName::dump(llvm::raw_ostream &OS,
|
||||
const ASTContext &Context) const {
|
||||
ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
|
||||
ASTDumper Dumper(OS, Context, showColorsForStream(Context, OS));
|
||||
Dumper.Visit(*this);
|
||||
}
|
||||
|
||||
|
|
@ -391,6 +397,6 @@ LLVM_DUMP_METHOD void TemplateArgument::dump() const {
|
|||
|
||||
LLVM_DUMP_METHOD void TemplateArgument::dump(llvm::raw_ostream &OS,
|
||||
const ASTContext &Context) const {
|
||||
ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
|
||||
ASTDumper Dumper(OS, Context, showColorsForStream(Context, OS));
|
||||
Dumper.Visit(*this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "clang/Basic/DiagnosticOptions.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/VirtualFileSystem.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cstring>
|
||||
using namespace clang;
|
||||
|
||||
|
|
@ -53,7 +54,7 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
|
|||
|
||||
Diags.setElideType(Opts.ElideType);
|
||||
Diags.setPrintTemplateTree(Opts.ShowTemplateTree);
|
||||
Diags.setShowColors(Opts.ShowColors);
|
||||
Diags.setShowColors(Opts.showColors(llvm::errs().has_colors()));
|
||||
|
||||
// Handle -ferror-limit
|
||||
if (Opts.ErrorLimit)
|
||||
|
|
|
|||
|
|
@ -3317,8 +3317,16 @@ void tools::handleColorDiagnosticsArgs(const Driver &D, const ArgList &Args,
|
|||
<< Value << A->getOption().getName();
|
||||
}
|
||||
|
||||
if (D.getDiags().getDiagnosticOptions().ShowColors)
|
||||
switch (D.getDiags().getDiagnosticOptions().getShowColors()) {
|
||||
case ShowColorsKind::On:
|
||||
CmdArgs.push_back("-fcolor-diagnostics");
|
||||
break;
|
||||
case ShowColorsKind::Off:
|
||||
CmdArgs.push_back("-fno-color-diagnostics");
|
||||
break;
|
||||
case ShowColorsKind::Auto:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void tools::escapeSpacesAndBackslashes(const char *Arg,
|
||||
|
|
|
|||
|
|
@ -2459,35 +2459,31 @@ static bool ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
|
|||
return Diags.getNumErrors() == NumErrorsBefore;
|
||||
}
|
||||
|
||||
static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) {
|
||||
static ShowColorsKind parseShowColorsMode(const ArgList &Args,
|
||||
bool DefaultColor) {
|
||||
// Color diagnostics default to auto ("on" if terminal supports) in the driver
|
||||
// but default to off in cc1, needing an explicit OPT_fdiagnostics_color.
|
||||
// Support both clang's -f[no-]color-diagnostics and gcc's
|
||||
// -f[no-]diagnostics-colors[=never|always|auto].
|
||||
enum {
|
||||
Colors_On,
|
||||
Colors_Off,
|
||||
Colors_Auto
|
||||
} ShowColors = DefaultColor ? Colors_Auto : Colors_Off;
|
||||
ShowColorsKind Mode =
|
||||
DefaultColor ? ShowColorsKind::Auto : ShowColorsKind::Off;
|
||||
for (auto *A : Args) {
|
||||
const Option &O = A->getOption();
|
||||
if (O.matches(options::OPT_fcolor_diagnostics)) {
|
||||
ShowColors = Colors_On;
|
||||
Mode = ShowColorsKind::On;
|
||||
} else if (O.matches(options::OPT_fno_color_diagnostics)) {
|
||||
ShowColors = Colors_Off;
|
||||
Mode = ShowColorsKind::Off;
|
||||
} else if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
|
||||
StringRef Value(A->getValue());
|
||||
if (Value == "always")
|
||||
ShowColors = Colors_On;
|
||||
Mode = ShowColorsKind::On;
|
||||
else if (Value == "never")
|
||||
ShowColors = Colors_Off;
|
||||
Mode = ShowColorsKind::Off;
|
||||
else if (Value == "auto")
|
||||
ShowColors = Colors_Auto;
|
||||
Mode = ShowColorsKind::Auto;
|
||||
}
|
||||
}
|
||||
return ShowColors == Colors_On ||
|
||||
(ShowColors == Colors_Auto &&
|
||||
llvm::sys::Process::StandardErrHasColors());
|
||||
return Mode;
|
||||
}
|
||||
|
||||
static bool checkVerifyPrefixes(const std::vector<std::string> &VerifyPrefixes,
|
||||
|
|
@ -2568,8 +2564,16 @@ void CompilerInvocationBase::GenerateDiagnosticArgs(
|
|||
GenerateArg(Consumer, OPT_diagnostic_serialized_file,
|
||||
Opts.DiagnosticSerializationFile);
|
||||
|
||||
if (Opts.ShowColors)
|
||||
switch (Opts.getShowColors()) {
|
||||
case ShowColorsKind::On:
|
||||
GenerateArg(Consumer, OPT_fcolor_diagnostics);
|
||||
break;
|
||||
case ShowColorsKind::Off:
|
||||
GenerateArg(Consumer, OPT_fno_color_diagnostics);
|
||||
break;
|
||||
case ShowColorsKind::Auto:
|
||||
break;
|
||||
}
|
||||
|
||||
if (Opts.VerifyDiagnostics &&
|
||||
llvm::is_contained(Opts.VerifyPrefixes, "expected"))
|
||||
|
|
@ -2678,7 +2682,7 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
|
|||
if (Arg *A =
|
||||
Args.getLastArg(OPT_diagnostic_serialized_file, OPT__serialize_diags))
|
||||
Opts.DiagnosticSerializationFile = A->getValue();
|
||||
Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor);
|
||||
Opts.setShowColors(parseShowColorsMode(Args, DefaultDiagColor));
|
||||
|
||||
Opts.VerifyDiagnostics = Args.hasArg(OPT_verify) || Args.hasArg(OPT_verify_EQ);
|
||||
Opts.VerifyDirectives = Args.hasArg(OPT_verify_directives);
|
||||
|
|
@ -5090,8 +5094,7 @@ bool CompilerInvocation::CreateFromArgsImpl(
|
|||
ParseMigratorArgs(Res.getMigratorOpts(), Args, Diags);
|
||||
ParseAnalyzerArgs(Res.getAnalyzerOpts(), Args, Diags);
|
||||
ParseSSAFArgs(Res.getSSAFOpts(), Args, Diags);
|
||||
ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags,
|
||||
/*DefaultDiagColor=*/false);
|
||||
ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags);
|
||||
ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags, LangOpts.IsHeaderFile);
|
||||
// FIXME: We shouldn't have to pass the DashX option around here
|
||||
InputKind DashX = Res.getFrontendOpts().DashX;
|
||||
|
|
|
|||
|
|
@ -700,7 +700,8 @@ namespace {
|
|||
Out.indent(2) << "Diagnostic options:\n";
|
||||
#define DIAGOPT(Name, Bits, Default) DUMP_BOOLEAN(DiagOpts.Name, #Name);
|
||||
#define ENUM_DIAGOPT(Name, Type, Bits, Default) \
|
||||
Out.indent(4) << #Name << ": " << DiagOpts.get##Name() << "\n";
|
||||
Out.indent(4) << #Name << ": " \
|
||||
<< static_cast<unsigned>(DiagOpts.get##Name()) << "\n";
|
||||
#define VALUE_DIAGOPT(Name, Bits, Default) \
|
||||
Out.indent(4) << #Name << ": " << DiagOpts.Name << "\n";
|
||||
#include "clang/Basic/DiagnosticOptions.def"
|
||||
|
|
|
|||
|
|
@ -730,15 +730,16 @@ void TextDiagnostic::emitDiagnosticMessage(
|
|||
if (Loc.isValid())
|
||||
emitDiagnosticLoc(Loc, PLoc, Level, Ranges);
|
||||
|
||||
if (DiagOpts.ShowColors)
|
||||
if (DiagOpts.showColors(OS.has_colors()))
|
||||
OS.resetColor();
|
||||
|
||||
if (DiagOpts.ShowLevel)
|
||||
printDiagnosticLevel(OS, Level, DiagOpts.ShowColors);
|
||||
printDiagnosticLevel(OS, Level, DiagOpts.showColors(OS.has_colors()));
|
||||
printDiagnosticMessage(OS,
|
||||
/*IsSupplemental*/ Level == DiagnosticsEngine::Note,
|
||||
Message, OS.getColumn() - StartOfLocationInfo,
|
||||
DiagOpts.MessageLength, DiagOpts.ShowColors);
|
||||
DiagOpts.MessageLength,
|
||||
DiagOpts.showColors(OS.has_colors()));
|
||||
// We use a formatted ostream, which does its own buffering. Flush here
|
||||
// so we keep the proper order of output.
|
||||
OS.flush();
|
||||
|
|
@ -872,7 +873,7 @@ void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
|
|||
if (!DiagOpts.ShowLocation)
|
||||
return;
|
||||
|
||||
if (DiagOpts.ShowColors)
|
||||
if (DiagOpts.showColors(OS.has_colors()))
|
||||
OS.changeColor(SavedColor, true);
|
||||
|
||||
emitFilename(PLoc.getFilename(), Loc.getManager());
|
||||
|
|
@ -1429,7 +1430,7 @@ void TextDiagnostic::emitSnippetAndCaret(
|
|||
// emit, starting from the first line.
|
||||
std::unique_ptr<SmallVector<StyleRange>[]> SourceStyles =
|
||||
highlightLines(BufData, Lines.first, Lines.second, PP, LangOpts,
|
||||
DiagOpts.ShowColors, FID, SM);
|
||||
DiagOpts.showColors(OS.has_colors()), FID, SM);
|
||||
|
||||
SmallVector<LineRange> LineRanges =
|
||||
prepareAndFilterRanges(Ranges, SM, Lines, FID, LangOpts);
|
||||
|
|
@ -1508,22 +1509,22 @@ void TextDiagnostic::emitSnippetAndCaret(
|
|||
|
||||
if (!CaretLine.empty()) {
|
||||
indentForLineNumbers();
|
||||
if (DiagOpts.ShowColors)
|
||||
if (DiagOpts.showColors(OS.has_colors()))
|
||||
OS.changeColor(CaretColor, true);
|
||||
OS << CaretLine << '\n';
|
||||
if (DiagOpts.ShowColors)
|
||||
if (DiagOpts.showColors(OS.has_colors()))
|
||||
OS.resetColor();
|
||||
}
|
||||
|
||||
if (!FixItInsertionLine.empty()) {
|
||||
indentForLineNumbers();
|
||||
if (DiagOpts.ShowColors)
|
||||
if (DiagOpts.showColors(OS.has_colors()))
|
||||
// Print fixit line in color
|
||||
OS.changeColor(FixitColor, false);
|
||||
if (DiagOpts.ShowSourceRanges)
|
||||
OS << ' ';
|
||||
OS << FixItInsertionLine << '\n';
|
||||
if (DiagOpts.ShowColors)
|
||||
if (DiagOpts.showColors(OS.has_colors()))
|
||||
OS.resetColor();
|
||||
}
|
||||
}
|
||||
|
|
@ -1552,7 +1553,7 @@ void TextDiagnostic::emitSnippet(StringRef SourceLine,
|
|||
printableTextForNextCharacter(SourceLine, &I, DiagOpts.TabStop);
|
||||
|
||||
// Toggle inverted colors on or off for this character.
|
||||
if (DiagOpts.ShowColors) {
|
||||
if (DiagOpts.showColors(OS.has_colors())) {
|
||||
if (WasPrintable == PrintReversed) {
|
||||
PrintReversed = !PrintReversed;
|
||||
if (PrintReversed)
|
||||
|
|
@ -1583,7 +1584,7 @@ void TextDiagnostic::emitSnippet(StringRef SourceLine,
|
|||
OS << Str;
|
||||
}
|
||||
|
||||
if (DiagOpts.ShowColors)
|
||||
if (DiagOpts.showColors(OS.has_colors()))
|
||||
OS.resetColor();
|
||||
|
||||
OS << '\n';
|
||||
|
|
|
|||
|
|
@ -134,11 +134,12 @@ void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
|
|||
// other infrastructure necessary when emitting more rich diagnostics.
|
||||
if (!Info.getLocation().isValid()) {
|
||||
if (DiagOpts.ShowLevel)
|
||||
TextDiagnostic::printDiagnosticLevel(OS, Level, DiagOpts.ShowColors);
|
||||
TextDiagnostic::printDiagnosticLevel(
|
||||
OS, Level, DiagOpts.showColors(OS.has_colors()));
|
||||
TextDiagnostic::printDiagnosticMessage(
|
||||
OS, /*IsSupplemental=*/Level == DiagnosticsEngine::Note,
|
||||
DiagMessageStream.str(), OS.tell() - StartOfLocationInfo,
|
||||
DiagOpts.MessageLength, DiagOpts.ShowColors);
|
||||
DiagOpts.MessageLength, DiagOpts.showColors(OS.has_colors()));
|
||||
OS.flush();
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
25
clang/test/Misc/diagnostic-color-output-stream.cpp
Normal file
25
clang/test/Misc/diagnostic-color-output-stream.cpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// REQUIRES: ansi-escape-sequences
|
||||
|
||||
// Default ('auto'): a redirected (non-terminal) stderr must not get ANSI codes.
|
||||
// RUN: not %clang_cc1 -fsyntax-only -std=c++11 %s 2>&1 \
|
||||
// RUN: | FileCheck --check-prefix=NOCOLOR %s
|
||||
|
||||
// Forced off behaves the same.
|
||||
// RUN: not %clang_cc1 -fsyntax-only -std=c++11 -fno-color-diagnostics %s 2>&1 \
|
||||
// RUN: | FileCheck --check-prefix=NOCOLOR %s
|
||||
|
||||
// Forced on: ANSI codes are emitted even to a non-terminal.
|
||||
// RUN: not %clang_cc1 -fsyntax-only -std=c++11 -fcolor-diagnostics %s 2>&1 \
|
||||
// RUN: | FileCheck --check-prefix=COLOR %s
|
||||
|
||||
// A -diagnostic-log-file pointing at a regular file must not contain ANSI.
|
||||
// RUN: rm -f %t.log
|
||||
// RUN: not %clang_cc1 -fsyntax-only -std=c++11 -diagnostic-log-file %t.log %s 2>/dev/null
|
||||
// RUN: FileCheck --check-prefix=NOCOLOR %s < %t.log
|
||||
|
||||
template <typename> struct foo {};
|
||||
void func(foo<int>);
|
||||
void g() { func(foo<double>()); }
|
||||
|
||||
// COLOR: {{.\[0;1;36m}}double{{.\[0m}}
|
||||
// NOCOLOR-NOT: {{.\[0;1;36m}}
|
||||
|
|
@ -651,11 +651,13 @@ struct CheckColoredDiagnosticsAction : public clang::ASTFrontendAction {
|
|||
: ShouldShowColor(ShouldShowColor) {}
|
||||
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
|
||||
StringRef) override {
|
||||
if (Compiler.getDiagnosticOpts().ShowColors != ShouldShowColor)
|
||||
bool HasColors =
|
||||
Compiler.getDiagnosticOpts().getShowColors() ==
|
||||
(ShouldShowColor ? ShowColorsKind::On : ShowColorsKind::Off);
|
||||
if (!HasColors)
|
||||
Compiler.getDiagnostics().Report(
|
||||
Compiler.getDiagnostics().getCustomDiagID(
|
||||
DiagnosticsEngine::Fatal,
|
||||
"getDiagnosticOpts().ShowColors != ShouldShowColor"));
|
||||
DiagnosticsEngine::Fatal, "getShowColors() != expected"));
|
||||
return std::make_unique<ASTConsumer>();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -122,7 +122,8 @@ static unsigned getOptimizationLevel(llvm::opt::ArgList &args,
|
|||
|
||||
bool Fortran::frontend::parseDiagnosticArgs(clang::DiagnosticOptions &opts,
|
||||
llvm::opt::ArgList &args) {
|
||||
opts.ShowColors = parseShowColorsArgs(args);
|
||||
opts.setShowColors(parseShowColorsArgs(args) ? clang::ShowColorsKind::On
|
||||
: clang::ShowColorsKind::Off);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1102,8 +1103,10 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
|
|||
|
||||
// Default to off for `flang -fc1`.
|
||||
bool showColors{parseShowColorsArgs(args, false)};
|
||||
diags.getDiagnosticOptions().ShowColors = showColors;
|
||||
res.getDiagnosticOpts().ShowColors = showColors;
|
||||
auto colorsMode =
|
||||
showColors ? clang::ShowColorsKind::On : clang::ShowColorsKind::Off;
|
||||
diags.getDiagnosticOptions().setShowColors(colorsMode);
|
||||
res.getDiagnosticOpts().setShowColors(colorsMode);
|
||||
res.getFrontendOpts().showColors = showColors;
|
||||
return !diags.hasUncompilableErrorOccurred();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ void TextDiagnosticPrinter::printLocForRemarks(
|
|||
llvm::sys::path::make_preferred(absPath);
|
||||
|
||||
// Used for changing only the bold attribute
|
||||
if (diagOpts.ShowColors)
|
||||
if (diagOpts.showColors(os.has_colors()))
|
||||
os.changeColor(llvm::raw_ostream::SAVEDCOLOR, true);
|
||||
|
||||
// Print path, file name, line and column
|
||||
|
|
@ -112,12 +112,12 @@ void TextDiagnosticPrinter::HandleDiagnostic(
|
|||
llvm::StringRef diagMsg;
|
||||
printLocForRemarks(diagMessageStream, diagMsg);
|
||||
|
||||
Fortran::frontend::TextDiagnostic::printDiagnosticLevel(os, level,
|
||||
diagOpts.ShowColors);
|
||||
Fortran::frontend::TextDiagnostic::printDiagnosticLevel(
|
||||
os, level, diagOpts.showColors(os.has_colors()));
|
||||
Fortran::frontend::TextDiagnostic::printDiagnosticMessage(
|
||||
os,
|
||||
/*IsSupplemental=*/level == clang::DiagnosticsEngine::Note, diagMsg,
|
||||
diagOpts.ShowColors);
|
||||
diagOpts.showColors(os.has_colors()));
|
||||
|
||||
os.flush();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
! RUN: not %flang_fc1 %s -fcolor-diagnostics 2>&1 \
|
||||
! RUN: | FileCheck %s --check-prefix=CHECK_CD
|
||||
! RUN: not %flang_fc1 %s -fno-color-diagnostics 2>&1 \
|
||||
! RUN: | FileCheck %s --check-prefix=UNSUPPORTED_COLOR_DIAGS
|
||||
! RUN: | FileCheck %s --check-prefix=CHECK_NCD
|
||||
|
||||
! RUN: not %flang %s -fdiagnostics-color 2>&1 \
|
||||
! RUN: | FileCheck %s --check-prefix=CHECK_CD
|
||||
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
! CHECK_NCD: Semantic errors in {{.*}}color-diagnostics.f90
|
||||
|
||||
! UNSUPPORTED_COLOR_DIAGS: error: unknown argument: '-fno-color-diagnostics'
|
||||
! UNSUPPORTED_DIAGS_COLOR: error: unknown argument: '-fdiagnostics-color'
|
||||
! UNSUPPORTED_NO_DIAGS_COLOR: error: unknown argument: '-fno-diagnostics-color'
|
||||
|
||||
|
|
|
|||
|
|
@ -8477,14 +8477,19 @@ TypeSystemClang::dump(lldb::opaque_compiler_type_t type) const {
|
|||
namespace {
|
||||
struct ScopedASTColor {
|
||||
ScopedASTColor(clang::ASTContext &ast, bool show_colors)
|
||||
: ast(ast), old_show_colors(ast.getDiagnostics().getShowColors()) {
|
||||
ast.getDiagnostics().setShowColors(show_colors);
|
||||
: ast(ast),
|
||||
old_show_colors(
|
||||
ast.getDiagnostics().getDiagnosticOptions().getShowColors()) {
|
||||
ast.getDiagnostics().getDiagnosticOptions().setShowColors(
|
||||
show_colors ? clang::ShowColorsKind::On : clang::ShowColorsKind::Off);
|
||||
}
|
||||
|
||||
~ScopedASTColor() { ast.getDiagnostics().setShowColors(old_show_colors); }
|
||||
~ScopedASTColor() {
|
||||
ast.getDiagnostics().getDiagnosticOptions().setShowColors(old_show_colors);
|
||||
}
|
||||
|
||||
clang::ASTContext *
|
||||
const bool old_show_colors;
|
||||
const clang::ShowColorsKind old_show_colors;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue