Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
31 changes: 18 additions & 13 deletions lib/cppcheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -850,19 +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) const
{
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<std::uint8_t>(settings.checkLevel));
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<std::uint8_t>(mSettings.checkLevel));
for (const auto &a : mSettings.addonInfos) {
toolinfo << a.name;
toolinfo << a.args;
}
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());
}

Expand Down Expand Up @@ -922,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));
}
Expand All @@ -931,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));
}
Expand Down Expand Up @@ -1015,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<ErrorMessage> errors;
if (!analyzerInformation->analyzeFile(mSettings.buildDir, file.spath(), cfgname, fileIndex, hash, errors)) {
while (!errors.empty()) {
Expand Down
10 changes: 10 additions & 0 deletions lib/cppcheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class AnalyzerInformation;
class ErrorLogger;
class Settings;
struct Suppressions;
class Preprocessor;

namespace simplecpp { class TokenList; }

Expand Down Expand Up @@ -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 tokens Token list from preprocessed file.
* @return hash
*/
std::size_t calculateHash(const Preprocessor &preprocessor, const simplecpp::TokenList &tokens) const;

/**
* @brief Check a file using stream
* @param file the file
Expand Down
36 changes: 36 additions & 0 deletions test/testcppcheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "fixture.h"
#include "helpers.h"
#include "path.h"
#include "preprocessor.h"
#include "settings.h"
#include "suppressions.h"

Expand Down Expand Up @@ -68,6 +69,7 @@ class TestCppcheck : public TestFixture {
TEST_CASE(isPremiumCodingStandardId);
TEST_CASE(getDumpFileContentsRawTokens);
TEST_CASE(getDumpFileContentsLibrary);
TEST_CASE(premiumResultsCache);
}

void getErrorMessages() const {
Expand Down Expand Up @@ -324,6 +326,40 @@ 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<std::string> files;

std::istringstream istr("void f();\nint x;\n");
const 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, {});
const size_t hash1 = check.calculateHash(preprocessor, tokens);

settings.premiumArgs = "";
const size_t hash2 = check.calculateHash(preprocessor, tokens);

// cppcheck-suppress knownConditionTrueFalse
ASSERT(hash1 != hash2);
}

// TODO: test suppressions
// TODO: test all with FS
};
Expand Down
Loading