Fix 10297: Regression; ValueFlow known value, sign conversion (#3307)

This commit is contained in:
Paul Fultz II 2021-06-26 02:16:04 -05:00 committed by GitHub
parent bf019a1ab2
commit 508188df2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 5 deletions

View File

@ -4143,12 +4143,34 @@ static void valueFlowForwardAssign(Token* const tok,
valueFlowForwardAssign(tok, var->nameToken(), {var}, values, init, tokenlist, errorLogger, settings);
}
static std::list<ValueFlow::Value> truncateValues(std::list<ValueFlow::Value> values, const ValueType *valueType, const Settings *settings)
static std::list<ValueFlow::Value> truncateValues(std::list<ValueFlow::Value> values,
const ValueType* dst,
const ValueType* src,
const Settings* settings)
{
if (!valueType || !valueType->isIntegral())
if (!dst || !dst->isIntegral())
return values;
const size_t sz = ValueFlow::getSizeOf(*valueType, settings);
const size_t sz = ValueFlow::getSizeOf(*dst, settings);
if (src) {
const size_t osz = ValueFlow::getSizeOf(*src, settings);
if (osz >= sz && dst->sign == ValueType::Sign::SIGNED && src->sign == ValueType::Sign::UNSIGNED) {
values.remove_if([&](const ValueFlow::Value& value) {
if (!value.isIntValue())
return false;
if (!value.isImpossible())
return false;
if (value.bound != ValueFlow::Value::Bound::Upper)
return false;
if (osz == sz && value.intvalue < 0)
return true;
if (osz > sz)
return true;
return false;
});
}
}
for (ValueFlow::Value &value : values) {
// Don't truncate impossible values since those can be outside of the valid range
@ -4163,7 +4185,7 @@ static std::list<ValueFlow::Value> truncateValues(std::list<ValueFlow::Value> va
const MathLib::biguint unsignedMaxValue = (1ULL << (sz * 8)) - 1ULL;
const MathLib::biguint signBit = 1ULL << (sz * 8 - 1);
value.intvalue &= unsignedMaxValue;
if (valueType->sign == ValueType::Sign::SIGNED && (value.intvalue & signBit))
if (dst->sign == ValueType::Sign::SIGNED && (value.intvalue & signBit))
value.intvalue |= ~unsignedMaxValue;
}
}
@ -4208,7 +4230,8 @@ static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldat
if (!tok->astOperand2() || tok->astOperand2()->values().empty())
continue;
std::list<ValueFlow::Value> values = truncateValues(tok->astOperand2()->values(), tok->astOperand1()->valueType(), settings);
std::list<ValueFlow::Value> values = truncateValues(
tok->astOperand2()->values(), tok->astOperand1()->valueType(), tok->astOperand2()->valueType(), settings);
// Remove known values
std::set<ValueFlow::Value::ValueType> types;
if (tok->astOperand1()->hasKnownValue()) {

View File

@ -3639,6 +3639,15 @@ private:
" if (num < 0) {}\n" // <- do not report knownConditionTrueFalse
"}");
ASSERT_EQUALS("", errout.str());
// #10297
check("void foo(size_t len, int start) {\n"
" if (start < 0) {\n"
" start = len+start;\n"
" if (start < 0) {}\n"
" }\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void alwaysTrueInfer() {