diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index 14fa900944d..cf54c882f34 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -1975,8 +1975,6 @@ void CheckCondition::checkCompareValueOutOfTypeRange() continue; if (valueTok->getKnownIntValue() < 0 && valueTok->valueType() && valueTok->valueType()->sign != ValueType::Sign::SIGNED) continue; - if (valueTok->valueType() && valueTok->valueType()->isTypeEqual(typeTok->valueType())) - continue; std::uint8_t bits = 0; switch (typeTok->valueType()->type) { case ValueType::Type::BOOL: @@ -2015,6 +2013,8 @@ void CheckCondition::checkCompareValueOutOfTypeRange() bool result{}; const auto kiv = valueTok->getKnownIntValue(); + if (kiv == 0) + continue; // prevent overlap with TestOther::unsignedPositive/unsignedLessThanZero if (tok->str() == "==") result = false; else if (tok->str() == "!=") diff --git a/lib/vf_settokenvalue.cpp b/lib/vf_settokenvalue.cpp index 12acc01dedd..602d87e159d 100644 --- a/lib/vf_settokenvalue.cpp +++ b/lib/vf_settokenvalue.cpp @@ -72,7 +72,7 @@ namespace ValueFlow return value; if (!parent->isBinaryOp()) return value; - if (!parent->isConstOp()) + if (!parent->isConstOp() && !parent->isAssignmentOp()) return value; if (!astIsIntegral(parent->astOperand1(), false)) return value; @@ -88,7 +88,7 @@ namespace ValueFlow ValueType::Sign sign = ValueType::Sign::UNSIGNED; if (n1 < n2) sign = vt2->sign; - else if (n1 > n2) + else // (n1 >= n2) sign = vt1->sign; Value v = castValue(value, sign, std::max(n1, n2) * 8); v.wideintvalue = value.intvalue; diff --git a/test/testcondition.cpp b/test/testcondition.cpp index 241d0400099..29d63562fa3 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -6324,28 +6324,24 @@ class TestCondition : public TestFixture { check("void f(const unsigned char u) {\n" " if (u > 0) {}\n" - " if (u < 0) {}\n" // warn - " if (u >= 0) {}\n" // warn + " if (u < 0) {}\n" + " if (u >= 0) {}\n" " if (u <= 0) {}\n" " if (u > 255) {}\n" // warn " if (u < 255) {}\n" " if (u >= 255) {}\n" " if (u <= 255) {}\n" // warn " if (0 < u) {}\n" - " if (0 > u) {}\n" // warn - " if (0 <= u) {}\n" // warn + " if (0 > u) {}\n" + " if (0 <= u) {}\n" " if (0 >= u) {}\n" " if (255 < u) {}\n" // warn " if (255 > u) {}\n" " if (255 <= u) {}\n" " if (255 >= u) {}\n" // warn "}\n", settingsUnix64); - ASSERT_EQUALS("[test.cpp:3:14]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always false. [compareValueOutOfTypeRangeError]\n" - "[test.cpp:4:14]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always true. [compareValueOutOfTypeRangeError]\n" - "[test.cpp:6:14]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always false. [compareValueOutOfTypeRangeError]\n" + ASSERT_EQUALS("[test.cpp:6:14]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always false. [compareValueOutOfTypeRangeError]\n" "[test.cpp:9:14]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always true. [compareValueOutOfTypeRangeError]\n" - "[test.cpp:11:9]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always false. [compareValueOutOfTypeRangeError]\n" - "[test.cpp:12:9]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always true. [compareValueOutOfTypeRangeError]\n" "[test.cpp:14:9]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always false. [compareValueOutOfTypeRangeError]\n" "[test.cpp:17:9]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always true. [compareValueOutOfTypeRangeError]\n", errout_str()); @@ -6355,6 +6351,15 @@ class TestCondition : public TestFixture { "}\n", settingsUnix64); ASSERT_EQUALS("[test.cpp:2:14]: (style) Comparing expression of type 'bool' against value 2. Condition is always true. [compareValueOutOfTypeRangeError]\n", errout_str()); + + check("void f(const std::uint32_t& u) {\n" // #9078 + " if (u >= UINT32_MAX) {}\n" + " if (u <= UINT32_MAX) {}\n" + " if (u > UINT32_MAX) {}\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:14]: (style) Comparing expression of type 'const unsigned int &' against value 4294967295. Condition is always true. [compareValueOutOfTypeRangeError]\n" + "[test.cpp:4:13]: (style) Comparing expression of type 'const unsigned int &' against value 4294967295. Condition is always false. [compareValueOutOfTypeRangeError]\n", + errout_str()); } void knownConditionCast() { diff --git a/test/testother.cpp b/test/testother.cpp index d2f57bbb2a4..00d25fc1b22 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -9313,6 +9313,24 @@ class TestOther : public TestFixture { " for (unsigned p = 0; p < (sizeof(a) / sizeof((a)[0])); ++p) {}\n" "}"); ASSERT_EQUALS("", errout_str()); + + check("void f(const unsigned char u) {\n" + " if (u > 0) {}\n" + " if (u < 0) {}\n" + " if (u >= 0) {}\n" + " if (u <= 0) {}\n" + " if (0 < u) {}\n" + " if (0 > u) {}\n" + " if (0 <= u) {}\n" + " if (0 >= u) {}\n" + "}"); + ASSERT_EQUALS("[test.cpp:3:11]: (style) Checking if unsigned expression 'u' is less than zero. [unsignedLessThanZero]\n" + "[test.cpp:4:11]: (style) Unsigned expression 'u' can't be negative so it is unnecessary to test it. [unsignedPositive]\n" + "[test.cpp:5:11]: (style) Checking if unsigned expression 'u' is less than zero. [unsignedLessThanZero]\n" + "[test.cpp:7:11]: (style) Checking if unsigned expression 'u' is less than zero. [unsignedLessThanZero]\n" + "[test.cpp:8:11]: (style) Unsigned expression 'u' can't be negative so it is unnecessary to test it. [unsignedPositive]\n" + "[test.cpp:9:11]: (style) Checking if unsigned expression 'u' is less than zero. [unsignedLessThanZero]\n", + errout_str()); } void checkSignOfPointer() { diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 709be2a204f..265704f6844 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -3112,6 +3112,12 @@ class TestValueFlow : public TestFixture { " return x;\n" "}\n"; ASSERT_EQUALS(false, testValueOfXKnown(code, 9U, 1)); + + code = "int32_t f() {\n" + " const int32_t x = 0xffffffff;\n" + " return x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfXKnown(code, 3U, -1)); } void valueFlowAfterSwap()