From 4e293d47c5550cb695cc7d81834a519b32cf75c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 26 Jul 2015 11:27:52 +0200 Subject: [PATCH] CheckMemoryLeak: Fix handling of comparisons after simplifyIfNotNull is removed, detected problem with run_more_tests --- lib/checkmemoryleak.cpp | 19 ++++++++++++++++++- lib/valueflow.cpp | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 539a66e85..e51263d31 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -543,6 +543,23 @@ static bool ifvar(const Token *tok, unsigned int varid, const std::string &comp, 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) { @@ -1090,7 +1107,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::liststr() == "for") || (tok->str() == "while")) { 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 ( ; ; )")) { addtoken(&rettail, tok, "while1"); tok = end; diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 58e92a8b6..a4bcd78ff 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -389,7 +389,9 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value) } // 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 && parent->astOperand1()->values.front().isKnown()) || (parent->astOperand2()->values.size() == 1U && @@ -431,6 +433,39 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value) 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; + 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; } } }