diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index c021d1d296b..96c2ba24159 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -4131,7 +4131,7 @@ static std::list truncateValues(std::list va } if (value.isIntValue() && sz > 0 && sz < sizeof(MathLib::biguint)) - value.intvalue = ValueFlow::truncateIntValue(value.intvalue, sz, dst->sign); + value.intvalue = ValueFlow::truncateIntValue(value.intvalue, sz, dst, settings.platform); } return values; } diff --git a/lib/vf_analyzers.cpp b/lib/vf_analyzers.cpp index 1a4d17aa849..b2ef2abe1ea 100644 --- a/lib/vf_analyzers.cpp +++ b/lib/vf_analyzers.cpp @@ -357,7 +357,7 @@ struct ValueFlowAnalyzer : Analyzer { if (dst) { const size_t sz = dst->getSizeOf(settings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointer); if (sz > 0 && sz < sizeof(MathLib::biguint)) { - MathLib::bigint newvalue = ValueFlow::truncateIntValue(value->intvalue, sz, dst->sign); + MathLib::bigint newvalue = ValueFlow::truncateIntValue(value->intvalue, sz, dst, settings.platform); /* Handle overflow/underflow for value bounds */ if (value->bound != ValueFlow::Value::Bound::Point) { diff --git a/lib/vf_common.cpp b/lib/vf_common.cpp index f9eecc20fb9..b1cabcc9201 100644 --- a/lib/vf_common.cpp +++ b/lib/vf_common.cpp @@ -96,7 +96,7 @@ namespace ValueFlow return true; } - MathLib::bigint truncateIntValue(MathLib::bigint value, size_t value_size, const ValueType::Sign dst_sign) + MathLib::bigint truncateIntValue(MathLib::bigint value, size_t value_size, const ValueType* dst, const Platform& platform) { if (value_size == 0) return value; @@ -104,7 +104,7 @@ namespace ValueFlow const MathLib::biguint unsignedMaxValue = std::numeric_limits::max() >> ((sizeof(unsignedMaxValue) - value_size) * 8); const MathLib::biguint signBit = 1ULL << ((value_size * 8) - 1); value &= unsignedMaxValue; - if (dst_sign == ValueType::Sign::SIGNED && (value & signBit)) + if ((dst->sign == ValueType::Sign::SIGNED || (dst->sign == ValueType::Sign::UNKNOWN_SIGN && dst->type == ValueType::Type::CHAR && platform.defaultSign == 's')) && (value & signBit)) value |= ~unsignedMaxValue; return value; diff --git a/lib/vf_common.h b/lib/vf_common.h index aca438a0dff..448d14ccb41 100644 --- a/lib/vf_common.h +++ b/lib/vf_common.h @@ -41,7 +41,7 @@ namespace ValueFlow { bool getMinMaxValues(const ValueType* vt, const Platform& platform, MathLib::bigint& minValue, MathLib::bigint& maxValue); - MathLib::bigint truncateIntValue(MathLib::bigint value, size_t value_size, ValueType::Sign dst_sign); + MathLib::bigint truncateIntValue(MathLib::bigint value, size_t value_size, const ValueType* dst, const Platform& platform); Token * valueFlowSetConstantValue(Token *tok, const Settings &settings); diff --git a/lib/vf_settokenvalue.cpp b/lib/vf_settokenvalue.cpp index 1d6179fb9af..21bfbbe2da2 100644 --- a/lib/vf_settokenvalue.cpp +++ b/lib/vf_settokenvalue.cpp @@ -665,7 +665,7 @@ namespace ValueFlow const ValueType *dst = tok->valueType(); if (dst) { const size_t sz = dst->getSizeOf(settings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointer); - MathLib::bigint newvalue = ValueFlow::truncateIntValue(v.intvalue + 1, sz, dst->sign); + MathLib::bigint newvalue = ValueFlow::truncateIntValue(v.intvalue + 1, sz, dst, settings.platform); if (v.bound != ValueFlow::Value::Bound::Point) { if (newvalue < v.intvalue) { v.invertBound(); @@ -695,7 +695,7 @@ namespace ValueFlow const ValueType *dst = tok->valueType(); if (dst) { const size_t sz = dst->getSizeOf(settings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointer); - MathLib::bigint newvalue = ValueFlow::truncateIntValue(v.intvalue - 1, sz, dst->sign); + MathLib::bigint newvalue = ValueFlow::truncateIntValue(v.intvalue - 1, sz, dst, settings.platform); if (v.bound != ValueFlow::Value::Bound::Point) { if (newvalue > v.intvalue) { v.invertBound(); diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index f84f0ea0d89..3609bf2aee2 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -1389,6 +1389,13 @@ class TestValueFlow : public TestFixture { ASSERT_EQUALS(22, values.back().intvalue); } + code = "void f() {\n" // #15032 + " char c = -1;\n" + " if (~c == -256) {}\n" + "}\n"; + const int expected = std::numeric_limits::is_signed ? 0 : -256; + ASSERT_EQUALS(true, testKnownValueOfTok(code, "~", expected)); + // #10251 starship operator code = "struct X {};\n" "auto operator<=>(const X & a, const X & b) -> decltype(1 <=> 2) {\n"