diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 45e88ced7..54559e6f3 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -747,10 +747,15 @@ void CppCheck::reportErr(const ErrorLogger::ErrorMessage &msg) const Suppressions::ErrorMessage errorMessage = msg.toSuppressionsErrorMessage(); - if (_settings.nomsg.isSuppressed(errorMessage)) - return; + if (_useGlobalSuppressions) { + if (_settings.nomsg.isSuppressed(errorMessage)) + return; + } else { + if (_settings.nomsg.isSuppressedLocal(errorMessage)) + return; + } - if (!_settings.nofail.isSuppressed(errorMessage)) + if (!_settings.nofail.isSuppressed(errorMessage) && (_useGlobalSuppressions || !_settings.nomsg.isSuppressed(errorMessage))) exitcode = 1; _errorList.push_back(errmsg); diff --git a/lib/suppressions.cpp b/lib/suppressions.cpp index 18d95f97f..539df8557 100644 --- a/lib/suppressions.cpp +++ b/lib/suppressions.cpp @@ -277,6 +277,21 @@ bool Suppressions::isSuppressed(const Suppressions::ErrorMessage &errmsg) return false; } +bool Suppressions::isSuppressedLocal(const Suppressions::ErrorMessage &errmsg) +{ + const bool unmatchedSuppression(errmsg.errorId == "unmatchedSuppression"); + for (std::list::iterator it = _suppressions.begin(); it != _suppressions.end(); ++it) { + Suppression &s = *it; + if (!s.isLocal()) + continue; + if (unmatchedSuppression && s.errorId != errmsg.errorId) + continue; + if (s.isMatch(errmsg)) + return true; + } + return false; +} + void Suppressions::dump(std::ostream & out) { out << " " << std::endl; @@ -294,6 +309,8 @@ void Suppressions::dump(std::ostream & out) out << " " << std::endl; } +#include + std::list Suppressions::getUnmatchedLocalSuppressions(const std::string &file, const bool unusedFunctionChecking) const { std::list result; @@ -303,7 +320,7 @@ std::list Suppressions::getUnmatchedLocalSuppressions continue; if (!unusedFunctionChecking && s.errorId == "unusedFunction") continue; - if (!file.empty() && !s.fileName.empty() && s.fileName != file) + if (file.empty() || !s.isLocal() || s.fileName != file) continue; result.push_back(s); } @@ -319,7 +336,7 @@ std::list Suppressions::getUnmatchedGlobalSuppression continue; if (!unusedFunctionChecking && s.errorId == "unusedFunction") continue; - if (s.fileName.find_first_of("?*") == std::string::npos) + if (s.isLocal()) continue; result.push_back(s); } diff --git a/lib/suppressions.h b/lib/suppressions.h index ac784fe99..a3ab80aa2 100644 --- a/lib/suppressions.h +++ b/lib/suppressions.h @@ -88,6 +88,10 @@ public: bool isMatch(const ErrorMessage &errmsg); std::string getText() const; + bool isLocal() const { + return !fileName.empty() && fileName.find_first_of("?*") == std::string::npos; + } + std::string errorId; std::string fileName; int lineNumber; @@ -135,6 +139,13 @@ public: */ bool isSuppressed(const ErrorMessage &errmsg); + /** + * @brief Returns true if this message should not be shown to the user, only uses local suppressions. + * @param errmsg error message + * @return true if this error is suppressed. + */ + bool isSuppressedLocal(const ErrorMessage &errmsg); + /** * @brief Create an xml dump of suppressions * @param out stream to write XML to diff --git a/test/testsuppressions.cpp b/test/testsuppressions.cpp index bb1f3d54c..564547ba3 100644 --- a/test/testsuppressions.cpp +++ b/test/testsuppressions.cpp @@ -50,6 +50,8 @@ private: TEST_CASE(inlinesuppress); TEST_CASE(inlinesuppress_symbolname); + TEST_CASE(globalSuppressions); // Testing that global suppressions work (#8515) + TEST_CASE(inlinesuppress_unusedFunction); // #4210 - unusedFunction TEST_CASE(globalsuppress_unusedFunction); // #4946 TEST_CASE(suppressionWithRelativePaths); // #4733 @@ -432,6 +434,19 @@ private: ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", errout.str()); } + void globalSuppressions() { // Testing that Cppcheck::useGlobalSuppressions works (#8515) + errout.str(""); + + CppCheck cppCheck(*this, false); // <- do not "use global suppressions". pretend this is a thread that just checks a file. + Settings& settings = cppCheck.settings(); + settings.nomsg.addSuppressionLine("uninitvar"); + settings.exitCode = 1; + + const char code[] = "int f() { int a; return a; }"; + ASSERT_EQUALS(0, cppCheck.check("test.c", code)); // <- no unsuppressed error is seen + ASSERT_EQUALS("[test.c:1]: (error) Uninitialized variable: a\n", errout.str()); // <- report error so ThreadExecutor can suppress it and make sure the global suppression is matched. + } + void inlinesuppress_unusedFunction() const { // #4210, #4946 - wrong report of "unmatchedSuppression" for "unusedFunction" Suppressions suppressions; suppressions.addSuppression(Suppressions::Suppression("unusedFunction", "test.c", 3));