Skip to content

Commit 347a12f

Browse files
committed
added command-line option --valueflow-max-iterations to control amount of valueflow iterations / also log debug warning when iterations are being exceeded
1 parent 6a01fa9 commit 347a12f

5 files changed

Lines changed: 76 additions & 1 deletion

File tree

cli/cmdlineparser.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,21 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
904904
}
905905
}
906906

907+
else if (std::strncmp(argv[i], "--valueflow-max-iterations=", 27) == 0) {
908+
long tmp;
909+
try {
910+
tmp = std::stol(argv[i] + 27);
911+
} catch (const std::invalid_argument &) {
912+
printError("argument to '--valueflow-max-iteration' is invalid.");
913+
return false;
914+
}
915+
if (tmp < 0) {
916+
printError("argument to '--valueflow-max-iteration' needs to be at least 0.");
917+
return false;
918+
}
919+
mSettings->valueFlowMaxIterations = static_cast<std::size_t>(tmp);
920+
}
921+
907922
else if (std::strcmp(argv[i], "-v") == 0 || std::strcmp(argv[i], "--verbose") == 0)
908923
mSettings->verbose = true;
909924

lib/settings.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ Settings::Settings()
6666
relativePaths(false),
6767
reportProgress(false),
6868
showtime(SHOWTIME_MODES::SHOWTIME_NONE),
69+
valueFlowMaxIterations(4),
6970
verbose(false),
7071
xml(false),
7172
xml_version(2)

lib/settings.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,9 @@ class CPPCHECKLIB Settings : public cppcheck::Platform {
350350
/** @brief forced includes given by the user */
351351
std::list<std::string> userIncludes;
352352

353+
/** @brief the maximum iterations of valueflow (--valueflow-max-iterations=T) */
354+
std::size_t valueFlowMaxIterations;
355+
353356
/** @brief Is --verbose given? */
354357
bool verbose;
355358

lib/valueflow.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8887,7 +8887,7 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
88878887
const std::uint64_t stopTime = getValueFlowStopTime(settings);
88888888

88898889
std::size_t values = 0;
8890-
std::size_t n = 4;
8890+
int n = settings->valueFlowMaxIterations;
88918891
while (n > 0 && values != getTotalValues(tokenlist)) {
88928892
values = getTotalValues(tokenlist);
88938893

@@ -8949,6 +8949,18 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
89498949
n--;
89508950
}
89518951

8952+
if (settings->debugwarnings) {
8953+
if (n == 0 && values != getTotalValues(tokenlist)) {
8954+
ErrorMessage errmsg({},
8955+
emptyString,
8956+
Severity::debug,
8957+
"ValueFlow maximum iterations exceeded",
8958+
"valueFlowMaxIterations",
8959+
Certainty::normal);
8960+
errorLogger->reportErr(errmsg);
8961+
}
8962+
}
8963+
89528964
if (std::time(nullptr) < stopTime)
89538965
valueFlowDynamicBufferSize(tokenlist, symboldatabase, settings);
89548966

test/testcmdlineparser.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ class TestCmdlineParser : public TestFixture {
153153
TEST_CASE(clang);
154154
TEST_CASE(clang2);
155155
TEST_CASE(clangInvalid);
156+
TEST_CASE(valueFlowMaxIterations);
157+
TEST_CASE(valueFlowMaxIterations2);
158+
TEST_CASE(valueFlowMaxIterationsInvalid);
159+
TEST_CASE(valueFlowMaxIterationsInvalid2);
160+
TEST_CASE(valueFlowMaxIterationsInvalid3);
156161

157162
// TODO
158163
// Disabling these tests since they use relative paths to the
@@ -1278,6 +1283,45 @@ class TestCmdlineParser : public TestFixture {
12781283
ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--clang-foo\".\n", GET_REDIRECT_OUTPUT);
12791284
}
12801285

1286+
void valueFlowMaxIterations() {
1287+
REDIRECT;
1288+
const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=0"};
1289+
settings.valueFlowMaxIterations = -1;
1290+
ASSERT(defParser.parseFromArgs(2, argv));
1291+
ASSERT_EQUALS(0, settings.valueFlowMaxIterations);
1292+
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
1293+
}
1294+
1295+
void valueFlowMaxIterations2() {
1296+
REDIRECT;
1297+
const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=11"};
1298+
settings.valueFlowMaxIterations = -1;
1299+
ASSERT(defParser.parseFromArgs(2, argv));
1300+
ASSERT_EQUALS(11, settings.valueFlowMaxIterations);
1301+
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
1302+
}
1303+
1304+
void valueFlowMaxIterationsInvalid() {
1305+
REDIRECT;
1306+
const char * const argv[] = {"cppcheck", "--valueflow-max-iterations"};
1307+
ASSERT(!defParser.parseFromArgs(2, argv));
1308+
ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--valueflow-max-iterations\".\n", GET_REDIRECT_OUTPUT);
1309+
}
1310+
1311+
void valueFlowMaxIterationsInvalid2() {
1312+
REDIRECT;
1313+
const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=seven"};
1314+
ASSERT(!defParser.parseFromArgs(2, argv));
1315+
ASSERT_EQUALS("cppcheck: error: argument to '--valueflow-max-iteration' is invalid.\n", GET_REDIRECT_OUTPUT);
1316+
}
1317+
1318+
void valueFlowMaxIterationsInvalid3() {
1319+
REDIRECT;
1320+
const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=-1"};
1321+
ASSERT(!defParser.parseFromArgs(2, argv));
1322+
ASSERT_EQUALS("cppcheck: error: argument to '--valueflow-max-iteration' needs to be at least 0.\n", GET_REDIRECT_OUTPUT);
1323+
}
1324+
12811325
/*
12821326
void ignorepaths1() {
12831327
REDIRECT;

0 commit comments

Comments
 (0)