Fixed #5866 (False negative: useless condition or null pointer dereference (null object after while loop, method))
This commit is contained in:
parent
76510e0006
commit
65f10edcb6
|
@ -2202,6 +2202,8 @@ void Tokenizer::simplifyLabelsCaseDefault()
|
||||||
if (Token::Match(tok->next(),"[:{};]"))
|
if (Token::Match(tok->next(),"[:{};]"))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!tok)
|
||||||
|
break;
|
||||||
if (tok->str() != "case" && tok->next() && tok->next()->str() == ":") {
|
if (tok->str() != "case" && tok->next() && tok->next()->str() == ":") {
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
if (tok->next()->str() != ";")
|
if (tok->next()->str() != ";")
|
||||||
|
|
|
@ -704,6 +704,17 @@ static bool valueFlowForward(Token * const startToken,
|
||||||
|
|
||||||
// TODO: don't check noreturn scopes
|
// TODO: don't check noreturn scopes
|
||||||
if (read && (number_of_if > 0U || Token::findmatch(tok2, "%varid%", start, varid))) {
|
if (read && (number_of_if > 0U || Token::findmatch(tok2, "%varid%", start, varid))) {
|
||||||
|
// Set values in condition
|
||||||
|
const Token * const condend = tok2->linkAt(1);
|
||||||
|
for (Token *condtok = tok2; condtok != condend; condtok = condtok->next()) {
|
||||||
|
if (condtok->varId() == varid) {
|
||||||
|
std::list<ValueFlow::Value>::const_iterator it;
|
||||||
|
for (it = values.begin(); it != values.end(); ++it)
|
||||||
|
setTokenValue(condtok, *it);
|
||||||
|
}
|
||||||
|
if (Token::Match(condtok, "%oror%|&&"))
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (settings->debugwarnings)
|
if (settings->debugwarnings)
|
||||||
bailout(tokenlist, errorLogger, tok2, "variable " + var->nameToken()->str() + " is assigned in conditional code");
|
bailout(tokenlist, errorLogger, tok2, "variable " + var->nameToken()->str() + " is assigned in conditional code");
|
||||||
return false;
|
return false;
|
||||||
|
@ -896,13 +907,15 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg
|
||||||
if (Token::Match(tok,"==|!=|>=|<=")) {
|
if (Token::Match(tok,"==|!=|>=|<=")) {
|
||||||
if (!tok->astOperand1() || !tok->astOperand2())
|
if (!tok->astOperand1() || !tok->astOperand2())
|
||||||
continue;
|
continue;
|
||||||
if (tok->astOperand1()->isName()) {
|
if (tok->astOperand1()->isNumber()) {
|
||||||
vartok = tok->astOperand1();
|
|
||||||
numtok = tok->astOperand2();
|
|
||||||
} else {
|
|
||||||
vartok = tok->astOperand2();
|
|
||||||
numtok = tok->astOperand1();
|
numtok = tok->astOperand1();
|
||||||
|
vartok = tok->astOperand2();
|
||||||
|
} else {
|
||||||
|
numtok = tok->astOperand2();
|
||||||
|
vartok = tok->astOperand1();
|
||||||
}
|
}
|
||||||
|
if (vartok->str() == "=" && vartok->astOperand1() && vartok->astOperand2())
|
||||||
|
vartok = vartok->astOperand1();
|
||||||
if (!vartok->isName() || !numtok->isNumber() || !MathLib::isInt(numtok->str()))
|
if (!vartok->isName() || !numtok->isNumber() || !MathLib::isInt(numtok->str()))
|
||||||
continue;
|
continue;
|
||||||
} else if (tok->str() == "!") {
|
} else if (tok->str() == "!") {
|
||||||
|
@ -913,7 +926,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg
|
||||||
|
|
||||||
} else if (tok->isName() &&
|
} else if (tok->isName() &&
|
||||||
(Token::Match(tok->astParent(), "%oror%|&&") ||
|
(Token::Match(tok->astParent(), "%oror%|&&") ||
|
||||||
Token::Match(tok->tokAt(-2), "if|while ( %var% )"))) {
|
Token::Match(tok->tokAt(-2), "if|while ( %var% [)=]"))) {
|
||||||
vartok = tok;
|
vartok = tok;
|
||||||
numtok = nullptr;
|
numtok = nullptr;
|
||||||
|
|
||||||
|
@ -964,7 +977,9 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg
|
||||||
const Token *top = tok->astTop();
|
const Token *top = tok->astTop();
|
||||||
if (top && Token::Match(top->previous(), "if|while (") && !top->previous()->isExpandedMacro()) {
|
if (top && Token::Match(top->previous(), "if|while (") && !top->previous()->isExpandedMacro()) {
|
||||||
// does condition reassign variable?
|
// does condition reassign variable?
|
||||||
if (isVariableChanged(top,top->link(),varid)) {
|
if (tok != top->astOperand2() &&
|
||||||
|
Token::Match(top->astOperand2(), "%oror%|&&") &&
|
||||||
|
isVariableChanged(top,top->link(),varid)) {
|
||||||
if (settings->debugwarnings)
|
if (settings->debugwarnings)
|
||||||
bailout(tokenlist, errorLogger, tok, "assignment in condition");
|
bailout(tokenlist, errorLogger, tok, "assignment in condition");
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -907,6 +907,45 @@ private:
|
||||||
"}";
|
"}";
|
||||||
ASSERT_EQUALS(true, testValueOfX(code, 3U, 3));
|
ASSERT_EQUALS(true, testValueOfX(code, 3U, 3));
|
||||||
|
|
||||||
|
code = "void f(int x) {\n"
|
||||||
|
" while (11 != (x = dostuff())) {}\n"
|
||||||
|
" a = x;\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 3U, 11));
|
||||||
|
|
||||||
|
code = "void f(int x) {\n"
|
||||||
|
" while (11 != (x = dostuff()) && y) {}\n"
|
||||||
|
" a = x;\n"
|
||||||
|
"}";
|
||||||
|
TODO_ASSERT_EQUALS(true, false, testValueOfX(code, 3U, 11));
|
||||||
|
|
||||||
|
code = "void f(int x) {\n"
|
||||||
|
" while (x = dostuff()) {}\n"
|
||||||
|
" a = x;\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
|
||||||
|
|
||||||
|
code = "void f(const Token *x) {\n" // #5866
|
||||||
|
" x = x->next();\n"
|
||||||
|
" while (x) { x = x->next(); }\n"
|
||||||
|
" if (x->str()) {}\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 4U, 0));
|
||||||
|
|
||||||
|
code = "void f(const Token *x) {\n"
|
||||||
|
" while (0 != (x = x->next)) {}\n"
|
||||||
|
" x->ab = 0;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
|
||||||
|
|
||||||
|
code = "void f(const Token* x) {\n"
|
||||||
|
" while (0 != (x = x->next)) {}\n"
|
||||||
|
" if (x->str) {\n" // <- possible value 0
|
||||||
|
" x = y;\n" // <- this caused some problem
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
|
||||||
|
|
||||||
// conditional code after if/else/while
|
// conditional code after if/else/while
|
||||||
code = "void f(int x) {\n"
|
code = "void f(int x) {\n"
|
||||||
" if (x == 2) {}\n"
|
" if (x == 2) {}\n"
|
||||||
|
|
Loading…
Reference in New Issue