Index: clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp =================================================================== --- clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp +++ clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp @@ -448,10 +448,9 @@ runClangTidy(Context, OptionsParser.getCompilations(), PathList, BaseFS, EnableCheckProfile ? &Profile : nullptr); ArrayRef Errors = Context.getErrors(); - bool FoundErrors = - std::find_if(Errors.begin(), Errors.end(), [](const ClangTidyError &E) { - return E.DiagLevel == ClangTidyError::Error; - }) != Errors.end(); + bool FoundErrors = llvm::find_if(Errors, [](const ClangTidyError &E) { + return E.DiagLevel == ClangTidyError::Error; + }) != Errors.end(); const bool DisableFixes = Fix && FoundErrors && !FixErrors; @@ -491,6 +490,19 @@ return WErrorCount; } + if (FoundErrors) { + // TODO: Figure out when zero exit code should be used with -fix-errors: + // a. when a fix has been applied for an error + // b. when a fix has been applied for all errors + // c. some other condition. + // For now always returning zero when -fix-errors is used. + if (FixErrors) + return 0; + if (!Quiet) + llvm::errs() << "Found compiler error(s).\n"; + return 1; + } + return 0; } Index: clang-tools-extra/trunk/test/clang-tidy/bugprone-suspicious-semicolon-fail.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/bugprone-suspicious-semicolon-fail.cpp +++ clang-tools-extra/trunk/test/clang-tidy/bugprone-suspicious-semicolon-fail.cpp @@ -1,7 +1,9 @@ -// RUN: clang-tidy %s -checks="-*,bugprone-suspicious-semicolon" -- -DERROR 2>&1 \ +// RUN: not clang-tidy %s \ +// RUN: -checks="-*,bugprone-suspicious-semicolon" -- -DERROR 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-ERROR \ // RUN: -implicit-check-not="{{warning|error}}:" -// RUN: clang-tidy %s -checks="-*,bugprone-suspicious-semicolon,clang-diagnostic*" \ +// RUN: not clang-tidy %s \ +// RUN: -checks="-*,bugprone-suspicious-semicolon,clang-diagnostic*" \ // RUN: -- -DWERROR -Wno-everything -Werror=unused-variable 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-WERROR \ // RUN: -implicit-check-not="{{warning|error}}:" Index: clang-tools-extra/trunk/test/clang-tidy/check_clang_tidy.py =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/check_clang_tidy.py +++ clang-tools-extra/trunk/test/clang-tidy/check_clang_tidy.py @@ -39,6 +39,7 @@ def main(): parser = argparse.ArgumentParser() + parser.add_argument('-expect-clang-tidy-error', action='store_true') parser.add_argument('-resource-dir') parser.add_argument('-assume-filename') parser.add_argument('input_file_name') @@ -52,6 +53,7 @@ input_file_name = args.input_file_name check_name = args.check_name temp_file_name = args.temp_file_name + expect_clang_tidy_error = args.expect_clang_tidy_error file_name_with_extension = assume_file_name or input_file_name _, extension = os.path.splitext(file_name_with_extension) @@ -97,6 +99,8 @@ args = ['clang-tidy', temp_file_name, '-fix', '--checks=-*,' + check_name] + \ clang_tidy_extra_args + if expect_clang_tidy_error: + args.insert(0, 'not') print('Running ' + repr(args) + '...') try: clang_tidy_output = \ Index: clang-tools-extra/trunk/test/clang-tidy/diagnostic.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/diagnostic.cpp +++ clang-tools-extra/trunk/test/clang-tidy/diagnostic.cpp @@ -1,13 +1,15 @@ -// RUN: clang-tidy -checks='-*,modernize-use-override' %s.nonexistent.cpp -- | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s -// RUN: clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %s -- -fan-unknown-option | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s -// RUN: clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %s -- -fan-unknown-option | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s +// RUN: not clang-tidy -checks='-*,modernize-use-override' %s.nonexistent.cpp -- | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s +// RUN: not clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %s -- -fan-unknown-option | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s +// RUN: not clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %s -- -fan-unknown-option | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s // RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %s -- -DMACRO_FROM_COMMAND_LINE | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s +// RUN: not clang-tidy -checks='-*,modernize-use-override' %s -- -DCOMPILATION_ERROR | FileCheck -check-prefix=CHECK6 -implicit-check-not='{{warning:|error:}}' %s // // Now repeat the tests and ensure no other errors appear on stderr: -// RUN: clang-tidy -checks='-*,modernize-use-override' %s.nonexistent.cpp -- 2>&1 | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s -// RUN: clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %s -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s -// RUN: clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %s -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s +// RUN: not clang-tidy -checks='-*,modernize-use-override' %s.nonexistent.cpp -- 2>&1 | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s +// RUN: not clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %s -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s +// RUN: not clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %s -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s // RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %s -- -DMACRO_FROM_COMMAND_LINE 2>&1 | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s +// RUN: not clang-tidy -checks='-*,modernize-use-override' %s -- -DCOMPILATION_ERROR 2>&1 | FileCheck -check-prefix=CHECK6 -implicit-check-not='{{warning:|error:}}' %s // // Now create a directory with a compilation database file and ensure we don't // use it after failing to parse commands from the command line: @@ -15,11 +17,12 @@ // RUN: mkdir -p %T/diagnostics/ // RUN: echo '[{"directory": "%/T/diagnostics/","command": "clang++ -fan-option-from-compilation-database -c %/T/diagnostics/input.cpp", "file": "%/T/diagnostics/input.cpp"}]' > %T/diagnostics/compile_commands.json // RUN: cat %s > %T/diagnostics/input.cpp -// RUN: clang-tidy -checks='-*,modernize-use-override' %T/diagnostics/nonexistent.cpp -- 2>&1 | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s -// RUN: clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %T/diagnostics/input.cpp -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s -// RUN: clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %T/diagnostics/input.cpp -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s +// RUN: not clang-tidy -checks='-*,modernize-use-override' %T/diagnostics/nonexistent.cpp -- 2>&1 | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s +// RUN: not clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %T/diagnostics/input.cpp -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s +// RUN: not clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %T/diagnostics/input.cpp -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s // RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %T/diagnostics/input.cpp -- -DMACRO_FROM_COMMAND_LINE 2>&1 | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s -// RUN: clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %T/diagnostics/input.cpp 2>&1 | FileCheck -check-prefix=CHECK5 -implicit-check-not='{{warning:|error:}}' %s +// RUN: not clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %T/diagnostics/input.cpp 2>&1 | FileCheck -check-prefix=CHECK5 -implicit-check-not='{{warning:|error:}}' %s +// RUN: not clang-tidy -checks='-*,modernize-use-override' %T/diagnostics/input.cpp -- -DCOMPILATION_ERROR 2>&1 | FileCheck -check-prefix=CHECK6 -implicit-check-not='{{warning:|error:}}' %s // CHECK1: error: error reading '{{.*}}nonexistent.cpp' [clang-diagnostic-error] // CHECK2: error: unknown argument: '-fan-unknown-option' [clang-diagnostic-error] @@ -38,3 +41,10 @@ #define MACRO_FROM_COMMAND_LINE // CHECK4: :[[@LINE-1]]:9: warning: 'MACRO_FROM_COMMAND_LINE' macro redefined + +#ifdef COMPILATION_ERROR +void f(int a) { + &(a + 1); + // CHECK6: :[[@LINE-1]]:3: error: cannot take the address of an rvalue of type 'int' [clang-diagnostic-error] +} +#endif Index: clang-tools-extra/trunk/test/clang-tidy/fix-errors.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/fix-errors.cpp +++ clang-tools-extra/trunk/test/clang-tidy/fix-errors.cpp @@ -1,5 +1,5 @@ // RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp -// RUN: clang-tidy %t.cpp -checks='-*,google-explicit-constructor' -fix -- > %t.msg 2>&1 +// RUN: not clang-tidy %t.cpp -checks='-*,google-explicit-constructor' -fix -- > %t.msg 2>&1 // RUN: FileCheck -input-file=%t.cpp -check-prefix=CHECK-FIX %s // RUN: FileCheck -input-file=%t.msg -check-prefix=CHECK-MESSAGES %s // RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp Index: clang-tools-extra/trunk/test/clang-tidy/misc-misplaced-const-cxx17.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/misc-misplaced-const-cxx17.cpp +++ clang-tools-extra/trunk/test/clang-tidy/misc-misplaced-const-cxx17.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s misc-misplaced-const %t -- -- -std=c++17 +// RUN: %check_clang_tidy -expect-clang-tidy-error %s misc-misplaced-const %t -- -- -std=c++17 // This test previously would cause a failed assertion because the structured // binding declaration had no valid type associated with it. This ensures the Index: clang-tools-extra/trunk/test/clang-tidy/misc-unused-using-decls-errors.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/misc-unused-using-decls-errors.cpp +++ clang-tools-extra/trunk/test/clang-tidy/misc-unused-using-decls-errors.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s misc-unused-using-decls %t +// RUN: %check_clang_tidy -expect-clang-tidy-error %s misc-unused-using-decls %t namespace n { class C; Index: clang-tools-extra/trunk/test/clang-tidy/modernize-loop-convert-assert-failure.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/modernize-loop-convert-assert-failure.cpp +++ clang-tools-extra/trunk/test/clang-tidy/modernize-loop-convert-assert-failure.cpp @@ -1,4 +1,4 @@ -// RUN: clang-tidy %s -checks=-*,modernize-loop-convert -- +// RUN: not clang-tidy %s -checks=-*,modernize-loop-convert -- // Note: this test expects no assert failure happened in clang-tidy. Index: clang-tools-extra/trunk/test/clang-tidy/readability-braces-around-statements-assert-failure.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/readability-braces-around-statements-assert-failure.cpp +++ clang-tools-extra/trunk/test/clang-tidy/readability-braces-around-statements-assert-failure.cpp @@ -1,4 +1,4 @@ -// RUN: clang-tidy -checks='-*,readability-braces-around-statements' %s -- +// RUN: not clang-tidy -checks='-*,readability-braces-around-statements' %s -- // Note: this test expects no assert failure happened in clang-tidy. Index: clang-tools-extra/trunk/test/clang-tidy/serialize-diagnostics.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/serialize-diagnostics.cpp +++ clang-tools-extra/trunk/test/clang-tidy/serialize-diagnostics.cpp @@ -1,3 +1,3 @@ -// RUN: clang-tidy -checks=-*,llvm-namespace-comment %s -- -serialize-diagnostics %t | FileCheck %s +// RUN: not clang-tidy -checks=-*,llvm-namespace-comment %s -- -serialize-diagnostics %t | FileCheck %s // CHECK: :[[@LINE+1]]:12: error: expected ';' after struct [clang-diagnostic-error] struct A {}