@@ -5747,9 +5747,15 @@ static bool intersects(const C1& c1, const C2& c2)
57475747 return false ;
57485748}
57495749
5750- static void valueFlowAfterAssign (TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
5750+ static void valueFlowAfterAssign (TokenList *tokenlist,
5751+ SymbolDatabase* symboldatabase,
5752+ ErrorLogger *errorLogger,
5753+ const Settings *settings,
5754+ const std::set<const Scope*>& skippedFunctions)
57515755{
57525756 for (const Scope * scope : symboldatabase->functionScopes ) {
5757+ if (skippedFunctions.count (scope))
5758+ continue ;
57535759 std::unordered_map<nonneg int , std::unordered_set<nonneg int >> backAssigns;
57545760 for (Token* tok = const_cast <Token*>(scope->bodyStart ); tok != scope->bodyEnd ; tok = tok->next ()) {
57555761 // Assignment
@@ -6051,9 +6057,12 @@ struct ConditionHandler {
60516057 void traverseCondition (TokenList* tokenlist,
60526058 SymbolDatabase* symboldatabase,
60536059 const Settings* settings,
6060+ const std::set<const Scope*>& skippedFunctions,
60546061 const std::function<void (const Condition& cond, Token* tok, const Scope* scope)>& f) const
60556062 {
60566063 for (const Scope *scope : symboldatabase->functionScopes ) {
6064+ if (skippedFunctions.count (scope))
6065+ continue ;
60576066 for (Token *tok = const_cast <Token *>(scope->bodyStart ); tok != scope->bodyEnd ; tok = tok->next ()) {
60586067 if (Token::Match (tok, " if|while|for (" ))
60596068 continue ;
@@ -6086,8 +6095,9 @@ struct ConditionHandler {
60866095 void beforeCondition (TokenList* tokenlist,
60876096 SymbolDatabase* symboldatabase,
60886097 ErrorLogger* errorLogger,
6089- const Settings* settings) const {
6090- traverseCondition (tokenlist, symboldatabase, settings, [&](const Condition& cond, Token* tok, const Scope*) {
6098+ const Settings* settings,
6099+ const std::set<const Scope*>& skippedFunctions) const {
6100+ traverseCondition (tokenlist, symboldatabase, settings, skippedFunctions, [&](const Condition& cond, Token* tok, const Scope*) {
60916101 if (cond.vartok ->exprId () == 0 )
60926102 return ;
60936103
@@ -6233,8 +6243,9 @@ struct ConditionHandler {
62336243 void afterCondition (TokenList* tokenlist,
62346244 SymbolDatabase* symboldatabase,
62356245 ErrorLogger* errorLogger,
6236- const Settings* settings) const {
6237- traverseCondition (tokenlist, symboldatabase, settings, [&](const Condition& cond, Token* condTok, const Scope* scope) {
6246+ const Settings* settings,
6247+ const std::set<const Scope*>& skippedFunctions) const {
6248+ traverseCondition (tokenlist, symboldatabase, settings, skippedFunctions, [&](const Condition& cond, Token* condTok, const Scope* scope) {
62386249 const Token* top = condTok->astTop ();
62396250
62406251 const MathLib::bigint path = cond.getPath ();
@@ -6564,10 +6575,11 @@ static void valueFlowCondition(const ValuePtr<ConditionHandler>& handler,
65646575 TokenList* tokenlist,
65656576 SymbolDatabase* symboldatabase,
65666577 ErrorLogger* errorLogger,
6567- const Settings* settings)
6578+ const Settings* settings,
6579+ const std::set<const Scope*>& skippedFunctions)
65686580{
6569- handler->beforeCondition (tokenlist, symboldatabase, errorLogger, settings);
6570- handler->afterCondition (tokenlist, symboldatabase, errorLogger, settings);
6581+ handler->beforeCondition (tokenlist, symboldatabase, errorLogger, settings, skippedFunctions );
6582+ handler->afterCondition (tokenlist, symboldatabase, errorLogger, settings, skippedFunctions );
65716583}
65726584
65736585struct SimpleConditionHandler : ConditionHandler {
@@ -8966,6 +8978,36 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
89668978
89678979 const std::uint64_t stopTime = getValueFlowStopTime (settings);
89688980
8981+ std::set<const Scope*> skippedFunctions;
8982+ if (settings->performanceValueFlowMaxIfCount < 1000 ) {
8983+ for (const Scope* functionScope: symboldatabase->functionScopes ) {
8984+ int countIfScopes = 0 ;
8985+ std::vector<const Scope*> scopes{functionScope};
8986+ while (!scopes.empty ()) {
8987+ const Scope* s = scopes.back ();
8988+ scopes.pop_back ();
8989+ for (const Scope* s2: s->nestedList ) {
8990+ scopes.emplace_back (s2);
8991+ if (s2->type == Scope::ScopeType::eIf)
8992+ ++countIfScopes;
8993+ }
8994+ }
8995+ if (countIfScopes > settings->performanceValueFlowMaxIfCount ) {
8996+ skippedFunctions.emplace (functionScope);
8997+
8998+ const std::string& functionName = functionScope->className ;
8999+ const std::list<ErrorMessage::FileLocation> callstack (1 , ErrorMessage::FileLocation (functionScope->bodyStart , tokenlist));
9000+ const ErrorMessage errmsg (callstack, tokenlist->getSourceFilePath (), Severity::information,
9001+ " ValueFlow analysis is limited in " + functionName + " because if-count in function " +
9002+ std::to_string (countIfScopes) + " exceeds limit " +
9003+ std::to_string (settings->performanceValueFlowMaxIfCount ) + " . The limit can be adjusted with "
9004+ " --performance-valueflow-max-if-count. Increasing the if-count limit will likely increase the "
9005+ " analysis time." , " performanceValueflowMaxIfCountExceeded" , Certainty::normal);
9006+ errorLogger->reportErr (errmsg);
9007+ }
9008+ }
9009+ }
9010+
89699011 std::size_t values = 0 ;
89709012 std::size_t n = settings->valueFlowMaxIterations ;
89719013 while (n > 0 && values != getTotalValues (tokenlist)) {
@@ -8976,7 +9018,7 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
89769018 if (std::time (nullptr ) < stopTime)
89779019 valueFlowSymbolicOperators (symboldatabase, settings);
89789020 if (std::time (nullptr ) < stopTime)
8979- valueFlowCondition (SymbolicConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings);
9021+ valueFlowCondition (SymbolicConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions );
89809022 if (std::time (nullptr ) < stopTime)
89819023 valueFlowSymbolicInfer (symboldatabase, settings);
89829024 if (std::time (nullptr ) < stopTime)
@@ -8986,11 +9028,11 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
89869028 if (std::time (nullptr ) < stopTime)
89879029 valueFlowRightShift (tokenlist, settings);
89889030 if (std::time (nullptr ) < stopTime)
8989- valueFlowAfterAssign (tokenlist, symboldatabase, errorLogger, settings);
9031+ valueFlowAfterAssign (tokenlist, symboldatabase, errorLogger, settings, skippedFunctions );
89909032 if (std::time (nullptr ) < stopTime)
89919033 valueFlowAfterSwap (tokenlist, symboldatabase, errorLogger, settings);
89929034 if (std::time (nullptr ) < stopTime)
8993- valueFlowCondition (SimpleConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings);
9035+ valueFlowCondition (SimpleConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions );
89949036 if (std::time (nullptr ) < stopTime)
89959037 valueFlowInferCondition (tokenlist, settings);
89969038 if (std::time (nullptr ) < stopTime)
@@ -9016,13 +9058,13 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
90169058 if (std::time (nullptr ) < stopTime)
90179059 valueFlowIterators (tokenlist, settings);
90189060 if (std::time (nullptr ) < stopTime)
9019- valueFlowCondition (IteratorConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings);
9061+ valueFlowCondition (IteratorConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions );
90209062 if (std::time (nullptr ) < stopTime)
90219063 valueFlowIteratorInfer (tokenlist, settings);
9022- if (std::time (nullptr ) < stopTime)
9064+ if (std::time (nullptr ) < stopTime && skippedFunctions. empty () )
90239065 valueFlowContainerSize (tokenlist, symboldatabase, errorLogger, settings);
90249066 if (std::time (nullptr ) < stopTime)
9025- valueFlowCondition (ContainerConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings);
9067+ valueFlowCondition (ContainerConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions );
90269068 }
90279069 if (std::time (nullptr ) < stopTime)
90289070 valueFlowSafeFunctions (tokenlist, symboldatabase, settings);
0 commit comments