diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index 978458ba2..0d6f1da6e 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -1030,12 +1030,15 @@ void CheckCondition::checkInvalidTestForOverflow() continue; const Token *calcToken, *exprToken; - if (tok->str() == "<" && tok->astOperand1()->str() == "+") { + bool result; + if (Token::Match(tok, "<|>=") && tok->astOperand1()->str() == "+") { calcToken = tok->astOperand1(); exprToken = tok->astOperand2(); - } else if (tok->str() == ">" && tok->astOperand2()->str() == "+") { + result = (tok->str() == ">="); + } else if (Token::Match(tok, ">|<=") && tok->astOperand2()->str() == "+") { calcToken = tok->astOperand2(); exprToken = tok->astOperand1(); + result = (tok->str() == "<="); } else continue; @@ -1058,18 +1061,20 @@ void CheckCondition::checkInvalidTestForOverflow() // Only warn when termToken is always positive if (termToken->valueType() && termToken->valueType()->sign == ValueType::Sign::UNSIGNED) - invalidTestForOverflow(tok); + invalidTestForOverflow(tok, result); else if (termToken->isNumber() && MathLib::isPositive(termToken->str())) - invalidTestForOverflow(tok); + invalidTestForOverflow(tok, result); } } } -void CheckCondition::invalidTestForOverflow(const Token* tok) +void CheckCondition::invalidTestForOverflow(const Token* tok, bool result) { std::string errmsg; errmsg = "Invalid test for overflow '" + (tok ? tok->expressionString() : std::string("x + u < x")) + - "'. Condition is always false unless there is overflow, and overflow is UB."; + "'. Condition is always " + + std::string(result ? "true" : "false") + + " unless there is overflow, and overflow is UB."; reportError(tok, Severity::warning, "invalidTestForOverflow", errmsg); } diff --git a/lib/checkcondition.h b/lib/checkcondition.h index 099ba6316..acc4e313b 100644 --- a/lib/checkcondition.h +++ b/lib/checkcondition.h @@ -126,7 +126,7 @@ private: void alwaysTrueFalseError(const Token *tok, bool knownResult); - void invalidTestForOverflow(const Token* tok); + void invalidTestForOverflow(const Token* tok, bool result); void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { CheckCondition c(0, settings, errorLogger); @@ -142,7 +142,7 @@ private: c.moduloAlwaysTrueFalseError(0, "1"); c.clarifyConditionError(0, true, false); c.alwaysTrueFalseError(0, true); - c.invalidTestForOverflow(0); + c.invalidTestForOverflow(0, false); } static std::string myName() { diff --git a/test/testcondition.cpp b/test/testcondition.cpp index 1df4f6493..876471a23 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -1613,6 +1613,21 @@ private: "}"); ASSERT_EQUALS("[test.cpp:2]: (warning) Invalid test for overflow '(p+x)
= p);\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (warning) Invalid test for overflow '(p+x)>=p'. Condition is always true unless there is overflow, and overflow is UB.\n", errout.str()); + + check("void f(char *p, unsigned int x) {\n" + " assert(p > (p + x));\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (warning) Invalid test for overflow 'p>(p+x)'. Condition is always false unless there is overflow, and overflow is UB.\n", errout.str()); + + check("void f(char *p, unsigned int x) {\n" + " assert(p <= (p + x));\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (warning) Invalid test for overflow 'p<=(p+x)'. Condition is always true unless there is overflow, and overflow is UB.\n", errout.str()); + check("void f(signed int x) {\n" " assert(x + 100 < x);\n" "}");