Skip to content

Commit ef97ebb

Browse files
firewaveweb-flow
authored andcommitted
fixed #14609 - valueflow.cpp: made timer results unique (cppcheck-opensource#8358)
1 parent 46e07c3 commit ef97ebb

2 files changed

Lines changed: 67 additions & 17 deletions

File tree

lib/valueflow.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,6 +1210,12 @@ static void valueFlowEnumValue(SymbolDatabase & symboldatabase, const Settings &
12101210
}
12111211
}
12121212

1213+
// trampoline to generate unique timer results entry
1214+
static void valueFlowEnumValueEarly(SymbolDatabase & symboldatabase, const Settings & settings)
1215+
{
1216+
valueFlowEnumValue(symboldatabase, settings);
1217+
}
1218+
12131219
static void valueFlowGlobalConstVar(TokenList& tokenList, const Settings& settings)
12141220
{
12151221
// Get variable values...
@@ -7200,7 +7206,7 @@ struct ValueFlowPassRunner {
72007206
bool run_once(std::initializer_list<ValuePtr<ValueFlowPass>> passes) const
72017207
{
72027208
return std::any_of(passes.begin(), passes.end(), [&](const ValuePtr<ValueFlowPass>& pass) {
7203-
return run(pass);
7209+
return run(pass, 0);
72047210
});
72057211
}
72067212

@@ -7210,10 +7216,11 @@ struct ValueFlowPassRunner {
72107216
std::size_t n = state.settings.vfOptions.maxIterations;
72117217
while (n > 0 && values != getTotalValues()) {
72127218
values = getTotalValues();
7213-
const std::string passnum = std::to_string(state.settings.vfOptions.maxIterations - n + 1);
7219+
const std::size_t passnum = state.settings.vfOptions.maxIterations - n + 1;
7220+
const std::string passnum_s = std::to_string(passnum);
72147221
if (std::any_of(passes.begin(), passes.end(), [&](const ValuePtr<ValueFlowPass>& pass) {
7215-
ProgressReporter progressReporter(state.errorLogger, state.settings.reportProgress, state.tokenlist.getSourceFilePath(), std::string("ValueFlow::") + pass->name() + (' ' + passnum));
7216-
return run(pass);
7222+
ProgressReporter progressReporter(state.errorLogger, state.settings.reportProgress, state.tokenlist.getSourceFilePath(), std::string("ValueFlow::") + pass->name() + (' ' + passnum_s));
7223+
return run(pass, passnum);
72177224
}))
72187225
return true;
72197226
--n;
@@ -7233,7 +7240,7 @@ struct ValueFlowPassRunner {
72337240
return false;
72347241
}
72357242

7236-
bool run(const ValuePtr<ValueFlowPass>& pass) const
7243+
bool run(const ValuePtr<ValueFlowPass>& pass, std::size_t it) const
72377244
{
72387245
auto start = Clock::now();
72397246
if (start > stop) {
@@ -7243,7 +7250,12 @@ struct ValueFlowPassRunner {
72437250
if (!state.tokenlist.isCPP() && pass->cpp())
72447251
return false;
72457252
if (timerResults) {
7246-
Timer t(pass->name(), state.settings.showtime, timerResults);
7253+
std::string name = pass->name();
7254+
if (it > 0) {
7255+
name += ' ';
7256+
name += std::to_string(it);
7257+
}
7258+
Timer t(name, state.settings.showtime, timerResults);
72477259
pass->run(state);
72487260
} else {
72497261
pass->run(state);
@@ -7375,7 +7387,7 @@ void ValueFlow::setValues(TokenList& tokenlist,
73757387

73767388
ValueFlowPassRunner runner{ValueFlowState{tokenlist, symboldatabase, errorLogger, settings}, timerResults};
73777389
runner.run_once({
7378-
VFA(valueFlowEnumValue(symboldatabase, settings)),
7390+
VFA(valueFlowEnumValueEarly(symboldatabase, settings)),
73797391
VFA(valueFlowNumber(tokenlist, settings)),
73807392
VFA(valueFlowString(tokenlist, settings)),
73817393
VFA(valueFlowTypeTraits(tokenlist, settings)),

test/cli/other_test.py

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -954,8 +954,11 @@ def test_unused_function_include(tmpdir):
954954
__test_unused_function_include(tmpdir, [])
955955

956956

957+
# TODO: test with clang-tidy
958+
# TODO: test with --addon
959+
# TODO: test with FileSettings
957960
# TODO: test with multiple files
958-
def __test_showtime(tmp_path, showtime, exp_len, exp_last, extra_args=None):
961+
def __test_showtime(tmp_path, showtime, exp_res, exp_last, extra_args=None):
959962
test_file = tmp_path / 'test.cpp'
960963
with open(test_file, 'wt') as f:
961964
f.write(
@@ -979,37 +982,40 @@ def __test_showtime(tmp_path, showtime, exp_len, exp_last, extra_args=None):
979982
exitcode, stdout, stderr = cppcheck(args)
980983
assert exitcode == 0
981984
lines = stdout.splitlines()
985+
exp_len = exp_res
986+
if exp_res:
987+
exp_len += 1 # empty line at the beginning - only added when individual results exist
982988
if 'cppcheck internal API usage' in stdout:
983989
exp_len += 1
990+
exp_len += 1 # last line
984991
assert len(lines) == exp_len
985-
idx_last = exp_len-1
986-
if idx_last:
992+
if exp_res:
987993
assert lines[0] == ''
988-
for i in range(1, idx_last):
994+
for i in range(1, exp_res):
989995
assert 'avg.' in lines[i]
990-
assert lines[idx_last].startswith(exp_last)
996+
assert lines[exp_len-1].startswith(exp_last)
991997
assert stderr == ''
992998

993999

9941000
def test_showtime_top5_file(tmp_path):
995-
__test_showtime(tmp_path, 'top5_file', 7, 'Check time: ')
1001+
__test_showtime(tmp_path, 'top5_file', 5, 'Check time: ')
9961002

9971003

9981004
# TODO: remove extra args when --executor=process works works
9991005
def test_showtime_top5_summary(tmp_path):
1000-
__test_showtime(tmp_path, 'top5_summary', 7, 'Overall time: ', ['-j1'])
1006+
__test_showtime(tmp_path, 'top5_summary', 5, 'Overall time: ', ['-j1'])
10011007

10021008

10031009
# TODO: remove when --executor=process works works
10041010
def test_showtime_top5_summary_j_thread(tmp_path):
1005-
__test_showtime(tmp_path, 'top5_summary', 7, 'Overall time: ', ['-j2', '--executor=thread'])
1011+
__test_showtime(tmp_path, 'top5_summary', 5, 'Overall time: ', ['-j2', '--executor=thread'])
10061012

10071013

10081014
# TODO: remove override when fixed
10091015
@pytest.mark.skipif(sys.platform == 'win32', reason="requires ProcessExecutor")
10101016
@pytest.mark.xfail(strict=True) # TODO: need to transfer the timer results to parent process - see #4452
10111017
def test_showtime_top5_summary_j_process(tmp_path):
1012-
__test_showtime(tmp_path, 'top5_summary', 7, 'Overall time: ', ['-j2', '--executor=process'])
1018+
__test_showtime(tmp_path, 'top5_summary', 5, 'Overall time: ', ['-j2', '--executor=process'])
10131019

10141020

10151021
def test_showtime_file(tmp_path):
@@ -1034,7 +1040,39 @@ def test_showtime_summary_j_process(tmp_path):
10341040

10351041

10361042
def test_showtime_file_total(tmp_path):
1037-
__test_showtime(tmp_path, 'file-total', 1, 'Check time: ')
1043+
__test_showtime(tmp_path, 'file-total', 0, 'Check time: ')
1044+
1045+
1046+
def test_showtime_unique(tmp_path):
1047+
test_file = tmp_path / 'test.cpp'
1048+
with open(test_file, 'wt') as f:
1049+
f.write(
1050+
"""
1051+
void f()
1052+
{
1053+
(void)(*((int*)0)); // cppcheck-suppress nullPointer
1054+
}
1055+
""")
1056+
1057+
args = [
1058+
'--showtime=summary',
1059+
'--quiet',
1060+
'--inline-suppr',
1061+
str(test_file)
1062+
]
1063+
1064+
exitcode, stdout, stderr = cppcheck(args)
1065+
assert exitcode == 0
1066+
multi_res = []
1067+
for line in stdout.splitlines():
1068+
# TODO: remove when we no longer emit empty line
1069+
if not line:
1070+
continue
1071+
if any(i in line for i in ['1 result(s)', 'Overall time:']):
1072+
continue
1073+
multi_res.append(line)
1074+
assert multi_res == []
1075+
assert stderr == ''
10381076

10391077

10401078
def test_missing_addon(tmpdir):

0 commit comments

Comments
 (0)