CheckMemoryLeak: Fix handling of comparisons after simplifyIfNotNull is removed, detected problem with run_more_tests

This commit is contained in:
Daniel Marjamäki 2015-07-26 11:27:52 +02:00
parent bbec54db8e
commit 4e293d47c5
2 changed files with 54 additions and 2 deletions

View File

@ -543,6 +543,23 @@ static bool ifvar(const Token *tok, unsigned int varid, const std::string &comp,
return (vartok && vartok->varId() == varid); return (vartok && vartok->varId() == varid);
} }
static bool alwaysTrue(const Token *tok)
{
if (!tok)
return false;
if (tok->values.size() == 1U &&
tok->values.front().intvalue != 0 &&
tok->values.front().isKnown())
return true;
if (tok->str() == "||")
return alwaysTrue(tok->astOperand1()) || alwaysTrue(tok->astOperand2());
if (tok->str() == "true")
return true;
return (tok->isComparisonOp() &&
tok->values.size() == 1U &&
tok->values.front().isKnown() &&
tok->values.front().intvalue != 0);
}
bool CheckMemoryLeakInFunction::test_white_list(const std::string &funcname, const Settings *settings, bool cpp) bool CheckMemoryLeakInFunction::test_white_list(const std::string &funcname, const Settings *settings, bool cpp)
{ {
@ -1090,7 +1107,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
else if ((tok->str() == "for") || (tok->str() == "while")) { else if ((tok->str() == "for") || (tok->str() == "while")) {
const Token* const end = tok->linkAt(1); const Token* const end = tok->linkAt(1);
if (Token::simpleMatch(tok, "while ( true )") || if ((Token::simpleMatch(tok, "while (") && alwaysTrue(tok->next()->astOperand2())) ||
Token::simpleMatch(tok, "for ( ; ; )")) { Token::simpleMatch(tok, "for ( ; ; )")) {
addtoken(&rettail, tok, "while1"); addtoken(&rettail, tok, "while1");
tok = end; tok = end;

View File

@ -389,7 +389,9 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
} }
// Calculations.. // Calculations..
else if (parent->isArithmeticalOp() && parent->astOperand1() && parent->astOperand2()) { else if ((parent->isArithmeticalOp() || parent->isComparisonOp()) &&
parent->astOperand1() &&
parent->astOperand2()) {
const bool known = ((parent->astOperand1()->values.size() == 1U && const bool known = ((parent->astOperand1()->values.size() == 1U &&
parent->astOperand1()->values.front().isKnown()) || parent->astOperand1()->values.front().isKnown()) ||
(parent->astOperand2()->values.size() == 1U && (parent->astOperand2()->values.size() == 1U &&
@ -431,6 +433,39 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
result.intvalue = value1->intvalue % value2->intvalue; result.intvalue = value1->intvalue % value2->intvalue;
setTokenValue(parent, result); setTokenValue(parent, result);
break; break;
case '=':
if (parent->str() == "==") {
result.intvalue = value1->intvalue == value2->intvalue;
setTokenValue(parent, result);
}
break;
case '!':
if (parent->str() == "!=") {
result.intvalue = value1->intvalue != value2->intvalue;
setTokenValue(parent, result);
}
break;
case '>':
if (parent->str() == ">")
result.intvalue = value1->intvalue > value2->intvalue;
else if (parent->str() == ">=")
result.intvalue = value1->intvalue >= value2->intvalue;
else
break;
setTokenValue(parent, result);
break;
case '<':
if (parent->str() == "<")
result.intvalue = value1->intvalue < value2->intvalue;
else if (parent->str() == "<=")
result.intvalue = value1->intvalue <= value2->intvalue;
else
break;
setTokenValue(parent, result);
break;
default:
// unhandled operator, do nothing
break;
} }
} }
} }