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().UseColor.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,9 @@ /// 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, it will be auto detect. + llvm::Optional UseColor; }; /// 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("UseColor", Options.UseColor); } }; @@ -154,6 +155,7 @@ overrideValue(Result.SystemHeaders, Other.SystemHeaders); overrideValue(Result.FormatStyle, Other.FormatStyle); overrideValue(Result.User, Other.User); + overrideValue(Result.UseColor, Other.UseColor); 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,15 @@ cl::value_desc("filename"), cl::cat(ClangTidyCategory)); +static cl::opt UseColor("use-color", cl::desc(R"( +Use colors in diagnostics. If not set, colors +will be used if the terminal connected to +standard output supports colors. +This option overrides the 'UseColor' option in +.clang-tidy file, if any. +)"), + cl::init(false), cl::cat(ClangTidyCategory)); + namespace clang { namespace tidy { @@ -291,6 +300,8 @@ OverrideOptions.SystemHeaders = SystemHeaders; if (FormatStyle.getNumOccurrences() > 0) OverrideOptions.FormatStyle = FormatStyle; + if (UseColor.getNumOccurrences() > 0) + OverrideOptions.UseColor = UseColor; if (!Config.empty()) { if (llvm::ErrorOr ParsedConfig = Index: clang-tools-extra/test/clang-tidy/infrastructure/use-color.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/infrastructure/use-color.cpp @@ -0,0 +1,28 @@ +// RUN: clang-tidy -dump-config | FileCheck %s +// RUN: clang-tidy -dump-config -use-color | FileCheck -check-prefix=CHECK-CONFIG-COLOR %s +// RUN: clang-tidy -dump-config -use-color=false | FileCheck -check-prefix=CHECK-CONFIG-NO-COLOR %s +// RUN: clang-tidy -config='UseColor: true' -dump-config | FileCheck -check-prefix=CHECK-CONFIG-COLOR %s +// RUN: clang-tidy -config='UseColor: 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 -use-color=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 -use-color %s | FileCheck -check-prefix=CHECK-COLOR %s + +// CHECK-NOT: UseColor +// CHECK-CONFIG-NO-COLOR: UseColor: false +// CHECK-CONFIG-COLOR: UseColor: true +// CHECK-OPT-PRESENT: --use-color + +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'] + UseColor: false )"); ASSERT_TRUE(!!Options1); llvm::ErrorOr Options2 = parseConfiguration(R"( @@ -85,6 +86,7 @@ User: user2 ExtraArgs: ['arg3', 'arg4'] ExtraArgsBefore: ['arg-before3', 'arg-before4'] + UseColor: 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.UseColor.hasValue()); + EXPECT_TRUE(*Options.UseColor); } class TestCheck : public ClangTidyCheck {