Skip to content

Fix #14064 Files are reanalyzed with --cppcheck-build-dir and inline suppressions (regression) #7741

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Aug 19, 2025
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
6 changes: 3 additions & 3 deletions lib/cppcheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) const
std::size_t CppCheck::calculateHash(const Preprocessor& preprocessor, const simplecpp::TokenList& tokens, const std::string& filePath) const
{
std::ostringstream toolinfo;
toolinfo << (mSettings.cppcheckCfgProductName.empty() ? CPPCHECK_VERSION_STRING : mSettings.cppcheckCfgProductName);
Expand All @@ -867,7 +867,7 @@ std::size_t CppCheck::calculateHash(const Preprocessor& preprocessor, const simp
}
toolinfo << mSettings.premiumArgs;
// TODO: do we need to add more options?
mSuppressions.nomsg.dump(toolinfo);
mSuppressions.nomsg.dump(toolinfo, filePath);
return preprocessor.calculateHash(tokens, toolinfo.str());
}

Expand Down Expand Up @@ -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);
const std::size_t hash = calculateHash(preprocessor, tokens1, file.spath());
std::list<ErrorMessage> errors;
if (!analyzerInformation->analyzeFile(mSettings.buildDir, file.spath(), cfgname, fileIndex, hash, errors)) {
while (!errors.empty()) {
Expand Down
2 changes: 1 addition & 1 deletion lib/cppcheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ class CPPCHECKLIB CppCheck {
* @param tokens Token list from preprocessed file.
* @return hash
*/
std::size_t calculateHash(const Preprocessor &preprocessor, const simplecpp::TokenList &tokens) const;
std::size_t calculateHash(const Preprocessor &preprocessor, const simplecpp::TokenList &tokens, const std::string& filePath = {}) const;

/**
* @brief Check a file using stream
Expand Down
4 changes: 3 additions & 1 deletion lib/suppressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -512,12 +512,14 @@ bool SuppressionList::isSuppressed(const ::ErrorMessage &errmsg, const std::set<
return isSuppressed(SuppressionList::ErrorMessage::fromErrorMessage(errmsg, macroNames));
}

void SuppressionList::dump(std::ostream & out) const
void SuppressionList::dump(std::ostream & out, const std::string& filePath) const
{
std::lock_guard<std::mutex> lg(mSuppressionsSync);

out << " <suppressions>" << std::endl;
for (const Suppression &suppression : mSuppressions) {
if (suppression.isInline && !suppression.fileName.empty() && !filePath.empty() && filePath != suppression.fileName)
continue;
out << " <suppression";
out << " errorId=\"" << ErrorLogger::toxml(suppression.errorId) << '"';
if (!suppression.fileName.empty())
Expand Down
2 changes: 1 addition & 1 deletion lib/suppressions.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ class CPPCHECKLIB SuppressionList {
* @brief Create an xml dump of suppressions
* @param out stream to write XML to
*/
void dump(std::ostream &out) const;
void dump(std::ostream &out, const std::string& filePath = {}) const;

/**
* @brief Returns list of unmatched local (per-file) suppressions.
Expand Down
34 changes: 32 additions & 2 deletions test/cli/inline-suppress_test.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@

# python -m pytest test-inline-suppress.py
# python -m pytest inline-suppress_test.py

import json
import os
import pytest
import sys
import time
from testutils import cppcheck

__script_dir = os.path.dirname(os.path.abspath(__file__))
Expand Down Expand Up @@ -247,6 +248,35 @@ def test_build_dir(tmpdir):
assert stdout == ''
assert ret == 0, stdout

def test_build_dir_jobs_suppressions(tmpdir): #14064
args = [
'-q',
'--template=simple',
'--cppcheck-build-dir={}'.format(tmpdir),
'--enable=style',
'--inline-suppr',
'-j4',
'reanalysis'
]

ret, stdout, stderr = cppcheck(args, cwd=__script_dir)
lines = stderr.splitlines()
assert lines == []
assert stdout == ''
assert ret == 0, stdout

a1Path = os.path.join(tmpdir, 'd.a1')
assert os.path.exists(a1Path)
mtimeOld = os.path.getmtime(a1Path)

time.sleep(1)

for _ in range(1, 10):
cppcheck(args, cwd=__script_dir)

mtimeNew = os.path.getmtime(a1Path)
assert mtimeOld == mtimeNew


def __test_build_dir_unused_template(tmpdir, extra_args):
args = [
Expand Down Expand Up @@ -470,4 +500,4 @@ def test_unmatched_cfg():
'{}cfg.c:9:0: information: Unmatched suppression: id [unmatchedSuppression]'.format(__proj_inline_suppres_path),
]
assert stdout == ''
assert ret == 0, stdout
assert ret == 0, stdout
4 changes: 4 additions & 0 deletions test/cli/reanalysis/a.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
int main() {
int i; // cppcheck-suppress unusedVariable
}

2 changes: 2 additions & 0 deletions test/cli/reanalysis/b.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
int main() {}

2 changes: 2 additions & 0 deletions test/cli/reanalysis/c.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
int main() {}

2 changes: 2 additions & 0 deletions test/cli/reanalysis/d.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
int main() {}

Loading