Index: clang-tools-extra/clang-tidy/ClangTidy.cpp =================================================================== --- clang-tools-extra/clang-tidy/ClangTidy.cpp +++ clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -106,7 +106,8 @@ DiagPrinter), SourceMgr(Diags, Files), Context(Context), ApplyFixes(ApplyFixes), TotalFixes(0), AppliedFixes(0), WarningsAsErrors(0) { - DiagOpts->ShowColors = llvm::sys::Process::StandardOutHasColors(); + DiagOpts->ShowColors = Context.getOptions().ColorDiagnostics.getValueOr( + llvm::sys::Process::StandardOutHasColors()); DiagPrinter->BeginSourceFile(LangOpts); } Index: clang-tools-extra/clang-tidy/ClangTidyOptions.h =================================================================== --- clang-tools-extra/clang-tidy/ClangTidyOptions.h +++ clang-tools-extra/clang-tidy/ClangTidyOptions.h @@ -126,6 +126,10 @@ /// apply this config file on top of the parent one. If false or missing, /// only this configuration file will be used. llvm::Optional InheritParentConfig; + + /// Use colors in diagnostics. If missing, colors will be used if standard + /// output is connected to a terminal. + llvm::Optional ColorDiagnostics; }; /// Abstract interface for retrieving various ClangTidy options. Index: clang-tools-extra/clang-tidy/ClangTidyOptions.cpp =================================================================== --- clang-tools-extra/clang-tidy/ClangTidyOptions.cpp +++ clang-tools-extra/clang-tidy/ClangTidyOptions.cpp @@ -96,6 +96,7 @@ IO.mapOptional("ExtraArgs", Options.ExtraArgs); IO.mapOptional("ExtraArgsBefore", Options.ExtraArgsBefore); IO.mapOptional("InheritParentConfig", Options.InheritParentConfig); + IO.mapOptional("ColorDiagnostics", Options.ColorDiagnostics); } }; @@ -154,6 +155,7 @@ overrideValue(Result.SystemHeaders, Other.SystemHeaders); overrideValue(Result.FormatStyle, Other.FormatStyle); overrideValue(Result.User, Other.User); + overrideValue(Result.ColorDiagnostics, Other.ColorDiagnostics); mergeVectors(Result.ExtraArgs, Other.ExtraArgs); mergeVectors(Result.ExtraArgsBefore, Other.ExtraArgsBefore); Index: clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp =================================================================== --- clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp +++ clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp @@ -229,6 +229,13 @@ cl::value_desc("filename"), cl::cat(ClangTidyCategory)); +static cl::opt ColorDiagnostics("color-diagnostics", cl::desc(R"( +Use colors in diagnostics. If not set, colors +will be used if standard output is connected +to a terminal. +)"), + cl::cat(ClangTidyCategory)); + namespace clang { namespace tidy { @@ -279,6 +286,7 @@ // USERNAME is used on Windows. if (!DefaultOptions.User) DefaultOptions.User = llvm::sys::Process::GetEnv("USERNAME"); + DefaultOptions.ColorDiagnostics = ColorDiagnostics; ClangTidyOptions OverrideOptions; if (Checks.getNumOccurrences() > 0) @@ -291,6 +299,8 @@ OverrideOptions.SystemHeaders = SystemHeaders; if (FormatStyle.getNumOccurrences() > 0) OverrideOptions.FormatStyle = FormatStyle; + if (ColorDiagnostics.getNumOccurrences() > 0) + OverrideOptions.ColorDiagnostics = ColorDiagnostics; if (!Config.empty()) { if (llvm::ErrorOr ParsedConfig = Index: clang-tools-extra/test/clang-tidy/infrastructure/color-diagnostics.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/infrastructure/color-diagnostics.cpp @@ -0,0 +1,27 @@ +// RUN: clang-tidy -dump-config | FileCheck -check-prefix=CHECK-CONFIG-NO-COLOR %s +// RUN: clang-tidy -dump-config -color-diagnostics | FileCheck -check-prefix=CHECK-CONFIG-COLOR %s +// RUN: clang-tidy -dump-config -color-diagnostics=false | FileCheck -check-prefix=CHECK-CONFIG-NO-COLOR %s +// RUN: clang-tidy -config='ColorDiagnostics: true' -dump-config | FileCheck -check-prefix=CHECK-CONFIG-COLOR %s +// RUN: clang-tidy -config='ColorDiagnostics: false' -dump-config | FileCheck -check-prefix=CHECK-CONFIG-NO-COLOR %s +// RUN: clang-tidy -help | FileCheck -check-prefix=CHECK-OPT-PRESENT %s + +// REQUIRES: ansi-escape-sequences +// RUN: clang-tidy -checks='-*, modernize-use-override' -extra-arg=-std=c++11 -color-diagnostics=false %s | FileCheck -check-prefix=CHECK-NO-COLOR %s +// RUN: clang-tidy -checks='-*, modernize-use-override' -extra-arg=-std=c++11 %s | FileCheck -check-prefix=CHECK-NO-COLOR %s +// RUN: clang-tidy -checks='-*, modernize-use-override' -extra-arg=-std=c++11 -color-diagnostics %s | FileCheck -check-prefix=CHECK-COLOR %s + +// CHECK-CONFIG-NO-COLOR: ColorDiagnostics: false +// CHECK-CONFIG-COLOR: ColorDiagnostics: true +// CHECK-OPT-PRESENT: --color-diagnostics + +class Base { +public: + virtual ~Base() = 0; +}; + +class Delivered : public Base { +public: + virtual ~Delivered() = default; + // CHECK-NO-COLOR: warning: prefer using 'override' or (rarely) 'final' instead of 'virtual' [modernize-use-override] + // CHECK-COLOR: {{.\[0;1;35m}}warning: {{.\[0m}}{{.\[1m}}prefer using 'override' or (rarely) 'final' instead of 'virtual' [modernize-use-override] +}; Index: clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp =================================================================== --- clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp +++ clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp @@ -76,6 +76,7 @@ User: user1 ExtraArgs: ['arg1', 'arg2'] ExtraArgsBefore: ['arg-before1', 'arg-before2'] + ColorDiagnostics: false )"); ASSERT_TRUE(!!Options1); llvm::ErrorOr Options2 = parseConfiguration(R"( @@ -85,6 +86,7 @@ User: user2 ExtraArgs: ['arg3', 'arg4'] ExtraArgsBefore: ['arg-before3', 'arg-before4'] + ColorDiagnostics: true )"); ASSERT_TRUE(!!Options2); ClangTidyOptions Options = Options1->mergeWith(*Options2, 0); @@ -98,6 +100,8 @@ EXPECT_EQ("arg-before1,arg-before2,arg-before3,arg-before4", llvm::join(Options.ExtraArgsBefore->begin(), Options.ExtraArgsBefore->end(), ",")); + ASSERT_TRUE(Options.ColorDiagnostics.hasValue()); + EXPECT_TRUE(*Options.ColorDiagnostics); } class TestCheck : public ClangTidyCheck {