Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
7 changes: 6 additions & 1 deletion cli/cppcheckexecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -661,8 +661,13 @@ void StdLogger::reportErr(const ErrorMessage &msg)
msgCopy.classification = getClassification(msgCopy.guideline, mSettings.reportType);

// TODO: there should be no need for verbose and default messages here
// Don't perform redundant reads for these formats, the code is not needed
// for deduplication
const bool noCode = mSettings.outputFormat == Settings::OutputFormat::xml ||
mSettings.outputFormat == Settings::OutputFormat::sarif;
const std::string msgStr =
msgCopy.toString(mSettings.verbose, mSettings.templateFormat, mSettings.templateLocation);
msgCopy.toString(mSettings.verbose, mSettings.templateFormat,
mSettings.templateLocation, noCode);

// Alert only about unique errors
if (!mSettings.emitDuplicates && !mShownErrors.insert(msgStr).second)
Expand Down
4 changes: 3 additions & 1 deletion lib/cppcheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,9 @@ class CppCheck::CppCheckLogger : public ErrorLogger
}

// TODO: there should be no need for the verbose and default messages here
std::string errmsg = msg.toString(mSettings.verbose, mSettings.templateFormat, mSettings.templateLocation);
// Code is not needed for deduplication
const bool noCode = true;
std::string errmsg = msg.toString(mSettings.verbose, mSettings.templateFormat, mSettings.templateLocation, noCode);
if (errmsg.empty())
return;

Expand Down
8 changes: 5 additions & 3 deletions lib/errorlogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ static void replaceColors(std::string& source, bool erase) {
replace(source, substitutionMapErase);
}

std::string ErrorMessage::toString(bool verbose, const std::string &templateFormat, const std::string &templateLocation) const
std::string ErrorMessage::toString(bool verbose, const std::string &templateFormat, const std::string &templateLocation, bool noCode) const
{
assert(!templateFormat.empty());

Expand Down Expand Up @@ -737,7 +737,8 @@ std::string ErrorMessage::toString(bool verbose, const std::string &templateForm
endl = "\r\n";
else
endl = "\r";
findAndReplace(result, "{code}", readCode(callStack.back().getOrigFile(), callStack.back().line, callStack.back().column, endl));
const std::string code = noCode ? "" : readCode(callStack.back().getOrigFile(), callStack.back().line, callStack.back().column, endl);
findAndReplace(result, "{code}", code);
}
} else {
static const std::unordered_map<std::string, std::string> callStackSubstitutionMap =
Expand Down Expand Up @@ -768,7 +769,8 @@ std::string ErrorMessage::toString(bool verbose, const std::string &templateForm
endl = "\r\n";
else
endl = "\r";
findAndReplace(text, "{code}", readCode(fileLocation.getOrigFile(), fileLocation.line, fileLocation.column, endl));
const std::string code = noCode ? "" : readCode(fileLocation.getOrigFile(), fileLocation.line, fileLocation.column, endl);
findAndReplace(text, "{code}", code);
}
result += '\n' + text;
}
Expand Down
4 changes: 3 additions & 1 deletion lib/errorlogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,13 @@ class CPPCHECKLIB ErrorMessage {
* or template to be used. E.g. "{file}:{line},{severity},{id},{message}"
* @param templateLocation Format Empty string to use default output format
* or template to be used. E.g. "{file}:{line},{info}"
* @param noCode Always replace {code} with an empty string
* @return formatted string
*/
std::string toString(bool verbose,
const std::string &templateFormat,
const std::string &templateLocation) const;
const std::string &templateLocation,
bool noCode = false) const;

std::string serialize() const;
/**
Expand Down
60 changes: 59 additions & 1 deletion test/cli/other_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4861,4 +4861,62 @@ def test_ipc_inline_suppressions(tmp_path):
stdout_lines = stdout.splitlines()
stdout_lines.sort()
assert stdout_lines == stdout_exp
assert stderr.splitlines() == []
assert stderr.splitlines() == []

def __count_openat_calls(tmpdir, flags, expected):
source_pathname = os.path.join(tmpdir, 'test.c')
Comment thread
ludviggunne marked this conversation as resolved.
strace_pathname = os.path.join(tmpdir, 'strace.txt')
content = """
void f(int x) {
int y = x / 0;
int z = x / 0;
}
"""
cppcheck_path = __lookup_cppcheck_exe()

with open(source_pathname, 'wt') as f:
f.write(content)

args = [
'strace',
'--summary-only',
'--summary-columns=count',
'--trace=openat',
'--follow-forks',
f'--output={strace_pathname}',
f'--trace-path={source_pathname}',
cppcheck_path,
'-q',
source_pathname,
]

args += flags
proc = subprocess.run(args, check=False)

assert proc.returncode == 0

with open(strace_pathname, 'r') as f:
strace_content = f.read()

assert strace_content.splitlines()[-1].strip() == f'{expected} total'

__strace_decorator = pytest.mark.skipif(
sys.platform != 'linux' or 'ASAN_OPTIONS' in os.environ,
reason="uses strace"
)

@__strace_decorator
def test_redundant_file_reads(tmpdir):
__count_openat_calls(tmpdir, [], 3)

@__strace_decorator
def test_redundant_file_reads_suppress(tmpdir):
__count_openat_calls(tmpdir, [ '--suppress=zerodiv' ], 1)

@__strace_decorator
def test_redundant_file_reads_template_cppcheck1(tmpdir):
__count_openat_calls(tmpdir, [ '--template=cppcheck1' ], 1)

@__strace_decorator
def test_redundant_file_reads_xml(tmpdir):
__count_openat_calls(tmpdir, [ '--xml' ], 1)
2 changes: 1 addition & 1 deletion test/cli/performance_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ def test_slow_many_headers(tmpdir):


@pytest.mark.skipif(sys.platform == 'darwin', reason='GitHub macOS runners are too slow')
@pytest.mark.timeout(10)
@pytest.mark.timeout(5)
def test_large_number_of_violations_and_suppressions(tmpdir):
filename_main = os.path.join(tmpdir, 'main.c')
# This name causes the PathMatch::match() to iterate ~70 times, which is not unrealistic for a header file placed in subdirs.
Expand Down
17 changes: 17 additions & 0 deletions test/testerrorlogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class TestErrorLogger : public TestFixture {
TEST_CASE(ErrorMessageVerboseNewline);
TEST_CASE(ErrorMessageFromInternalError);
TEST_CASE(ErrorMessageCode);
TEST_CASE(ErrorMessageNoCode);
TEST_CASE(CustomFormat);
TEST_CASE(CustomFormat2);
TEST_CASE(CustomFormatLocations);
Expand Down Expand Up @@ -386,6 +387,22 @@ class TestErrorLogger : public TestFixture {
msg.toString(false, "{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\n{code}", ""));
}

void ErrorMessageNoCode() const {
ScopedFile file("code.cpp",
"int i;\n"
"int i2;\n"
"int i3;\n"
);

ErrorMessage::FileLocation code{"code.cpp", 3, 5};
std::list<ErrorMessage::FileLocation> locs = { code };
ErrorMessage msg(std::move(locs), "", Severity::error, "Programming error.\nVerbose error", "errorId", Certainty::normal);
ASSERT_EQUALS(1, msg.callStack.size());
const bool noCode = true;
ASSERT_EQUALS("code.cpp:3:5: error: Programming error. [errorId]\n",
msg.toString(false, "{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\n{code}", "", noCode));
}

void CustomFormat() const {
std::list<ErrorMessage::FileLocation> locs(1, fooCpp5);
ErrorMessage msg(std::move(locs), "", Severity::error, "Programming error.\nVerbose error", "errorId", Certainty::normal);
Expand Down
Loading