Fixed #6317 (wrong simplification: int i = 1.5; return i; get simplified to: return 1.5;)
This commit is contained in:
parent
1cc5f3abe7
commit
6c3c090403
|
@ -3564,6 +3564,30 @@ static void valueFlowForwardAssign(Token * const tok,
|
||||||
valueFlowForward(const_cast<Token *>(nextExpression), endOfVarScope, var, var->declarationId(), values, constValue, false, tokenlist, errorLogger, settings);
|
valueFlowForward(const_cast<Token *>(nextExpression), endOfVarScope, var, var->declarationId(), values, constValue, false, tokenlist, errorLogger, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::list<ValueFlow::Value> truncateValues(std::list<ValueFlow::Value> values, const ValueType *valueType, const Settings *settings)
|
||||||
|
{
|
||||||
|
if (!valueType || !valueType->isIntegral())
|
||||||
|
return values;
|
||||||
|
|
||||||
|
const size_t sz = getSizeOf(*valueType, settings);
|
||||||
|
|
||||||
|
for (ValueFlow::Value &value : values) {
|
||||||
|
if (value.isFloatValue()) {
|
||||||
|
value.intvalue = value.floatValue;
|
||||||
|
value.valueType = ValueFlow::Value::INT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.isIntValue() && sz > 0 && sz < 8) {
|
||||||
|
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))
|
||||||
|
value.intvalue |= ~unsignedMaxValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
|
static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
|
||||||
{
|
{
|
||||||
for (const Scope * scope : symboldatabase->functionScopes) {
|
for (const Scope * scope : symboldatabase->functionScopes) {
|
||||||
|
@ -3593,7 +3617,7 @@ static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldat
|
||||||
if (!tok->astOperand2() || tok->astOperand2()->values().empty())
|
if (!tok->astOperand2() || tok->astOperand2()->values().empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::list<ValueFlow::Value> values = tok->astOperand2()->values();
|
std::list<ValueFlow::Value> values = truncateValues(tok->astOperand2()->values(), tok->astOperand1()->valueType(), settings);
|
||||||
const bool constValue = tok->astOperand2()->isNumber();
|
const bool constValue = tok->astOperand2()->isNumber();
|
||||||
const bool init = var->nameToken() == tok->astOperand1();
|
const bool init = var->nameToken() == tok->astOperand1();
|
||||||
valueFlowForwardAssign(const_cast<Token *>(tok->astOperand2()), var, values, constValue, init, tokenlist, errorLogger, settings);
|
valueFlowForwardAssign(const_cast<Token *>(tok->astOperand2()), var, values, constValue, init, tokenlist, errorLogger, settings);
|
||||||
|
|
|
@ -1443,6 +1443,25 @@ private:
|
||||||
"}";
|
"}";
|
||||||
ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
|
ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
|
||||||
|
|
||||||
|
// truncation
|
||||||
|
code = "int f() {\n"
|
||||||
|
" int x = 1.5;\n"
|
||||||
|
" return x;\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 3U, 1));
|
||||||
|
|
||||||
|
code = "int f() {\n"
|
||||||
|
" unsigned char x = 0x123;\n"
|
||||||
|
" return x;\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 3U, 0x23));
|
||||||
|
|
||||||
|
code = "int f() {\n"
|
||||||
|
" signed char x = 0xfe;\n"
|
||||||
|
" return x;\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 3U, -2));
|
||||||
|
|
||||||
// function
|
// function
|
||||||
code = "void f() {\n"
|
code = "void f() {\n"
|
||||||
" char *x = 0;\n"
|
" char *x = 0;\n"
|
||||||
|
|
Loading…
Reference in New Issue