diff --git a/lib/forwardanalyzer.cpp b/lib/forwardanalyzer.cpp index db1b478c5..a57e4ddd1 100644 --- a/lib/forwardanalyzer.cpp +++ b/lib/forwardanalyzer.cpp @@ -12,6 +12,7 @@ struct ForwardTraversal { enum class Progress { Continue, Break, Skip }; ValuePtr analyzer; const Settings* settings; + ForwardAnalyzer::Action actions; std::pair evalCond(const Token* tok) { std::vector result = analyzer->evaluate(tok); @@ -115,6 +116,7 @@ struct ForwardTraversal { Progress update(Token* tok) { ForwardAnalyzer::Action action = analyzer->analyze(tok); + actions |= action; if (!action.isNone()) analyzer->update(tok, action); if (action.isInconclusive() && !analyzer->lowerToInconclusive()) @@ -225,6 +227,7 @@ struct ForwardTraversal { allAnalysis |= analyzeRecursive(initTok); if (stepTok) allAnalysis |= analyzeRecursive(stepTok); + actions |= allAnalysis; if (allAnalysis.isInconclusive()) { if (!analyzer->lowerToInconclusive()) return Progress::Break; @@ -552,8 +555,9 @@ struct ForwardTraversal { }; -void valueFlowGenericForward(Token* start, const Token* end, const ValuePtr& fa, const Settings* settings) +ForwardAnalyzer::Action valueFlowGenericForward(Token* start, const Token* end, const ValuePtr& fa, const Settings* settings) { ForwardTraversal ft{fa, settings}; ft.updateRange(start, end); + return ft.actions; } diff --git a/lib/forwardanalyzer.h b/lib/forwardanalyzer.h index fb400782d..d80ce8654 100644 --- a/lib/forwardanalyzer.h +++ b/lib/forwardanalyzer.h @@ -113,6 +113,6 @@ struct ForwardAnalyzer { virtual ~ForwardAnalyzer() {} }; -void valueFlowGenericForward(Token* start, const Token* end, const ValuePtr& fa, const Settings* settings); +ForwardAnalyzer::Action valueFlowGenericForward(Token* start, const Token* end, const ValuePtr& fa, const Settings* settings); #endif diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index a030003aa..57d1df0c3 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1710,7 +1710,7 @@ static void valueFlowGlobalStaticVar(TokenList *tokenList, const Settings *setti } } -static void valueFlowForwardVariable(Token* const startToken, +static ForwardAnalyzer::Action valueFlowForwardVariable(Token* const startToken, const Token* const endToken, const Variable* const var, std::list values, @@ -2697,7 +2697,7 @@ static std::vector getAliasesFromValues(std::list values, @@ -2705,20 +2705,22 @@ static void valueFlowForwardVariable(Token* const startToken, TokenList* const tokenlist, const Settings* const settings) { + ForwardAnalyzer::Action actions; for (ValueFlow::Value& v : values) { VariableForwardAnalyzer a(var, v, aliases, tokenlist); - valueFlowGenericForward(startToken, endToken, a, settings); + actions |= valueFlowGenericForward(startToken, endToken, a, settings); } + return actions; } -static void valueFlowForwardVariable(Token* const startToken, +static ForwardAnalyzer::Action valueFlowForwardVariable(Token* const startToken, const Token* const endToken, const Variable* const var, std::list values, TokenList* const tokenlist, const Settings* const settings) { - valueFlowForwardVariable(startToken, endToken, var, std::move(values), getAliasesFromValues(values), tokenlist, settings); + return valueFlowForwardVariable(startToken, endToken, var, std::move(values), getAliasesFromValues(values), tokenlist, settings); } // Old deprecated version @@ -2805,17 +2807,19 @@ struct ExpressionForwardAnalyzer : SingleValueFlowForwardAnalyzer { } }; -static void valueFlowForwardExpression(Token* startToken, +static ForwardAnalyzer::Action valueFlowForwardExpression(Token* startToken, const Token* endToken, const Token* exprTok, const std::list& values, const TokenList* const tokenlist, const Settings* settings) { + ForwardAnalyzer::Action actions; for (const ValueFlow::Value& v : values) { ExpressionForwardAnalyzer a(exprTok, v, tokenlist); - valueFlowGenericForward(startToken, endToken, a, settings); + actions |= valueFlowGenericForward(startToken, endToken, a, settings); } + return actions; } static const Token* parseBinaryIntOp(const Token* expr, MathLib::bigint& known) @@ -2879,7 +2883,7 @@ static const Token* solveExprValues(const Token* expr, std::list values, @@ -2888,14 +2892,14 @@ static void valueFlowForward(Token* startToken, { const Token* expr = solveExprValues(exprTok, values); if (expr->variable()) { - valueFlowForwardVariable(startToken, + return valueFlowForwardVariable(startToken, endToken, expr->variable(), values, tokenlist, settings); } else { - valueFlowForwardExpression(startToken, endToken, expr, values, tokenlist, settings); + return valueFlowForwardExpression(startToken, endToken, expr, values, tokenlist, settings); } } @@ -4554,9 +4558,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist, const Token* vartok, const std::list& values, bool) { - valueFlowForward(start->next(), stop, vartok, values, tokenlist, settings); - std::vector vars = getExprVariables(vartok, tokenlist, symboldatabase, settings); - return isVariablesChanged(start, stop, 0, vars, settings, tokenlist->isCPP()); + return valueFlowForward(start->next(), stop, vartok, values, tokenlist, settings).isModified(); }; handler.parse = [&](const Token *tok) { ValueFlowConditionHandler::Condition cond; @@ -5887,19 +5889,19 @@ struct ContainerVariableForwardAnalyzer : VariableForwardAnalyzer { } }; -static void valueFlowContainerForward(Token *tok, const Token* endToken, const Variable* var, ValueFlow::Value value, TokenList *tokenlist) +static ForwardAnalyzer::Action valueFlowContainerForward(Token *tok, const Token* endToken, const Variable* var, ValueFlow::Value value, TokenList *tokenlist) { ContainerVariableForwardAnalyzer a(var, value, getAliasesFromValues({value}), tokenlist); - valueFlowGenericForward(tok, endToken, a, tokenlist->getSettings()); + return valueFlowGenericForward(tok, endToken, a, tokenlist->getSettings()); } -static void valueFlowContainerForward(Token *tok, const Variable* var, ValueFlow::Value value, TokenList *tokenlist) +static ForwardAnalyzer::Action valueFlowContainerForward(Token *tok, const Variable* var, ValueFlow::Value value, TokenList *tokenlist) { const Token * endOfVarScope = nullptr; if (var->isLocal() || var->isArgument()) endOfVarScope = var->scope()->bodyEnd; if (!endOfVarScope) endOfVarScope = tok->scope()->bodyEnd; - valueFlowContainerForward(tok, endOfVarScope, var, std::move(value), tokenlist); + return valueFlowContainerForward(tok, endOfVarScope, var, std::move(value), tokenlist); } static bool isContainerSizeChanged(const Token *tok, int depth) @@ -6053,9 +6055,7 @@ static void valueFlowIteratorAfterCondition(TokenList *tokenlist, const Token* vartok, const std::list& values, bool) { - valueFlowForward(start->next(), stop, vartok, values, tokenlist, settings); - std::vector vars = getExprVariables(vartok, tokenlist, symboldatabase, settings); - return isVariablesChanged(start, stop, 0, vars, settings, tokenlist->isCPP()); + return valueFlowForward(start->next(), stop, vartok, values, tokenlist, settings).isModified(); }; handler.parse = [&](const Token *tok) { ValueFlowConditionHandler::Condition cond; @@ -6230,8 +6230,7 @@ static void valueFlowContainerAfterCondition(TokenList *tokenlist, const Variable* var = vartok->variable(); if (!var) return false; - valueFlowContainerForward(start->next(), stop, var, values.front(), tokenlist); - return isContainerSizeChanged(var->declarationId(), start, stop); + return valueFlowContainerForward(start->next(), stop, var, values.front(), tokenlist).isModified(); }; handler.parse = [&](const Token *tok) { ValueFlowConditionHandler::Condition cond; diff --git a/test/testother.cpp b/test/testother.cpp index 22b5f7c76..d575a0838 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -697,6 +697,16 @@ private: " a = b / -x;\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + check("struct A {\n" + " int x;\n" + "};\n" + "int f(A* a) {\n" + " if (a->x == 0) \n" + " a->x = 1;\n" + " return 1/a->x;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void nanInArithmeticExpression() {