Skip to content

Commit

Permalink
Fix #11421 FP shiftTooManyBits with 64bit enum (#5406)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrchr-github committed Sep 13, 2023
1 parent 7d1423c commit 844ed2b
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 3 deletions.
34 changes: 31 additions & 3 deletions lib/symboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down
32 changes: 32 additions & 0 deletions test/testsymboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ class TestSymbolDatabase : public TestFixture {
TEST_CASE(enum11);
TEST_CASE(enum12);
TEST_CASE(enum13);
TEST_CASE(enum14);

TEST_CASE(sizeOfType);

Expand Down Expand Up @@ -5771,6 +5772,37 @@ class TestSymbolDatabase : public TestFixture {
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"
Expand Down

0 comments on commit 844ed2b

Please sign in to comment.