diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index ecbe15f03..34f0a9cc5 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -567,6 +567,11 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) else if (std::strncmp(argv[i], "--output-file=", 14) == 0) mSettings->outputFile = Path::simplifyPath(Path::fromNativeSeparators(argv[i] + 14)); + // Experimental: limit execution time for extended valueflow analysis. basic valueflow analysis + // is always executed. + else if (std::strncmp(argv[i], "--performance-valueflow-max-time=", 33) == 0) + mSettings->performanceValueFlowMaxTime = std::atoi(argv[i] + 33); + // Specify platform else if (std::strncmp(argv[i], "--platform=", 11) == 0) { const std::string platform(11+argv[i]); diff --git a/lib/settings.cpp b/lib/settings.cpp index ae959b1f5..c2a68e5b1 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -60,6 +60,7 @@ Settings::Settings() maxConfigs(12), maxCtuDepth(2), maxTemplateRecursion(100), + performanceValueFlowMaxTime(-1), preprocessOnly(false), quiet(false), relativePaths(false), diff --git a/lib/settings.h b/lib/settings.h index 5338caeb9..4e6ceb279 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -234,6 +234,9 @@ public: /** @brief write results (--output-file=<file>) */ std::string outputFile; + /** @brief Experimental: --performance-valueflow-max-time=T */ + int performanceValueFlowMaxTime; + /** @brief plist output (--plist-output=<dir>) */ std::string plistOutput; diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 94c6a3dff..10c0f98d5 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -107,6 +107,7 @@ #include #include #include +#include #include #include #include @@ -8880,44 +8881,76 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase, valueFlowSameExpressions(tokenlist); valueFlowConditionExpressions(tokenlist, symboldatabase, errorLogger, settings); + const std::time_t stopTime = (settings->performanceValueFlowMaxTime >= 0) ? (std::time(nullptr) + settings->performanceValueFlowMaxTime) : (~0ULL/2); + std::size_t values = 0; std::size_t n = 4; while (n > 0 && values != getTotalValues(tokenlist)) { values = getTotalValues(tokenlist); - valueFlowImpossibleValues(tokenlist, settings); - valueFlowSymbolicOperators(tokenlist, symboldatabase); - valueFlowCondition(SymbolicConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings); - valueFlowSymbolicInfer(tokenlist, symboldatabase); - valueFlowArrayBool(tokenlist); - valueFlowArrayElement(tokenlist, settings); - valueFlowRightShift(tokenlist, settings); - valueFlowAfterAssign(tokenlist, symboldatabase, errorLogger, settings); - valueFlowAfterSwap(tokenlist, symboldatabase, errorLogger, settings); - valueFlowCondition(SimpleConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings); - valueFlowInferCondition(tokenlist, settings); - valueFlowSwitchVariable(tokenlist, symboldatabase, errorLogger, settings); - valueFlowForLoop(tokenlist, symboldatabase, errorLogger, settings); - valueFlowSubFunction(tokenlist, symboldatabase, errorLogger, settings); - valueFlowFunctionReturn(tokenlist, errorLogger); - valueFlowLifetime(tokenlist, symboldatabase, errorLogger, settings); - valueFlowFunctionDefaultParameter(tokenlist, symboldatabase); - valueFlowUninit(tokenlist, symboldatabase, settings); + + if (std::time(nullptr) < stopTime) + valueFlowImpossibleValues(tokenlist, settings); + if (std::time(nullptr) < stopTime) + valueFlowSymbolicOperators(tokenlist, symboldatabase); + if (std::time(nullptr) < stopTime) + valueFlowCondition(SymbolicConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings); + if (std::time(nullptr) < stopTime) + valueFlowSymbolicInfer(tokenlist, symboldatabase); + if (std::time(nullptr) < stopTime) + valueFlowArrayBool(tokenlist); + if (std::time(nullptr) < stopTime) + valueFlowArrayElement(tokenlist, settings); + if (std::time(nullptr) < stopTime) + valueFlowRightShift(tokenlist, settings); + if (std::time(nullptr) < stopTime) + valueFlowAfterAssign(tokenlist, symboldatabase, errorLogger, settings); + if (std::time(nullptr) < stopTime) + valueFlowAfterSwap(tokenlist, symboldatabase, errorLogger, settings); + if (std::time(nullptr) < stopTime) + valueFlowCondition(SimpleConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings); + if (std::time(nullptr) < stopTime) + valueFlowInferCondition(tokenlist, settings); + if (std::time(nullptr) < stopTime) + valueFlowSwitchVariable(tokenlist, symboldatabase, errorLogger, settings); + if (std::time(nullptr) < stopTime) + valueFlowForLoop(tokenlist, symboldatabase, errorLogger, settings); + if (std::time(nullptr) < stopTime) + valueFlowSubFunction(tokenlist, symboldatabase, errorLogger, settings); + if (std::time(nullptr) < stopTime) + valueFlowFunctionReturn(tokenlist, errorLogger); + if (std::time(nullptr) < stopTime) + valueFlowLifetime(tokenlist, symboldatabase, errorLogger, settings); + if (std::time(nullptr) < stopTime) + valueFlowFunctionDefaultParameter(tokenlist, symboldatabase); + if (std::time(nullptr) < stopTime) + valueFlowUninit(tokenlist, symboldatabase, settings); + if (tokenlist->isCPP()) { - valueFlowAfterMove(tokenlist, symboldatabase, settings); - valueFlowSmartPointer(tokenlist, errorLogger, settings); - valueFlowIterators(tokenlist, settings); - valueFlowCondition(IteratorConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings); - valueFlowIteratorInfer(tokenlist, settings); - valueFlowContainerSize(tokenlist, symboldatabase, errorLogger, settings); - valueFlowCondition(ContainerConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings); + if (std::time(nullptr) < stopTime) + valueFlowAfterMove(tokenlist, symboldatabase, settings); + if (std::time(nullptr) < stopTime) + valueFlowSmartPointer(tokenlist, errorLogger, settings); + if (std::time(nullptr) < stopTime) + valueFlowIterators(tokenlist, settings); + if (std::time(nullptr) < stopTime) + valueFlowCondition(IteratorConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings); + if (std::time(nullptr) < stopTime) + valueFlowIteratorInfer(tokenlist, settings); + if (std::time(nullptr) < stopTime) + valueFlowContainerSize(tokenlist, symboldatabase, errorLogger, settings); + if (std::time(nullptr) < stopTime) + valueFlowCondition(ContainerConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings); } - valueFlowSafeFunctions(tokenlist, symboldatabase, settings); + if (std::time(nullptr) < stopTime) + valueFlowSafeFunctions(tokenlist, symboldatabase, settings); n--; } - valueFlowDynamicBufferSize(tokenlist, symboldatabase, settings); + if (std::time(nullptr) < stopTime) + valueFlowDynamicBufferSize(tokenlist, symboldatabase, settings); - valueFlowDebug(tokenlist, errorLogger); + if (std::time(nullptr) < stopTime) + valueFlowDebug(tokenlist, errorLogger); } ValueFlow::Value ValueFlow::Value::unknown()