diff --git a/lib/astutils.cpp b/lib/astutils.cpp index bebb1227b..eb3fe40f7 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -398,6 +398,16 @@ bool isReturnScope(const Token * const endToken) return false; } +bool isVariableChangedByFunctionCall(const Token *tok, unsigned int varid, const Settings *settings, bool *inconclusive) +{ + if (!tok) + return false; + if (tok->varId() == varid) + return isVariableChangedByFunctionCall(tok, settings, inconclusive); + return isVariableChangedByFunctionCall(tok->astOperand1(), varid, settings, inconclusive) || + isVariableChangedByFunctionCall(tok->astOperand2(), varid, settings, inconclusive); +} + bool isVariableChangedByFunctionCall(const Token *tok, const Settings *settings, bool *inconclusive) { if (!tok) @@ -411,7 +421,17 @@ bool isVariableChangedByFunctionCall(const Token *tok, const Settings *settings, ; else if (Token::Match(tok->tokAt(addressOf?-2:-1), "[(,] &| %name% [,)]")) ; - else + else if (Token::Match(tok->tokAt(addressOf?-2:-1), "[?:] &| %name% [:,)]")) { + const Token *parent = tok->astParent(); + if (parent == tok->previous() && parent->str() == "&") + parent = parent->astParent(); + while (Token::Match(parent, "[?:]")) + parent = parent->astParent(); + while (Token::simpleMatch(parent, ",")) + parent = parent->astParent(); + if (!parent || parent->str() != "(") + return false; + } else return false; // reinterpret_cast etc.. diff --git a/lib/astutils.h b/lib/astutils.h index f360d7a0b..8895b9a09 100644 --- a/lib/astutils.h +++ b/lib/astutils.h @@ -74,6 +74,17 @@ bool isWithoutSideEffects(bool cpp, const Token* tok); /** Is scope a return scope (scope will unconditionally return) */ bool isReturnScope(const Token *endToken); +/** Is variable changed by function call? + * In case the answer of the question is inconclusive, e.g. because the function declaration is not known + * the return value is false and the output parameter inconclusive is set to true + * + * @param tok ast tree + * @param varid Variable Id + * @param settings program settings + * @param inconclusive pointer to output variable which indicates that the answer of the question is inconclusive + */ +bool isVariableChangedByFunctionCall(const Token *tok, unsigned int varid, const Settings *settings, bool *inconclusive); + /** Is variable changed by function call? * In case the answer of the question is inconclusive, e.g. because the function declaration is not known * the return value is false and the output parameter inconclusive is set to true diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 3709c1a1c..b3a4bed8a 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -115,27 +115,6 @@ static void changeKnownToPossible(std::list &values) it->changeKnownToPossible(); } -static bool mightBeNonConstPointerFunctionArg(const Token *tok) -{ - // TODO: check if argument might be non-const pointer - const Token *parent = tok->astParent(); - while (parent && parent->str() == ",") - parent = parent->astParent(); - return (parent && Token::Match(parent->previous(), "%name% (")); -} - -static const Token *findVariableInAST(const Token *tok, unsigned int varid) -{ - if (!tok) - return nullptr; - if (tok->varId() == varid) - return tok; - const Token *ret1 = findVariableInAST(tok->astOperand1(), varid); - if (ret1) - return ret1; - return findVariableInAST(tok->astOperand2(), varid); -} - /** * Is condition always false when variable has given value? * \param condition top ast token in condition @@ -1858,7 +1837,7 @@ static bool valueFlowForward(Token * const startToken, std::list::const_iterator it; for (it = values.begin(); it != values.end(); ++it) valueFlowAST(const_cast(expr), varid, *it, settings); - if ((expr->valueType() && expr->valueType()->pointer) && mightBeNonConstPointerFunctionArg(tok2) && findVariableInAST(expr,varid)) + if (isVariableChangedByFunctionCall(expr, varid, settings, nullptr)) changeKnownToPossible(values); } else { std::list::const_iterator it; @@ -1871,8 +1850,7 @@ static bool valueFlowForward(Token * const startToken, else valueFlowAST(const_cast(op2), varid, *it, settings); } - - if (mightBeNonConstPointerFunctionArg(tok2) && findVariableInAST(op2,varid)) + if (isVariableChangedByFunctionCall(op2, varid, settings, nullptr)) changeKnownToPossible(values); }