Skip to content
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
15 changes: 15 additions & 0 deletions cli/cmdlineparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,21 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
}
}

else if (std::strncmp(argv[i], "--valueflow-max-iterations=", 27) == 0) {
long tmp;
try {
tmp = std::stol(argv[i] + 27);
} catch (const std::invalid_argument &) {
printError("argument to '--valueflow-max-iteration' is invalid.");
return false;
}
if (tmp < 0) {
printError("argument to '--valueflow-max-iteration' needs to be at least 0.");
return false;
}
mSettings->valueFlowMaxIterations = static_cast<std::size_t>(tmp);
}

else if (std::strcmp(argv[i], "-v") == 0 || std::strcmp(argv[i], "--verbose") == 0)
mSettings->verbose = true;

Expand Down
1 change: 1 addition & 0 deletions lib/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Settings::Settings()
relativePaths(false),
reportProgress(false),
showtime(SHOWTIME_MODES::SHOWTIME_NONE),
valueFlowMaxIterations(4),
verbose(false),
xml(false),
xml_version(2)
Expand Down
3 changes: 3 additions & 0 deletions lib/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,9 @@ class CPPCHECKLIB Settings : public cppcheck::Platform {
/** @brief forced includes given by the user */
std::list<std::string> userIncludes;

/** @brief the maximum iterations of valueflow (--valueflow-max-iterations=T) */
std::size_t valueFlowMaxIterations;

/** @brief Is --verbose given? */
bool verbose;

Expand Down
14 changes: 13 additions & 1 deletion lib/valueflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8887,7 +8887,7 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
const std::uint64_t stopTime = getValueFlowStopTime(settings);

std::size_t values = 0;
std::size_t n = 4;
std::size_t n = settings->valueFlowMaxIterations;
while (n > 0 && values != getTotalValues(tokenlist)) {
values = getTotalValues(tokenlist);

Expand Down Expand Up @@ -8949,6 +8949,18 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
n--;
}

if (settings->debugwarnings) {
if (n == 0 && values != getTotalValues(tokenlist)) {
ErrorMessage errmsg({},
emptyString,
Severity::debug,
"ValueFlow maximum iterations exceeded",
"valueFlowMaxIterations",
Certainty::normal);
errorLogger->reportErr(errmsg);
}
}

if (std::time(nullptr) < stopTime)
valueFlowDynamicBufferSize(tokenlist, symboldatabase, settings);

Expand Down
44 changes: 44 additions & 0 deletions test/testcmdlineparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ class TestCmdlineParser : public TestFixture {
TEST_CASE(clang);
TEST_CASE(clang2);
TEST_CASE(clangInvalid);
TEST_CASE(valueFlowMaxIterations);
TEST_CASE(valueFlowMaxIterations2);
TEST_CASE(valueFlowMaxIterationsInvalid);
TEST_CASE(valueFlowMaxIterationsInvalid2);
TEST_CASE(valueFlowMaxIterationsInvalid3);

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

void valueFlowMaxIterations() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=0"};
settings.valueFlowMaxIterations = -1;
ASSERT(defParser.parseFromArgs(2, argv));
ASSERT_EQUALS(0, settings.valueFlowMaxIterations);
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
}

void valueFlowMaxIterations2() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=11"};
settings.valueFlowMaxIterations = -1;
ASSERT(defParser.parseFromArgs(2, argv));
ASSERT_EQUALS(11, settings.valueFlowMaxIterations);
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
}

void valueFlowMaxIterationsInvalid() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--valueflow-max-iterations"};
ASSERT(!defParser.parseFromArgs(2, argv));
ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--valueflow-max-iterations\".\n", GET_REDIRECT_OUTPUT);
}

void valueFlowMaxIterationsInvalid2() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=seven"};
ASSERT(!defParser.parseFromArgs(2, argv));
ASSERT_EQUALS("cppcheck: error: argument to '--valueflow-max-iteration' is invalid.\n", GET_REDIRECT_OUTPUT);
}

void valueFlowMaxIterationsInvalid3() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=-1"};
ASSERT(!defParser.parseFromArgs(2, argv));
ASSERT_EQUALS("cppcheck: error: argument to '--valueflow-max-iteration' needs to be at least 0.\n", GET_REDIRECT_OUTPUT);
}

/*
void ignorepaths1() {
REDIRECT;
Expand Down