diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index 364beef55..0340d7277 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -116,7 +116,7 @@ public: /** * @brief Write the checkers report */ - void writeCheckersReport() const; + void writeCheckersReport(); bool hasCriticalErrors() const { return !mCriticalErrors.empty(); @@ -286,12 +286,13 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck) const cppcheck.tooManyConfigsError(emptyString,0U); } + if (settings.safety || settings.severity.isEnabled(Severity::information) || !settings.checkersReportFilename.empty()) + mStdLogger->writeCheckersReport(); + if (settings.xml) { mStdLogger->reportErr(ErrorMessage::getXMLFooter()); } - mStdLogger->writeCheckersReport(); - if (settings.safety && mStdLogger->hasCriticalErrors()) return EXIT_FAILURE; @@ -300,28 +301,39 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck) const return EXIT_SUCCESS; } -void CppCheckExecutor::StdLogger::writeCheckersReport() const +void CppCheckExecutor::StdLogger::writeCheckersReport() { CheckersReport checkersReport(mSettings, mActiveCheckers); - if (!mSettings.quiet) { + bool suppressed = false; + for (const Suppressions::Suppression& s : mSettings.nomsg.getSuppressions()) { + if (s.errorId == "checkersReport") + suppressed = true; + } + + if (!suppressed) { + ErrorMessage msg; + msg.severity = Severity::information; + msg.id = "checkersReport"; + const int activeCheckers = checkersReport.getActiveCheckersCount(); const int totalCheckers = checkersReport.getAllCheckersCount(); - const std::string extra = mSettings.verbose ? " (use --checkers-report= to see details)" : ""; + std::string what; if (mCriticalErrors.empty()) - std::cout << "Active checkers: " << activeCheckers << "/" << totalCheckers << extra << std::endl; + what = std::to_string(activeCheckers) + "/" + std::to_string(totalCheckers); else - std::cout << "Active checkers: There was critical errors" << extra << std::endl; + what = "There was critical errors"; + msg.setmsg("Active checkers: " + what + " (use --checkers-report= to see details)"); + + reportErr(msg); } - if (mSettings.checkersReportFilename.empty()) - return; - - std::ofstream fout(mSettings.checkersReportFilename); - if (fout.is_open()) - fout << checkersReport.getReport(mCriticalErrors); - + if (!mSettings.checkersReportFilename.empty()) { + std::ofstream fout(mSettings.checkersReportFilename); + if (fout.is_open()) + fout << checkersReport.getReport(mCriticalErrors); + } } #ifdef _WIN32 diff --git a/lib/suppressions.cpp b/lib/suppressions.cpp index e5f4e7b47..d13ba5705 100644 --- a/lib/suppressions.cpp +++ b/lib/suppressions.cpp @@ -35,6 +35,9 @@ #include "xml.h" +static const char ID_UNUSEDFUNCTION[] = "unusedFunction"; +static const char ID_CHECKERSREPORT[] = "checkersReport"; + Suppressions::ErrorMessage Suppressions::ErrorMessage::fromErrorMessage(const ::ErrorMessage &msg, const std::set ¯oNames) { Suppressions::ErrorMessage ret; @@ -468,7 +471,9 @@ std::list Suppressions::getUnmatchedLocalSuppressions continue; if (s.hash > 0) continue; - if (!unusedFunctionChecking && s.errorId == "unusedFunction") + if (s.errorId == ID_CHECKERSREPORT) + continue; + if (!unusedFunctionChecking && s.errorId == ID_UNUSEDFUNCTION) continue; if (tmpFile.empty() || !s.isLocal() || s.fileName != tmpFile) continue; @@ -485,7 +490,9 @@ std::list Suppressions::getUnmatchedGlobalSuppression continue; if (s.hash > 0) continue; - if (!unusedFunctionChecking && s.errorId == "unusedFunction") + if (!unusedFunctionChecking && s.errorId == ID_UNUSEDFUNCTION) + continue; + if (s.errorId == ID_CHECKERSREPORT) continue; if (s.isLocal()) continue; diff --git a/releasenotes.txt b/releasenotes.txt index 41295d325..593f61498 100644 --- a/releasenotes.txt +++ b/releasenotes.txt @@ -12,7 +12,7 @@ GUI: - Changed interface: -- +- Final report of active checkers is reported as a normal information message instead. Deprecations: - "--showtime=top5" has been deprecated and will be removed in Cppcheck 2.14. Please use --showtime=top5_file or --showtime=top5_summary instead. @@ -44,6 +44,3 @@ Other: - Markup files will now be processed after the regular source files when using multiple threads/processes (some issues remain - see Trac #12167 for details). - Added file name to ValueFlow "--debug" output. - Fixed build when using "clang-cl" in CMake. - -Safety critical fixes: -- Added "--safety" option. It makes Cppcheck more strict about critical errors. diff --git a/test/cli/test-suppress-syntaxError.py b/test/cli/test-suppress-syntaxError.py index b2293bc84..3c77ba5b8 100644 --- a/test/cli/test-suppress-syntaxError.py +++ b/test/cli/test-suppress-syntaxError.py @@ -14,14 +14,14 @@ def test_j2_suppress(): assert len(stderr) == 0 def test_safety_suppress_syntax_error_implicitly(tmpdir): - ret, stdout, stderr = cppcheck(['--safety', '--suppress=*', 'proj-suppress-syntaxError'], remove_active_checkers=False) + ret, stdout, stderr = cppcheck(['--safety', '--suppress=*', 'proj-suppress-syntaxError'], remove_checkers_report=False) assert ret == 1 assert '[syntaxError]' in stderr - assert 'Active checkers: There was critical errors' in stdout + assert 'Active checkers: There was critical errors' in stderr def test_safety_suppress_syntax_error_explicitly(): - ret, stdout, stderr = cppcheck(['--safety', '--suppress=syntaxError', 'proj-suppress-syntaxError'], remove_active_checkers=False) + ret, stdout, stderr = cppcheck(['--safety', '--suppress=syntaxError', 'proj-suppress-syntaxError'], remove_checkers_report=False) assert ret == 1 assert '[syntaxError]' not in stderr - assert 'Active checkers: There was critical errors' in stdout + assert 'Active checkers: There was critical errors' in stderr diff --git a/test/cli/testutils.py b/test/cli/testutils.py index dd529e1b6..a27900a0e 100644 --- a/test/cli/testutils.py +++ b/test/cli/testutils.py @@ -71,7 +71,7 @@ def __lookup_cppcheck_exe(): # Run Cppcheck with args -def cppcheck(args, env=None, remove_active_checkers=True): +def cppcheck(args, env=None, remove_checkers_report=True): exe = __lookup_cppcheck_exe() assert exe is not None, 'no cppcheck binary found' @@ -80,8 +80,20 @@ def cppcheck(args, env=None, remove_active_checkers=True): comm = p.communicate() stdout = comm[0].decode(encoding='utf-8', errors='ignore').replace('\r\n', '\n') stderr = comm[1].decode(encoding='utf-8', errors='ignore').replace('\r\n', '\n') - if remove_active_checkers and stdout.find('\nActive checkers:') > 0: - stdout = stdout[:1 + stdout.find('\nActive checkers:')] + if remove_checkers_report: + if stderr.find('[checkersReport]\n') > 0: + start_id = stderr.find('[checkersReport]\n') + start_line = stderr.rfind('\n', 0, start_id) + if start_line <= 0: + stderr = '' + else: + stderr = stderr[:start_line + 1] + elif stderr.find(': (information) Active checkers: ') >= 0: + pos = stderr.find(': (information) Active checkers: ') + if pos == 0: + stderr = '' + elif stderr[pos - 1] == '\n': + stderr = stderr[:pos] return p.returncode, stdout, stderr