Fix #11421 FP shiftTooManyBits with 64bit enum (#5406)

This commit is contained in:
chrchr-github 2023-09-13 17:59:47 +02:00 committed by GitHub
parent 7d1423c5fb
commit 844ed2bf22
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 3 deletions

View File

@ -6281,6 +6281,8 @@ void SymbolDatabase::setValueType(Token* tok, const Variable& var, SourceLocatio
}
}
static ValueType::Type getEnumType(const Scope* scope, const cppcheck::Platform& platform);
void SymbolDatabase::setValueType(Token* tok, const Enumerator& enumerator, SourceLocation loc)
{
ValueType valuetype;
@ -6307,7 +6309,7 @@ void SymbolDatabase::setValueType(Token* tok, const Enumerator& enumerator, Sour
setValueType(tok, valuetype);
} else {
valuetype.sign = ValueType::SIGNED;
valuetype.type = ValueType::INT;
valuetype.type = getEnumType(enumerator.scope, mSettings.platform);
setValueType(tok, valuetype);
}
}
@ -6796,6 +6798,32 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source
}
}
static ValueType::Type getEnumType(const Scope* scope, const cppcheck::Platform& platform) // TODO: also determine sign?
{
ValueType::Type type = ValueType::Type::INT;
for (const Token* tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next()) {
if (!tok->isAssignmentOp())
continue;
const Token* vTok = tok->astOperand2();
if (!vTok->hasKnownIntValue()) {
if (!vTok->isLiteral())
continue;
if (const ValueType* vt = vTok->valueType()) {
if ((vt->type > type && (vt->type == ValueType::Type::LONG || vt->type == ValueType::Type::LONGLONG)))
type = vt->type;
}
continue;
}
const MathLib::bigint value = vTok->getKnownIntValue();
if (!platform.isIntValue(value)) {
type = ValueType::Type::LONG;
if (!platform.isLongValue(value))
type = ValueType::Type::LONGLONG;
}
}
return type;
}
static const Token* parsedecl(const Token* type,
ValueType* const valuetype,
ValueType::Sign defaultSignedness,
@ -6829,7 +6857,7 @@ static const Token* parsedecl(const Token* type,
else if (enum_type->isStandardType())
valuetype->fromLibraryType(enum_type->str(), settings);
} else
valuetype->type = ValueType::Type::INT;
valuetype->type = getEnumType(valuetype->typeScope, settings.platform);
} else
valuetype->type = ValueType::Type::RECORD;
bool par = false;
@ -6976,8 +7004,8 @@ static const Token* parsedecl(const Token* type,
valuetype->type = type->str() == "struct" ? ValueType::Type::RECORD : ValueType::Type::NONSTD;
else if (!valuetype->typeScope && type->type() && type->type()->classScope) {
if (type->type()->classScope->type == Scope::ScopeType::eEnum) {
valuetype->type = ValueType::Type::INT;
valuetype->sign = ValueType::Sign::SIGNED;
valuetype->type = getEnumType(type->type()->classScope, settings.platform);
} else {
valuetype->type = ValueType::Type::RECORD;
}

View File

@ -388,6 +388,7 @@ private:
TEST_CASE(enum11);
TEST_CASE(enum12);
TEST_CASE(enum13);
TEST_CASE(enum14);
TEST_CASE(sizeOfType);
@ -5771,6 +5772,37 @@ private:
ASSERT(E1->scope == a->valueType()->typeScope);
}
void enum14() {
GET_SYMBOL_DB("void f() {\n" // #11421
" enum E { A = 0, B = 0xFFFFFFFFFFFFFFFFull, C = 0x7FFFFFFFFFFFFFFF };\n"
" E e = B;\n"
" auto s1 = e >> 32;\n"
" auto s2 = B >> 32;\n"
" enum F { F0 = sizeof(int) };\n"
" F f = F0;\n"
"}\n");
ASSERT(db != nullptr);
auto it = db->scopeList.begin();
std::advance(it, 2);
const Enumerator* B = it->findEnumerator("B");
ASSERT(B);
TODO_ASSERT(B->value_known);
const Enumerator* C = it->findEnumerator("C");
ASSERT(C && C->value_known);
const Token* const s1 = Token::findsimplematch(tokenizer.tokens(), "s1 =");
ASSERT(s1 && s1->valueType());
ASSERT_EQUALS(s1->valueType()->type, ValueType::Type::LONGLONG);
const Token* const s2 = Token::findsimplematch(s1, "s2 =");
ASSERT(s2 && s2->valueType());
ASSERT_EQUALS(s2->valueType()->type, ValueType::Type::LONGLONG);
++it;
const Enumerator* F0 = it->findEnumerator("F0");
ASSERT(F0 && F0->value_known);
const Token* const f = Token::findsimplematch(s2, "f =");
ASSERT(f && f->valueType());
ASSERT_EQUALS(f->valueType()->type, ValueType::Type::INT);
}
void sizeOfType() {
// #7615 - crash in Symboldatabase::sizeOfType()
GET_SYMBOL_DB("enum e;\n"