From 5ff28261b84d9409ba18cc37111ef32263fb23cf Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 13 Jun 2025 19:34:44 +0200 Subject: [PATCH 01/10] Add addons and premium args to hhash function --- lib/cppcheck.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 79448429ede..fc4a1b09f15 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -861,6 +861,11 @@ static std::size_t calculateHash(const Preprocessor& preprocessor, const simplec toolinfo << (settings.severity.isEnabled(Severity::information) ? 'i' : ' '); toolinfo << settings.userDefines; toolinfo << std::to_string(static_cast(settings.checkLevel)); + for (const auto &a : settings.addonInfos) { + toolinfo << a.name; + toolinfo << a.args; + } + toolinfo << settings.premiumArgs; // TODO: do we need to add more options? supprs.nomsg.dump(toolinfo); return preprocessor.calculateHash(tokens, toolinfo.str()); From 1322092577228a911394922d128036ad4371878b Mon Sep 17 00:00:00 2001 From: glank Date: Mon, 16 Jun 2025 08:40:36 +0200 Subject: [PATCH 02/10] Add test --- lib/cppcheck.cpp | 30 ++++++++++++------------- lib/cppcheck.h | 10 +++++++++ test/testcppcheck.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 15 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index fc4a1b09f15..ce6dc3faca3 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -850,24 +850,24 @@ static simplecpp::TokenList createTokenList(const std::string& filename, std::ve return {filename, files, outputList}; } -static std::size_t calculateHash(const Preprocessor& preprocessor, const simplecpp::TokenList& tokens, const Settings& settings, const Suppressions& supprs) +std::size_t CppCheck::calculateHash(const Preprocessor& preprocessor, const simplecpp::TokenList& tokens) { std::ostringstream toolinfo; - toolinfo << (settings.cppcheckCfgProductName.empty() ? CPPCHECK_VERSION_STRING : settings.cppcheckCfgProductName); - toolinfo << (settings.severity.isEnabled(Severity::warning) ? 'w' : ' '); - toolinfo << (settings.severity.isEnabled(Severity::style) ? 's' : ' '); - toolinfo << (settings.severity.isEnabled(Severity::performance) ? 'p' : ' '); - toolinfo << (settings.severity.isEnabled(Severity::portability) ? 'p' : ' '); - toolinfo << (settings.severity.isEnabled(Severity::information) ? 'i' : ' '); - toolinfo << settings.userDefines; - toolinfo << std::to_string(static_cast(settings.checkLevel)); - for (const auto &a : settings.addonInfos) { + toolinfo << (mSettings.cppcheckCfgProductName.empty() ? CPPCHECK_VERSION_STRING : mSettings.cppcheckCfgProductName); + toolinfo << (mSettings.severity.isEnabled(Severity::warning) ? 'w' : ' '); + toolinfo << (mSettings.severity.isEnabled(Severity::style) ? 's' : ' '); + toolinfo << (mSettings.severity.isEnabled(Severity::performance) ? 'p' : ' '); + toolinfo << (mSettings.severity.isEnabled(Severity::portability) ? 'p' : ' '); + toolinfo << (mSettings.severity.isEnabled(Severity::information) ? 'i' : ' '); + toolinfo << mSettings.userDefines; + toolinfo << std::to_string(static_cast(mSettings.checkLevel)); + for (const auto &a : mSettings.addonInfos) { toolinfo << a.name; toolinfo << a.args; } - toolinfo << settings.premiumArgs; + toolinfo << mSettings.premiumArgs; // TODO: do we need to add more options? - supprs.nomsg.dump(toolinfo); + mSuppressions.nomsg.dump(toolinfo); return preprocessor.calculateHash(tokens, toolinfo.str()); } @@ -927,7 +927,7 @@ unsigned int CppCheck::checkFile(const FileWithDetails& file, const std::string simplecpp::TokenList tokens(*fileStream, files, file.spath()); if (analyzerInformation) { const Preprocessor preprocessor(mSettings, mErrorLogger, Standards::Language::C); - hash = calculateHash(preprocessor, tokens, mSettings, mSuppressions); + hash = calculateHash(preprocessor, tokens); } tokenlist.createTokens(std::move(tokens)); } @@ -936,7 +936,7 @@ unsigned int CppCheck::checkFile(const FileWithDetails& file, const std::string simplecpp::TokenList tokens(file.spath(), files); if (analyzerInformation) { const Preprocessor preprocessor(mSettings, mErrorLogger, file.lang()); - hash = calculateHash(preprocessor, tokens, mSettings, mSuppressions); + hash = calculateHash(preprocessor, tokens); } tokenlist.createTokens(std::move(tokens)); } @@ -1020,7 +1020,7 @@ unsigned int CppCheck::checkFile(const FileWithDetails& file, const std::string if (analyzerInformation) { // Calculate hash so it can be compared with old hash / future hashes - const std::size_t hash = calculateHash(preprocessor, tokens1, mSettings, mSuppressions); + const std::size_t hash = calculateHash(preprocessor, tokens1); std::list errors; if (!analyzerInformation->analyzeFile(mSettings.buildDir, file.spath(), cfgname, fileIndex, hash, errors)) { while (!errors.empty()) { diff --git a/lib/cppcheck.h b/lib/cppcheck.h index d7c326704a1..260bdf76e30 100644 --- a/lib/cppcheck.h +++ b/lib/cppcheck.h @@ -42,6 +42,7 @@ class AnalyzerInformation; class ErrorLogger; class Settings; struct Suppressions; +class Preprocessor; namespace simplecpp { class TokenList; } @@ -162,6 +163,15 @@ class CPPCHECKLIB CppCheck { /** @brief There has been an internal error => Report information message */ void internalError(const std::string &filename, const std::string &msg); + /** + * @brief Calculate hash used to detect when a file needs to be reanalyzed. + * + * @param preprocessor Preprocessor used to calculate the hash. + * @param toolinfo Token list from preprocessed file. + * @return hash + */ + std::size_t calculateHash(const Preprocessor &preprocessor, const simplecpp::TokenList &tokens); + /** * @brief Check a file using stream * @param file the file diff --git a/test/testcppcheck.cpp b/test/testcppcheck.cpp index a5b2b83e9f1..9892f222c37 100644 --- a/test/testcppcheck.cpp +++ b/test/testcppcheck.cpp @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +#include "cmdlineparser.h" #include "color.h" #include "cppcheck.h" #include "errorlogger.h" @@ -23,6 +24,7 @@ #include "fixture.h" #include "helpers.h" #include "path.h" +#include "preprocessor.h" #include "settings.h" #include "suppressions.h" @@ -58,6 +60,22 @@ class TestCppcheck : public TestFixture { } }; + class NullCmdLineLogger : public CmdLineLogger + { + public: + void printMessage(const std::string &) override + { + } + + void printError(const std::string &) override + { + } + + void printRaw(const std::string &) override + { + } + }; + void run() override { TEST_CASE(getErrorMessages); TEST_CASE(checkWithFile); @@ -68,6 +86,7 @@ class TestCppcheck : public TestFixture { TEST_CASE(isPremiumCodingStandardId); TEST_CASE(getDumpFileContentsRawTokens); TEST_CASE(getDumpFileContentsLibrary); + TEST_CASE(premiumResultsCache); } void getErrorMessages() const { @@ -324,6 +343,39 @@ class TestCppcheck : public TestFixture { } } + void premiumResultsCache() const { + // Trac #13889 - cached misra results are shown after removing --premium=misra-c-2012 option + + Settings settings; + Suppressions supprs; + ErrorLogger2 errorLogger; + + std::vector files; + + std::istringstream istr("void f();\nint x;\n"); + simplecpp::TokenList tokens(istr, files, "m1.c"); + + Preprocessor preprocessor(settings, errorLogger, Standards::Language::C); + ASSERT(preprocessor.loadFiles(tokens, files)); + + AddonInfo premiumaddon; + premiumaddon.name = "premiumaddon.json"; + premiumaddon.executable = "premiumaddon"; + + settings.cppcheckCfgProductName = "Cppcheck Premium 0.0.0"; + settings.addons.insert(premiumaddon.name); + settings.addonInfos.push_back(premiumaddon); + + settings.premiumArgs = "misra-c-2012"; + CppCheck check(settings, supprs, errorLogger, false, {}); + size_t hash1 = check.calculateHash(preprocessor, tokens); + + settings.premiumArgs = ""; + size_t hash2 = check.calculateHash(preprocessor, tokens); + + ASSERT(hash1 != hash2); + } + // TODO: test suppressions // TODO: test all with FS }; From dd642df5864e09efa840e52ab2258285f7964146 Mon Sep 17 00:00:00 2001 From: glank Date: Mon, 16 Jun 2025 13:38:23 +0200 Subject: [PATCH 03/10] Remove leftover NullCmdLineLogger --- test/testcppcheck.cpp | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/test/testcppcheck.cpp b/test/testcppcheck.cpp index 9892f222c37..f12f57bc1ea 100644 --- a/test/testcppcheck.cpp +++ b/test/testcppcheck.cpp @@ -16,7 +16,6 @@ * along with this program. If not, see . */ -#include "cmdlineparser.h" #include "color.h" #include "cppcheck.h" #include "errorlogger.h" @@ -60,22 +59,6 @@ class TestCppcheck : public TestFixture { } }; - class NullCmdLineLogger : public CmdLineLogger - { - public: - void printMessage(const std::string &) override - { - } - - void printError(const std::string &) override - { - } - - void printRaw(const std::string &) override - { - } - }; - void run() override { TEST_CASE(getErrorMessages); TEST_CASE(checkWithFile); From 9ae2624100136665a33ec0be12ff6b1260497914 Mon Sep 17 00:00:00 2001 From: glank Date: Mon, 16 Jun 2025 13:44:14 +0200 Subject: [PATCH 04/10] Run dmake --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 2a72e243844..b081aa304c7 100644 --- a/Makefile +++ b/Makefile @@ -743,7 +743,7 @@ test/testcondition.o: test/testcondition.cpp lib/addoninfo.h lib/check.h lib/che test/testconstructors.o: test/testconstructors.cpp lib/addoninfo.h lib/check.h lib/checkclass.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testconstructors.cpp -test/testcppcheck.o: test/testcppcheck.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testcppcheck.o: test/testcppcheck.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcppcheck.cpp test/testerrorlogger.o: test/testerrorlogger.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/xml.h test/fixture.h test/helpers.h From 82f564e7f429497513ec55c9f7393dec1380d79c Mon Sep 17 00:00:00 2001 From: glank Date: Mon, 16 Jun 2025 13:53:42 +0200 Subject: [PATCH 05/10] Fix documentation error --- lib/cppcheck.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cppcheck.h b/lib/cppcheck.h index 260bdf76e30..10a3141fe89 100644 --- a/lib/cppcheck.h +++ b/lib/cppcheck.h @@ -167,7 +167,7 @@ class CPPCHECKLIB CppCheck { * @brief Calculate hash used to detect when a file needs to be reanalyzed. * * @param preprocessor Preprocessor used to calculate the hash. - * @param toolinfo Token list from preprocessed file. + * @param tokens Token list from preprocessed file. * @return hash */ std::size_t calculateHash(const Preprocessor &preprocessor, const simplecpp::TokenList &tokens); From 3cf2f1ee740703d9100fc3b5e6f1f503de56075f Mon Sep 17 00:00:00 2001 From: glank Date: Mon, 16 Jun 2025 13:58:22 +0200 Subject: [PATCH 06/10] Remove unused TokenList forward declaration --- lib/cppcheck.h | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/cppcheck.h b/lib/cppcheck.h index 10a3141fe89..fb507752071 100644 --- a/lib/cppcheck.h +++ b/lib/cppcheck.h @@ -32,7 +32,6 @@ #include #include -class TokenList; enum class SHOWTIME_MODES : std::uint8_t; struct FileSettings; class CheckUnusedFunctions; From 8e2914359499a74687c4a91b497424ef4d0ccf18 Mon Sep 17 00:00:00 2001 From: glank Date: Mon, 16 Jun 2025 14:12:21 +0200 Subject: [PATCH 07/10] Use const --- test/testcppcheck.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/testcppcheck.cpp b/test/testcppcheck.cpp index f12f57bc1ea..d4c7eeb14b2 100644 --- a/test/testcppcheck.cpp +++ b/test/testcppcheck.cpp @@ -336,7 +336,7 @@ class TestCppcheck : public TestFixture { std::vector files; std::istringstream istr("void f();\nint x;\n"); - simplecpp::TokenList tokens(istr, files, "m1.c"); + const simplecpp::TokenList tokens(istr, files, "m1.c"); Preprocessor preprocessor(settings, errorLogger, Standards::Language::C); ASSERT(preprocessor.loadFiles(tokens, files)); @@ -351,10 +351,10 @@ class TestCppcheck : public TestFixture { settings.premiumArgs = "misra-c-2012"; CppCheck check(settings, supprs, errorLogger, false, {}); - size_t hash1 = check.calculateHash(preprocessor, tokens); + const size_t hash1 = check.calculateHash(preprocessor, tokens); settings.premiumArgs = ""; - size_t hash2 = check.calculateHash(preprocessor, tokens); + const size_t hash2 = check.calculateHash(preprocessor, tokens); ASSERT(hash1 != hash2); } From ddb384f8908183f730243fdaa9ec9276d9d3b977 Mon Sep 17 00:00:00 2001 From: glank Date: Mon, 16 Jun 2025 15:05:15 +0200 Subject: [PATCH 08/10] Revert "Remove unused TokenList forward declaration" This reverts commit 3cf2f1ee740703d9100fc3b5e6f1f503de56075f. --- lib/cppcheck.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/cppcheck.h b/lib/cppcheck.h index fb507752071..10a3141fe89 100644 --- a/lib/cppcheck.h +++ b/lib/cppcheck.h @@ -32,6 +32,7 @@ #include #include +class TokenList; enum class SHOWTIME_MODES : std::uint8_t; struct FileSettings; class CheckUnusedFunctions; From 3e0e3ffa716b0be8e5db317d17eb6a140ea0b4c6 Mon Sep 17 00:00:00 2001 From: glank Date: Mon, 16 Jun 2025 17:00:34 +0200 Subject: [PATCH 09/10] Make calculateHash const --- lib/cppcheck.cpp | 2 +- lib/cppcheck.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index ce6dc3faca3..4b891f33ea0 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -850,7 +850,7 @@ static simplecpp::TokenList createTokenList(const std::string& filename, std::ve return {filename, files, outputList}; } -std::size_t CppCheck::calculateHash(const Preprocessor& preprocessor, const simplecpp::TokenList& tokens) +std::size_t CppCheck::calculateHash(const Preprocessor& preprocessor, const simplecpp::TokenList& tokens) const { std::ostringstream toolinfo; toolinfo << (mSettings.cppcheckCfgProductName.empty() ? CPPCHECK_VERSION_STRING : mSettings.cppcheckCfgProductName); diff --git a/lib/cppcheck.h b/lib/cppcheck.h index 10a3141fe89..3a39b2db6d6 100644 --- a/lib/cppcheck.h +++ b/lib/cppcheck.h @@ -170,7 +170,7 @@ class CPPCHECKLIB CppCheck { * @param tokens Token list from preprocessed file. * @return hash */ - std::size_t calculateHash(const Preprocessor &preprocessor, const simplecpp::TokenList &tokens); + std::size_t calculateHash(const Preprocessor &preprocessor, const simplecpp::TokenList &tokens) const; /** * @brief Check a file using stream From c5a354b27c4407d0a256c2234801cec02edad510 Mon Sep 17 00:00:00 2001 From: glank Date: Tue, 17 Jun 2025 09:32:09 +0200 Subject: [PATCH 10/10] Add suppression --- test/testcppcheck.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/testcppcheck.cpp b/test/testcppcheck.cpp index d4c7eeb14b2..18562c17a19 100644 --- a/test/testcppcheck.cpp +++ b/test/testcppcheck.cpp @@ -356,6 +356,7 @@ class TestCppcheck : public TestFixture { settings.premiumArgs = ""; const size_t hash2 = check.calculateHash(preprocessor, tokens); + // cppcheck-suppress knownConditionTrueFalse ASSERT(hash1 != hash2); }