Fixed #7006 (False positive Mismatching assignment and comparison (variable is changed in loop))
This commit is contained in:
parent
00a47546f8
commit
b9b0964dab
|
@ -271,3 +271,36 @@ bool isWithoutSideEffects(bool cpp, const Token* tok)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool isVariableChanged(const Token *start, const Token *end, const unsigned int varid)
|
||||
{
|
||||
for (const Token *tok = start; tok != end; tok = tok->next()) {
|
||||
if (tok->varId() == varid) {
|
||||
if (Token::Match(tok, "%name% =|++|--"))
|
||||
return true;
|
||||
|
||||
if (Token::Match(tok->previous(), "++|-- %name%"))
|
||||
return true;
|
||||
|
||||
if (Token::Match(tok->tokAt(-2), "[(,] & %var% [,)]"))
|
||||
return true; // TODO: check if function parameter is const
|
||||
|
||||
if (Token::Match(tok->previous(), "[(,] %var% [,)]")) {
|
||||
const Token *parent = tok->astParent();
|
||||
while (parent && parent->str() == ",")
|
||||
parent = parent->astParent();
|
||||
if (parent && parent->str() == "(") {
|
||||
if (parent->astOperand1() && parent->astOperand1()->isName() && !parent->astOperand1()->function())
|
||||
return true;
|
||||
// TODO: check if function parameter is non-const reference etc..
|
||||
}
|
||||
}
|
||||
|
||||
const Token *parent = tok->astParent();
|
||||
while (Token::Match(parent, ".|::"))
|
||||
parent = parent->astParent();
|
||||
if (parent && parent->tokType() == Token::eIncDecOp)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -64,4 +64,7 @@ bool isConstExpression(const Token *tok, const std::set<std::string> &constFunct
|
|||
|
||||
bool isWithoutSideEffects(bool cpp, const Token* tok);
|
||||
|
||||
/** Is variable changed in block of code? */
|
||||
bool isVariableChanged(const Token *start, const Token *end, const unsigned int varid);
|
||||
|
||||
#endif // astutilsH
|
||||
|
|
|
@ -142,6 +142,13 @@ bool CheckCondition::assignIfParseScope(const Token * const assignTok,
|
|||
if (Token::Match(tok2, "if|while (")) {
|
||||
if (!islocal && tok2->str() == "while")
|
||||
continue;
|
||||
if (tok2->str() == "while") {
|
||||
// is variable changed in loop?
|
||||
const Token *bodyStart = tok2->linkAt(1)->next();
|
||||
const Token *bodyEnd = bodyStart ? bodyStart->link() : nullptr;
|
||||
if (!bodyEnd || bodyEnd->str() != "}" || isVariableChanged(bodyStart, bodyEnd, varid))
|
||||
continue;
|
||||
}
|
||||
|
||||
// parse condition
|
||||
const Token * const end = tok2->next()->link();
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
#include "valueflow.h"
|
||||
#include "astutils.h"
|
||||
#include "errorlogger.h"
|
||||
#include "mathlib.h"
|
||||
#include "settings.h"
|
||||
|
@ -321,40 +322,6 @@ static bool isReturn(const Token *tok)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool isVariableChanged(const Token *start, const Token *end, const unsigned int varid)
|
||||
{
|
||||
for (const Token *tok = start; tok != end; tok = tok->next()) {
|
||||
if (tok->varId() == varid) {
|
||||
if (Token::Match(tok, "%name% =|++|--"))
|
||||
return true;
|
||||
|
||||
if (Token::Match(tok->previous(), "++|-- %name%"))
|
||||
return true;
|
||||
|
||||
if (Token::Match(tok->tokAt(-2), "[(,] & %var% [,)]"))
|
||||
return true; // TODO: check if function parameter is const
|
||||
|
||||
if (Token::Match(tok->previous(), "[(,] %var% [,)]")) {
|
||||
const Token *parent = tok->astParent();
|
||||
while (parent && parent->str() == ",")
|
||||
parent = parent->astParent();
|
||||
if (parent && parent->str() == "(") {
|
||||
if (parent->astOperand1() && parent->astOperand1()->isName() && !parent->astOperand1()->function())
|
||||
return true;
|
||||
// TODO: check if function parameter is non-const reference etc..
|
||||
}
|
||||
}
|
||||
|
||||
const Token *parent = tok->astParent();
|
||||
while (Token::Match(parent, ".|::"))
|
||||
parent = parent->astParent();
|
||||
if (parent && parent->tokType() == Token::eIncDecOp)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Add token value. Return true if value is added. */
|
||||
static bool addValue(Token *tok, const ValueFlow::Value &value)
|
||||
{
|
||||
|
|
|
@ -178,6 +178,15 @@ private:
|
|||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("void f(int x) {\n"
|
||||
" int a = 100;\n"
|
||||
" while (x) {\n"
|
||||
" int y = 16 | a;\n"
|
||||
" while (y != 0) y--;\n"
|
||||
" }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// calling function
|
||||
check("void f(int x) {\n"
|
||||
" int y = x & 7;\n"
|
||||
|
|
Loading…
Reference in New Issue