diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 999180f84dd..50f9a716b24 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -1609,11 +1609,22 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a if (mSettings.jobs > 1 && mSettings.buildDir.empty()) { // TODO: bail out instead? if (mSettings.checks.isEnabled(Checks::unusedFunction)) + { mLogger.printMessage("unusedFunction check requires --cppcheck-build-dir to be active with -j."); + mSettings.checks.disable(Checks::unusedFunction); + // TODO: is there some later logic to remove? + } // TODO: enable //mLogger.printMessage("whole program analysis requires --cppcheck-build-dir to be active with -j."); } + if (!mSettings.checks.isEnabled(Checks::unusedFunction)) + mSettings.unmatchedSuppressionFilters.emplace_back("unusedFunction"); + if (!mSettings.addons.count("misra")) + mSettings.unmatchedSuppressionFilters.emplace_back("misra-*"); + if (!mSettings.premium) + mSettings.unmatchedSuppressionFilters.emplace_back("premium-*"); + if (inputAsFilter) { mSettings.fileFilters.insert(mSettings.fileFilters.end(), mPathNames.cbegin(), mPathNames.cend()); mPathNames.clear(); diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index acac0b5f8cd..54d83ee4789 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -293,35 +293,73 @@ int CppCheckExecutor::check_wrapper(const Settings& settings, Suppressions& supp return check_internal(settings, supprs); } -bool CppCheckExecutor::reportSuppressions(const Settings &settings, const SuppressionList& suppressions, bool unusedFunctionCheckEnabled, const std::list &files, const std::list& fileSettings, ErrorLogger& errorLogger) { - const auto& suppr = suppressions.getSuppressions(); - if (std::any_of(suppr.begin(), suppr.end(), [](const SuppressionList::Suppression& s) { - return s.errorId == "unmatchedSuppression" && s.fileName.empty() && s.lineNumber == SuppressionList::Suppression::NO_LINE; +/** + * Report unmatched suppressions + * @param unmatched list of unmatched suppressions (from Settings::Suppressions::getUnmatched(Local|Global)Suppressions) + * @return true is returned if errors are reported + */ +static bool reportUnmatchedSuppressions(const std::list &unmatched, ErrorLogger &errorLogger, const std::vector& filters) +{ + bool err = false; + // Report unmatched suppressions + for (const SuppressionList::Suppression &s : unmatched) { + // check if this unmatched suppression is suppressed + bool suppressed = false; + for (const SuppressionList::Suppression &s2 : unmatched) { + if (s2.errorId == "unmatchedSuppression") { + if ((s2.fileName.empty() || s2.fileName == "*" || s2.fileName == s.fileName) && + (s2.lineNumber == SuppressionList::Suppression::NO_LINE || s2.lineNumber == s.lineNumber)) { + suppressed = true; + break; + } + } + } + + if (suppressed) + continue; + + const bool skip = std::any_of(filters.cbegin(), filters.cend(), [&s](const std::string& filter) { + return matchglob(filter, s.errorId); + }); + if (skip) + continue; + + std::list<::ErrorMessage::FileLocation> callStack; + if (!s.fileName.empty()) { + callStack.emplace_back(s.fileName, s.lineNumber, 0); + } + errorLogger.reportErr(::ErrorMessage(std::move(callStack), "", Severity::information, "Unmatched suppression: " + s.errorId, "unmatchedSuppression", Certainty::normal)); + err = true; + } + return err; +} + +bool CppCheckExecutor::reportUnmatchedSuppressions(const Settings &settings, const SuppressionList& suppressions, const std::list &files, const std::list& fileSettings, ErrorLogger& errorLogger) { + // the two inputs may only be used exclusively + assert(!(!files.empty() && !fileSettings.empty())); + + // bail out if there is a suppression of unmatchedSuppression which matches any file + const auto suppr = suppressions.getSuppressions(); + if (std::any_of(suppr.cbegin(), suppr.cend(), [](const SuppressionList::Suppression& s) { + return s.errorId == "unmatchedSuppression" && (s.fileName.empty() || s.fileName == "*") && s.lineNumber == SuppressionList::Suppression::NO_LINE; })) return false; bool err = false; - if (settings.useSingleJob()) { - // the two inputs may only be used exclusively - assert(!(!files.empty() && !fileSettings.empty())); - for (auto i = files.cbegin(); i != files.cend(); ++i) { - err |= SuppressionList::reportUnmatchedSuppressions( - suppressions.getUnmatchedLocalSuppressions(*i, unusedFunctionCheckEnabled), errorLogger); - } + for (auto i = files.cbegin(); i != files.cend(); ++i) { + err |= ::reportUnmatchedSuppressions(suppressions.getUnmatchedLocalSuppressions(*i), errorLogger, settings.unmatchedSuppressionFilters); + } - for (auto i = fileSettings.cbegin(); i != fileSettings.cend(); ++i) { - err |= SuppressionList::reportUnmatchedSuppressions( - suppressions.getUnmatchedLocalSuppressions(i->file, unusedFunctionCheckEnabled), errorLogger); - } + for (auto i = fileSettings.cbegin(); i != fileSettings.cend(); ++i) { + err |= ::reportUnmatchedSuppressions(suppressions.getUnmatchedLocalSuppressions(i->file), errorLogger, settings.unmatchedSuppressionFilters); } + if (settings.inlineSuppressions) { - // report unmatched unusedFunction suppressions - err |= SuppressionList::reportUnmatchedSuppressions( - suppressions.getUnmatchedInlineSuppressions(unusedFunctionCheckEnabled), errorLogger); + err |= ::reportUnmatchedSuppressions(suppressions.getUnmatchedInlineSuppressions(), errorLogger, settings.unmatchedSuppressionFilters); } - err |= SuppressionList::reportUnmatchedSuppressions(suppressions.getUnmatchedGlobalSuppressions(unusedFunctionCheckEnabled), errorLogger); + err |= ::reportUnmatchedSuppressions(suppressions.getUnmatchedGlobalSuppressions(), errorLogger, settings.unmatchedSuppressionFilters); return err; } @@ -376,7 +414,7 @@ int CppCheckExecutor::check_internal(const Settings& settings, Suppressions& sup returnValue |= cppcheck.analyseWholeProgram(settings.buildDir, mFiles, mFileSettings, stdLogger.getCtuInfo()); if (settings.severity.isEnabled(Severity::information) || settings.checkConfiguration) { - const bool err = reportSuppressions(settings, supprs.nomsg, settings.checks.isEnabled(Checks::unusedFunction), mFiles, mFileSettings, stdLogger); + const bool err = reportUnmatchedSuppressions(settings, supprs.nomsg, mFiles, mFileSettings, stdLogger); if (err && returnValue == 0) returnValue = settings.exitCode; } diff --git a/cli/cppcheckexecutor.h b/cli/cppcheckexecutor.h index 9c8b6707b64..5ef743ef20d 100644 --- a/cli/cppcheckexecutor.h +++ b/cli/cppcheckexecutor.h @@ -70,7 +70,7 @@ class CppCheckExecutor { protected: - static bool reportSuppressions(const Settings &settings, const SuppressionList& suppressions, bool unusedFunctionCheckEnabled, const std::list &files, const std::list& fileSettings, ErrorLogger& errorLogger); + static bool reportUnmatchedSuppressions(const Settings &settings, const SuppressionList& suppressions, const std::list &files, const std::list& fileSettings, ErrorLogger& errorLogger); /** * Wrapper around check_internal diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 9c411a8b0af..e81f4ee44d2 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -1299,16 +1299,6 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str mErrorLogger.reportErr(errmsg); } - // TODO: this is done too early causing the whole program analysis suppressions to be reported as unmatched - if (mSettings.severity.isEnabled(Severity::information) || mSettings.checkConfiguration) { - // In jointSuppressionReport mode, unmatched suppressions are - // collected after all files are processed - if (!mSettings.useSingleJob()) { - // TODO: check result? - SuppressionList::reportUnmatchedSuppressions(mSuppressions.nomsg.getUnmatchedLocalSuppressions(file, static_cast(mUnusedFunctionsCheck)), mErrorLogger); - } - } - if (analyzerInformation) { mLogger->setAnalyzerInfo(nullptr); analyzerInformation.reset(); diff --git a/lib/settings.h b/lib/settings.h index 7b773379490..615c2acdf96 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -435,6 +435,9 @@ class CPPCHECKLIB WARN_UNUSED Settings { /** @brief The maximum time in seconds for the typedef simplification */ std::size_t typedefMaxTime{}; + /** @brief Error IDs which should not be reported as unmatchedSuppression */ + std::vector unmatchedSuppressionFilters; + /** @brief defines given by the user */ std::string userDefines; diff --git a/lib/suppressions.cpp b/lib/suppressions.cpp index a7c30580700..162de168cb6 100644 --- a/lib/suppressions.cpp +++ b/lib/suppressions.cpp @@ -37,7 +37,6 @@ #include "xml.h" -static const char ID_UNUSEDFUNCTION[] = "unusedFunction"; static const char ID_CHECKERSREPORT[] = "checkersReport"; SuppressionList::ErrorMessage SuppressionList::ErrorMessage::fromErrorMessage(const ::ErrorMessage &msg, const std::set ¯oNames) @@ -312,13 +311,10 @@ bool SuppressionList::updateSuppressionState(const SuppressionList::Suppression& auto foundSuppression = std::find_if(mSuppressions.begin(), mSuppressions.end(), std::bind(&Suppression::isSameParameters, &suppression, std::placeholders::_1)); if (foundSuppression != mSuppressions.end()) { - // Update state of existing global suppression - if (!suppression.isLocal()) { - if (suppression.checked) - foundSuppression->checked = true; - if (suppression.matched) - foundSuppression->matched = true; - } + if (suppression.checked) + foundSuppression->checked = true; + if (suppression.matched) + foundSuppression->matched = true; return true; } @@ -555,7 +551,7 @@ void SuppressionList::dump(std::ostream & out, const std::string& filePath) cons out << " " << std::endl; } -std::list SuppressionList::getUnmatchedLocalSuppressions(const FileWithDetails &file, const bool includeUnusedFunction) const +std::list SuppressionList::getUnmatchedLocalSuppressions(const FileWithDetails &file) const { std::lock_guard lg(mSuppressionsSync); @@ -573,8 +569,6 @@ std::list SuppressionList::getUnmatchedLocalSuppre continue; if (s.errorId == ID_CHECKERSREPORT) continue; - if (!includeUnusedFunction && s.errorId == ID_UNUSEDFUNCTION) - continue; if (!s.isLocal() || s.fileName != file.spath()) continue; result.push_back(s); @@ -582,7 +576,7 @@ std::list SuppressionList::getUnmatchedLocalSuppre return result; } -std::list SuppressionList::getUnmatchedGlobalSuppressions(const bool includeUnusedFunction) const +std::list SuppressionList::getUnmatchedGlobalSuppressions() const { std::lock_guard lg(mSuppressionsSync); @@ -596,8 +590,6 @@ std::list SuppressionList::getUnmatchedGlobalSuppr continue; if (s.hash > 0) continue; - if (!includeUnusedFunction && s.errorId == ID_UNUSEDFUNCTION) - continue; if (s.errorId == ID_CHECKERSREPORT) continue; if (s.isLocal()) @@ -607,7 +599,7 @@ std::list SuppressionList::getUnmatchedGlobalSuppr return result; } -std::list SuppressionList::getUnmatchedInlineSuppressions(const bool includeUnusedFunction) const +std::list SuppressionList::getUnmatchedInlineSuppressions() const { std::list result; for (const SuppressionList::Suppression &s : SuppressionList::mSuppressions) { @@ -620,8 +612,6 @@ std::list SuppressionList::getUnmatchedInlineSuppr continue; if (s.hash > 0) continue; - if (!includeUnusedFunction && s.errorId == ID_UNUSEDFUNCTION) - continue; result.push_back(s); } return result; @@ -660,39 +650,6 @@ void SuppressionList::markUnmatchedInlineSuppressionsAsChecked(const Tokenizer & } } -bool SuppressionList::reportUnmatchedSuppressions(const std::list &unmatched, ErrorLogger &errorLogger) -{ - bool err = false; - // Report unmatched suppressions - for (const SuppressionList::Suppression &s : unmatched) { - // don't report "unmatchedSuppression" as unmatched - if (s.errorId == "unmatchedSuppression") - continue; - - // check if this unmatched suppression is suppressed - bool suppressed = false; - for (const SuppressionList::Suppression &s2 : unmatched) { - if (s2.errorId == "unmatchedSuppression") { - if ((s2.fileName.empty() || s2.fileName == "*" || s2.fileName == s.fileName) && - (s2.lineNumber == SuppressionList::Suppression::NO_LINE || s2.lineNumber == s.lineNumber)) { - suppressed = true; - break; - } - } - } - - if (suppressed) - continue; - - std::list<::ErrorMessage::FileLocation> callStack; - if (!s.fileName.empty()) - callStack.emplace_back(s.fileName, s.lineNumber, 0); - errorLogger.reportErr(::ErrorMessage(std::move(callStack), "", Severity::information, "Unmatched suppression: " + s.errorId, "unmatchedSuppression", Certainty::normal)); - err = true; - } - return err; -} - std::string SuppressionList::Suppression::toString() const { std::string s; diff --git a/lib/suppressions.h b/lib/suppressions.h index 84e2bc2cb6e..8b6776560b4 100644 --- a/lib/suppressions.h +++ b/lib/suppressions.h @@ -34,7 +34,6 @@ class Tokenizer; class ErrorMessage; -class ErrorLogger; enum class Certainty : std::uint8_t; class FileWithDetails; @@ -258,19 +257,19 @@ class CPPCHECKLIB SuppressionList { * @brief Returns list of unmatched local (per-file) suppressions. * @return list of unmatched suppressions */ - std::list getUnmatchedLocalSuppressions(const FileWithDetails &file, bool includeUnusedFunction) const; + std::list getUnmatchedLocalSuppressions(const FileWithDetails &file) const; /** * @brief Returns list of unmatched global (glob pattern) suppressions. * @return list of unmatched suppressions */ - std::list getUnmatchedGlobalSuppressions(bool includeUnusedFunction) const; + std::list getUnmatchedGlobalSuppressions() const; /** * @brief Returns list of unmatched inline suppressions. * @return list of unmatched suppressions */ - std::list getUnmatchedInlineSuppressions(bool includeUnusedFunction) const; + std::list getUnmatchedInlineSuppressions() const; /** * @brief Returns list of all suppressions. @@ -283,13 +282,6 @@ class CPPCHECKLIB SuppressionList { */ void markUnmatchedInlineSuppressionsAsChecked(const Tokenizer &tokenizer); - /** - * Report unmatched suppressions - * @param unmatched list of unmatched suppressions (from Settings::Suppressions::getUnmatched(Local|Global)Suppressions) - * @return true is returned if errors are reported - */ - static bool reportUnmatchedSuppressions(const std::list &unmatched, ErrorLogger &errorLogger); - private: mutable std::mutex mSuppressionsSync; /** @brief List of error which the user doesn't want to see. */ diff --git a/test/cli/inline-suppress_test.py b/test/cli/inline-suppress_test.py index ce3b68768cf..7b8be839df4 100644 --- a/test/cli/inline-suppress_test.py +++ b/test/cli/inline-suppress_test.py @@ -501,3 +501,60 @@ def test_unmatched_cfg(): ] assert stdout == '' assert ret == 0, stdout + + +# do not report unmatched unusedFunction inline suppressions when unusedFunction check is disabled +# unusedFunction is disabled when -j2 is specified without a builddir +def test_unused_function_disabled_unmatched_j(): + args = [ + '-q', + '--template=simple', + '--enable=warning,information', + '--inline-suppr', + '-j2', + '--no-cppcheck-build-dir', + 'proj-inline-suppress/unusedFunctionUnmatched.cpp' + ] + + ret, stdout, stderr = cppcheck(args, cwd=__script_dir) + assert stderr.splitlines() == [ + '{}unusedFunctionUnmatched.cpp:5:0: information: Unmatched suppression: uninitvar [unmatchedSuppression]'.format(__proj_inline_suppres_path) + ] + assert stdout == '' + assert ret == 0, stdout + + +# do not report unmatched misra-* inline suppressions when misra is not provided +def test_misra_disabled_unmatched(): #14232 + args = [ + '-q', + '--template=simple', + '--enable=warning,information', + '--inline-suppr', + 'proj-inline-suppress/misraUnmatched.c' + ] + + ret, stdout, stderr = cppcheck(args, cwd=__script_dir) + assert stderr.splitlines() == [ + '{}misraUnmatched.c:5:0: information: Unmatched suppression: uninitvar [unmatchedSuppression]'.format(__proj_inline_suppres_path) + ] + assert stdout == '' + assert ret == 0, stdout + + +# do not report unmatched premium-* inline suppressions when application is not premium +def test_premium_disabled_unmatched(): #13663 + args = [ + '-q', + '--template=simple', + '--enable=warning,information', + '--inline-suppr', + 'proj-inline-suppress/premiumUnmatched.cpp' + ] + + ret, stdout, stderr = cppcheck(args, cwd=__script_dir) + assert stderr.splitlines() == [ + '{}premiumUnmatched.cpp:5:0: information: Unmatched suppression: uninitvar [unmatchedSuppression]'.format(__proj_inline_suppres_path) + ] + assert stdout == '' + assert ret == 0, stdout \ No newline at end of file diff --git a/test/cli/other_test.py b/test/cli/other_test.py index 4af6eb66cf9..95fd81871a5 100644 --- a/test/cli/other_test.py +++ b/test/cli/other_test.py @@ -3751,4 +3751,50 @@ def test_ast_max_depth(tmp_path): assert stdout.splitlines() == [] assert stderr.splitlines() == [ '{}:12:5: error: maximum AST depth exceeded [internalAstError]'.format(test_file) - ] \ No newline at end of file + ] + + +# do not report unmatched misra-* suppressions when misra is not provided +def test_misra_disabled_unmatched(tmp_path): #14232 + test_file = tmp_path / 'test.c' + with open(test_file, "w"): + pass + + args = [ + '-q', + '--template=simple', + '--enable=warning,information', + '--suppress=misra-c2012-20.5', + '--suppress=uninitvar', + str(test_file) + ] + + ret, stdout, stderr = cppcheck(args) + assert stderr.splitlines() == [ + 'nofile:0:0: information: Unmatched suppression: uninitvar [unmatchedSuppression]' + ] + assert stdout == '' + assert ret == 0, stdout + + +# do not report unmatched premium-* suppressions when application is not premium +def test_premium_disabled_unmatched(tmp_path): #13663 + test_file = tmp_path / 'test.c' + with open(test_file, "w"): + pass + + args = [ + '-q', + '--template=simple', + '--enable=warning,information', + '--suppress=premium-misra-cpp-2023-12.2.1', + '--suppress=uninitvar', + str(test_file) + ] + + ret, stdout, stderr = cppcheck(args) + assert stderr.splitlines() == [ + 'nofile:0:0: information: Unmatched suppression: uninitvar [unmatchedSuppression]' + ] + assert stdout == '' + assert ret == 0, stdout \ No newline at end of file diff --git a/test/cli/proj-inline-suppress/misraUnmatched.c b/test/cli/proj-inline-suppress/misraUnmatched.c new file mode 100644 index 00000000000..93c81febbbc --- /dev/null +++ b/test/cli/proj-inline-suppress/misraUnmatched.c @@ -0,0 +1,5 @@ +void f() +{ + // cppcheck-suppress misra-c2012-20.5 + // cppcheck-suppress uninitvar +} \ No newline at end of file diff --git a/test/cli/proj-inline-suppress/premiumUnmatched.cpp b/test/cli/proj-inline-suppress/premiumUnmatched.cpp new file mode 100644 index 00000000000..3be3c1369a7 --- /dev/null +++ b/test/cli/proj-inline-suppress/premiumUnmatched.cpp @@ -0,0 +1,5 @@ +void f() +{ + // cppcheck-suppress premium-misra-cpp-2023-12.2.1 + // cppcheck-suppress uninitvar +} \ No newline at end of file diff --git a/test/testsuppressions.cpp b/test/testsuppressions.cpp index 7c00ed91dfd..eabfbe7b9e2 100644 --- a/test/testsuppressions.cpp +++ b/test/testsuppressions.cpp @@ -287,7 +287,7 @@ class TestSuppressions : public TestFixture { SingleExecutor executor(cppCheck, filelist, fileSettings, settings, supprs, *this); unsigned int exitCode = executor.check(); - const bool err = CppCheckExecutor::reportSuppressions(settings, supprs.nomsg, false, filelist, fileSettings, *this); + const bool err = CppCheckExecutor::reportUnmatchedSuppressions(settings, supprs.nomsg, filelist, fileSettings, *this); if (err && exitCode == 0) exitCode = 1; @@ -335,7 +335,7 @@ class TestSuppressions : public TestFixture { ThreadExecutor executor(filelist, fileSettings, settings, supprs, *this, CppCheckExecutor::executeCommand); unsigned int exitCode = executor.check(); - const bool err = CppCheckExecutor::reportSuppressions(settings, supprs.nomsg, false, filelist, fileSettings, *this); + const bool err = CppCheckExecutor::reportUnmatchedSuppressions(settings, supprs.nomsg, filelist, fileSettings, *this); if (err && exitCode == 0) exitCode = 1; @@ -384,7 +384,7 @@ class TestSuppressions : public TestFixture { ProcessExecutor executor(filelist, fileSettings, settings, supprs, *this, CppCheckExecutor::executeCommand); unsigned int exitCode = executor.check(); - const bool err = CppCheckExecutor::reportSuppressions(settings, supprs.nomsg, false, filelist, fileSettings, *this); + const bool err = CppCheckExecutor::reportUnmatchedSuppressions(settings, supprs.nomsg, filelist, fileSettings, *this); if (err && exitCode == 0) exitCode = 1; @@ -392,6 +392,7 @@ class TestSuppressions : public TestFixture { } #endif + // TODO: check all results void runChecks(unsigned int (TestSuppressions::*check)(const char[], const std::string &)) { // check to make sure the appropriate errors are present ASSERT_EQUALS(1, (this->*check)("void f() {\n" @@ -1267,20 +1268,16 @@ class TestSuppressions : public TestFixture { SuppressionList::Suppression suppression("unusedFunction", "test.c", 3); suppression.checked = true; // have to do this because fixes for #5704 ASSERT_EQUALS("", suppressions.addSuppression(std::move(suppression))); - ASSERT_EQUALS(true, !suppressions.getUnmatchedLocalSuppressions(FileWithDetails("test.c", Standards::Language::C, 0), true).empty()); - ASSERT_EQUALS(false, !suppressions.getUnmatchedGlobalSuppressions(true).empty()); - ASSERT_EQUALS(false, !suppressions.getUnmatchedLocalSuppressions(FileWithDetails("test.c", Standards::Language::C, 0), false).empty()); - ASSERT_EQUALS(false, !suppressions.getUnmatchedGlobalSuppressions(false).empty()); + ASSERT_EQUALS(true, !suppressions.getUnmatchedLocalSuppressions(FileWithDetails("test.c", Standards::Language::C, 0)).empty()); + ASSERT_EQUALS(false, !suppressions.getUnmatchedGlobalSuppressions().empty()); } void globalsuppress_unusedFunction() const { // #4946 - wrong report of "unmatchedSuppression" for "unusedFunction" SuppressionList suppressions; ASSERT_EQUALS("", suppressions.addSuppressionLine("unusedFunction:*")); ASSERT_EQUALS(false, suppressions.isSuppressed(errorMessage("errorid"))); - ASSERT_EQUALS(false, !suppressions.getUnmatchedLocalSuppressions(FileWithDetails("test.c", Standards::Language::C, 0), true).empty()); - ASSERT_EQUALS(true, !suppressions.getUnmatchedGlobalSuppressions(true).empty()); - ASSERT_EQUALS(false, !suppressions.getUnmatchedLocalSuppressions(FileWithDetails("test.c", Standards::Language::C, 0), false).empty()); - ASSERT_EQUALS(false, !suppressions.getUnmatchedGlobalSuppressions(false).empty()); + ASSERT_EQUALS(false, !suppressions.getUnmatchedLocalSuppressions(FileWithDetails("test.c", Standards::Language::C, 0)).empty()); + ASSERT_EQUALS(true, !suppressions.getUnmatchedGlobalSuppressions().empty()); } void suppressionWithRelativePaths() { @@ -1471,55 +1468,76 @@ class TestSuppressions : public TestFixture { ASSERT_EQUALS(false, suppressions.isSuppressed(errorMessage("errorid2", "test2.cpp", 1), false)); } + static void addCheckedSuppression(SuppressionList& supprs, SuppressionList::Suppression suppr) + { + suppr.checked = true; + supprs.addSuppression(std::move(suppr)); + } + void suppressUnmatchedSuppressions() { - std::list suppressions; + const std::list files = { {"a.c", Standards::Language::C, 0}}; + const std::list fs; // No unmatched suppression - suppressions.clear(); - ASSERT_EQUALS(false, SuppressionList::reportUnmatchedSuppressions(suppressions, *this)); - ASSERT_EQUALS("", errout_str()); + { + SuppressionList suppressions; + ASSERT_EQUALS(false, CppCheckExecutor::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); + ASSERT_EQUALS("", errout_str()); + } // suppress all unmatchedSuppression - suppressions.clear(); - suppressions.emplace_back("abc", "a.c", 10U); - suppressions.emplace_back("unmatchedSuppression", "*", SuppressionList::Suppression::NO_LINE); - ASSERT_EQUALS(false, SuppressionList::reportUnmatchedSuppressions(suppressions, *this)); - ASSERT_EQUALS("", errout_str()); + { + SuppressionList suppressions; + addCheckedSuppression(suppressions, {"abc", "a.c", 10U}); + addCheckedSuppression(suppressions, {"unmatchedSuppression", "*", SuppressionList::Suppression::NO_LINE}); + ASSERT_EQUALS(false, CppCheckExecutor::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); + ASSERT_EQUALS("", errout_str()); + } // suppress all unmatchedSuppression (corresponds to "--suppress=unmatchedSuppression") - suppressions.clear(); - suppressions.emplace_back("abc", "a.c", 10U); - suppressions.emplace_back("unmatchedSuppression", "", SuppressionList::Suppression::NO_LINE); - ASSERT_EQUALS(false, SuppressionList::reportUnmatchedSuppressions(suppressions, *this)); - ASSERT_EQUALS("", errout_str()); + { + SuppressionList suppressions; + addCheckedSuppression(suppressions, {"abc", "a.c", 10U}); + addCheckedSuppression(suppressions, {"unmatchedSuppression", "", SuppressionList::Suppression::NO_LINE}); + ASSERT_EQUALS(false, CppCheckExecutor::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); + ASSERT_EQUALS("", errout_str()); + } // suppress all unmatchedSuppression in a.c - suppressions.clear(); - suppressions.emplace_back("abc", "a.c", 10U); - suppressions.emplace_back("unmatchedSuppression", "a.c", SuppressionList::Suppression::NO_LINE); - ASSERT_EQUALS(false, SuppressionList::reportUnmatchedSuppressions(suppressions, *this)); - ASSERT_EQUALS("", errout_str()); + { + SuppressionList suppressions; + addCheckedSuppression(suppressions, {"abc", "a.c", 10U}); + addCheckedSuppression(suppressions, {"unmatchedSuppression", "a.c", SuppressionList::Suppression::NO_LINE}); + ASSERT_EQUALS(false, CppCheckExecutor::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); + ASSERT_EQUALS("", errout_str()); + } // suppress unmatchedSuppression in a.c at line 10 - suppressions.clear(); - suppressions.emplace_back("abc", "a.c", 10U); - suppressions.emplace_back("unmatchedSuppression", "a.c", 10U); - ASSERT_EQUALS(false, SuppressionList::reportUnmatchedSuppressions(suppressions, *this)); - ASSERT_EQUALS("", errout_str()); + { + SuppressionList suppressions; + addCheckedSuppression(suppressions, {"abc", "a.c", 10U}); + addCheckedSuppression(suppressions, {"unmatchedSuppression", "a.c", 10U}); + ASSERT_EQUALS(false, CppCheckExecutor::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); + ASSERT_EQUALS("", errout_str()); + } // don't suppress unmatchedSuppression when file is mismatching - suppressions.clear(); - suppressions.emplace_back("abc", "a.c", 10U); - suppressions.emplace_back("unmatchedSuppression", "b.c", SuppressionList::Suppression::NO_LINE); - ASSERT_EQUALS(true, SuppressionList::reportUnmatchedSuppressions(suppressions, *this)); - ASSERT_EQUALS("[a.c:10:0]: (information) Unmatched suppression: abc [unmatchedSuppression]\n", errout_str()); + { + SuppressionList suppressions; + addCheckedSuppression(suppressions, {"abc", "a.c", 10U}); + addCheckedSuppression(suppressions, {"unmatchedSuppression", "b.c", SuppressionList::Suppression::NO_LINE}); + ASSERT_EQUALS(true, CppCheckExecutor::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); + ASSERT_EQUALS("[a.c:10:0]: (information) Unmatched suppression: abc [unmatchedSuppression]\n", errout_str()); + } // don't suppress unmatchedSuppression when line is mismatching - suppressions.clear(); - suppressions.emplace_back("abc", "a.c", 10U); - suppressions.emplace_back("unmatchedSuppression", "a.c", 1U); - ASSERT_EQUALS(true, SuppressionList::reportUnmatchedSuppressions(suppressions, *this)); - ASSERT_EQUALS("[a.c:10:0]: (information) Unmatched suppression: abc [unmatchedSuppression]\n", errout_str()); + { + SuppressionList suppressions; + addCheckedSuppression(suppressions, {"abc", "a.c", 10U}); + addCheckedSuppression(suppressions, {"unmatchedSuppression", "a.c", 1U}); + ASSERT_EQUALS(true, CppCheckExecutor::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); + ASSERT_EQUALS("[a.c:10:0]: (information) Unmatched suppression: abc [unmatchedSuppression]\n", errout_str()); + } } void suppressionsParseXmlFile() const { @@ -1626,7 +1644,7 @@ class TestSuppressions : public TestFixture { ASSERT_EQUALS(true, supprs.updateSuppressionState(s)); - const std::list l = supprs.getUnmatchedGlobalSuppressions(false); + const std::list l = supprs.getUnmatchedGlobalSuppressions(); ASSERT_EQUALS(1, l.size()); } { @@ -1641,7 +1659,7 @@ class TestSuppressions : public TestFixture { s.matched = true; ASSERT_EQUALS(true, supprs.updateSuppressionState(s)); - const std::list l = supprs.getUnmatchedGlobalSuppressions(false); + const std::list l = supprs.getUnmatchedGlobalSuppressions(); ASSERT_EQUALS(0, l.size()); } } @@ -1766,7 +1784,7 @@ class TestSuppressions : public TestFixture { ASSERT(!suppr->checked); ASSERT(!suppr->matched); } - ASSERT(suppressions.getUnmatchedGlobalSuppressions(true).empty()); + ASSERT(suppressions.getUnmatchedGlobalSuppressions().empty()); } { @@ -1780,7 +1798,7 @@ class TestSuppressions : public TestFixture { ASSERT(suppr->checked); ASSERT(!suppr->matched); } - ASSERT(!suppressions.getUnmatchedGlobalSuppressions(true).empty()); + ASSERT(!suppressions.getUnmatchedGlobalSuppressions().empty()); } { @@ -1794,7 +1812,7 @@ class TestSuppressions : public TestFixture { ASSERT(suppr->checked); ASSERT(!suppr->matched); } - ASSERT(!suppressions.getUnmatchedGlobalSuppressions(true).empty()); + ASSERT(!suppressions.getUnmatchedGlobalSuppressions().empty()); } { @@ -1807,7 +1825,7 @@ class TestSuppressions : public TestFixture { ASSERT(suppr->checked); ASSERT(suppr->matched); } - ASSERT(suppressions.getUnmatchedGlobalSuppressions(true).empty()); + ASSERT(suppressions.getUnmatchedGlobalSuppressions().empty()); } { @@ -1821,7 +1839,7 @@ class TestSuppressions : public TestFixture { ASSERT(suppr->checked); ASSERT(!suppr->matched); } - ASSERT(!suppressions.getUnmatchedGlobalSuppressions(true).empty()); + ASSERT(!suppressions.getUnmatchedGlobalSuppressions().empty()); } } };