Skip to content

Commit b380fd2

Browse files
authored
added command-line option --valueflow-max-iterations to control amount of valueflow iterations / also log debug warning when iterations are being exceeded (#4557)
1 parent 3c68b9b commit b380fd2

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
@@ -915,6 +915,21 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
915915
}
916916
}
917917

918+
else if (std::strncmp(argv[i], "--valueflow-max-iterations=", 27) == 0) {
919+
long tmp;
920+
try {
921+
tmp = std::stol(argv[i] + 27);
922+
} catch (const std::invalid_argument &) {
923+
printError("argument to '--valueflow-max-iteration' is invalid.");
924+
return false;
925+
}
926+
if (tmp < 0) {
927+
printError("argument to '--valueflow-max-iteration' needs to be at least 0.");
928+
return false;
929+
}
930+
mSettings->valueFlowMaxIterations = static_cast<std::size_t>(tmp);
931+
}
932+
918933
else if (std::strcmp(argv[i], "-v") == 0 || std::strcmp(argv[i], "--verbose") == 0)
919934
mSettings->verbose = true;
920935

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
@@ -351,6 +351,9 @@ class CPPCHECKLIB Settings : public cppcheck::Platform {
351351
/** @brief forced includes given by the user */
352352
std::list<std::string> userIncludes;
353353

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

lib/valueflow.cpp

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

89888988
std::size_t values = 0;
8989-
std::size_t n = 4;
8989+
std::size_t n = settings->valueFlowMaxIterations;
89908990
while (n > 0 && values != getTotalValues(tokenlist)) {
89918991
values = getTotalValues(tokenlist);
89928992

@@ -9048,6 +9048,18 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
90489048
n--;
90499049
}
90509050

9051+
if (settings->debugwarnings) {
9052+
if (n == 0 && values != getTotalValues(tokenlist)) {
9053+
ErrorMessage errmsg({},
9054+
emptyString,
9055+
Severity::debug,
9056+
"ValueFlow maximum iterations exceeded",
9057+
"valueFlowMaxIterations",
9058+
Certainty::normal);
9059+
errorLogger->reportErr(errmsg);
9060+
}
9061+
}
9062+
90519063
if (std::time(nullptr) < stopTime)
90529064
valueFlowDynamicBufferSize(tokenlist, symboldatabase, settings);
90539065

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
@@ -1260,6 +1265,45 @@ class TestCmdlineParser : public TestFixture {
12601265
ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--clang-foo\".\n", GET_REDIRECT_OUTPUT);
12611266
}
12621267

1268+
void valueFlowMaxIterations() {
1269+
REDIRECT;
1270+
const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=0"};
1271+
settings.valueFlowMaxIterations = -1;
1272+
ASSERT(defParser.parseFromArgs(2, argv));
1273+
ASSERT_EQUALS(0, settings.valueFlowMaxIterations);
1274+
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
1275+
}
1276+
1277+
void valueFlowMaxIterations2() {
1278+
REDIRECT;
1279+
const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=11"};
1280+
settings.valueFlowMaxIterations = -1;
1281+
ASSERT(defParser.parseFromArgs(2, argv));
1282+
ASSERT_EQUALS(11, settings.valueFlowMaxIterations);
1283+
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
1284+
}
1285+
1286+
void valueFlowMaxIterationsInvalid() {
1287+
REDIRECT;
1288+
const char * const argv[] = {"cppcheck", "--valueflow-max-iterations"};
1289+
ASSERT(!defParser.parseFromArgs(2, argv));
1290+
ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--valueflow-max-iterations\".\n", GET_REDIRECT_OUTPUT);
1291+
}
1292+
1293+
void valueFlowMaxIterationsInvalid2() {
1294+
REDIRECT;
1295+
const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=seven"};
1296+
ASSERT(!defParser.parseFromArgs(2, argv));
1297+
ASSERT_EQUALS("cppcheck: error: argument to '--valueflow-max-iteration' is invalid.\n", GET_REDIRECT_OUTPUT);
1298+
}
1299+
1300+
void valueFlowMaxIterationsInvalid3() {
1301+
REDIRECT;
1302+
const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=-1"};
1303+
ASSERT(!defParser.parseFromArgs(2, argv));
1304+
ASSERT_EQUALS("cppcheck: error: argument to '--valueflow-max-iteration' needs to be at least 0.\n", GET_REDIRECT_OUTPUT);
1305+
}
1306+
12631307
/*
12641308
void ignorepaths1() {
12651309
REDIRECT;

0 commit comments

Comments
 (0)