Skip to content

Commit 844ed2b

Browse files
Fix #11421 FP shiftTooManyBits with 64bit enum (#5406)
1 parent 7d1423c commit 844ed2b

2 files changed

Lines changed: 63 additions & 3 deletions

File tree

lib/symboldatabase.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6281,6 +6281,8 @@ void SymbolDatabase::setValueType(Token* tok, const Variable& var, SourceLocatio
62816281
}
62826282
}
62836283

6284+
static ValueType::Type getEnumType(const Scope* scope, const cppcheck::Platform& platform);
6285+
62846286
void SymbolDatabase::setValueType(Token* tok, const Enumerator& enumerator, SourceLocation loc)
62856287
{
62866288
ValueType valuetype;
@@ -6307,7 +6309,7 @@ void SymbolDatabase::setValueType(Token* tok, const Enumerator& enumerator, Sour
63076309
setValueType(tok, valuetype);
63086310
} else {
63096311
valuetype.sign = ValueType::SIGNED;
6310-
valuetype.type = ValueType::INT;
6312+
valuetype.type = getEnumType(enumerator.scope, mSettings.platform);
63116313
setValueType(tok, valuetype);
63126314
}
63136315
}
@@ -6796,6 +6798,32 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source
67966798
}
67976799
}
67986800

6801+
static ValueType::Type getEnumType(const Scope* scope, const cppcheck::Platform& platform) // TODO: also determine sign?
6802+
{
6803+
ValueType::Type type = ValueType::Type::INT;
6804+
for (const Token* tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next()) {
6805+
if (!tok->isAssignmentOp())
6806+
continue;
6807+
const Token* vTok = tok->astOperand2();
6808+
if (!vTok->hasKnownIntValue()) {
6809+
if (!vTok->isLiteral())
6810+
continue;
6811+
if (const ValueType* vt = vTok->valueType()) {
6812+
if ((vt->type > type && (vt->type == ValueType::Type::LONG || vt->type == ValueType::Type::LONGLONG)))
6813+
type = vt->type;
6814+
}
6815+
continue;
6816+
}
6817+
const MathLib::bigint value = vTok->getKnownIntValue();
6818+
if (!platform.isIntValue(value)) {
6819+
type = ValueType::Type::LONG;
6820+
if (!platform.isLongValue(value))
6821+
type = ValueType::Type::LONGLONG;
6822+
}
6823+
}
6824+
return type;
6825+
}
6826+
67996827
static const Token* parsedecl(const Token* type,
68006828
ValueType* const valuetype,
68016829
ValueType::Sign defaultSignedness,
@@ -6829,7 +6857,7 @@ static const Token* parsedecl(const Token* type,
68296857
else if (enum_type->isStandardType())
68306858
valuetype->fromLibraryType(enum_type->str(), settings);
68316859
} else
6832-
valuetype->type = ValueType::Type::INT;
6860+
valuetype->type = getEnumType(valuetype->typeScope, settings.platform);
68336861
} else
68346862
valuetype->type = ValueType::Type::RECORD;
68356863
bool par = false;
@@ -6976,8 +7004,8 @@ static const Token* parsedecl(const Token* type,
69767004
valuetype->type = type->str() == "struct" ? ValueType::Type::RECORD : ValueType::Type::NONSTD;
69777005
else if (!valuetype->typeScope && type->type() && type->type()->classScope) {
69787006
if (type->type()->classScope->type == Scope::ScopeType::eEnum) {
6979-
valuetype->type = ValueType::Type::INT;
69807007
valuetype->sign = ValueType::Sign::SIGNED;
7008+
valuetype->type = getEnumType(type->type()->classScope, settings.platform);
69817009
} else {
69827010
valuetype->type = ValueType::Type::RECORD;
69837011
}

test/testsymboldatabase.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ class TestSymbolDatabase : public TestFixture {
388388
TEST_CASE(enum11);
389389
TEST_CASE(enum12);
390390
TEST_CASE(enum13);
391+
TEST_CASE(enum14);
391392

392393
TEST_CASE(sizeOfType);
393394

@@ -5771,6 +5772,37 @@ class TestSymbolDatabase : public TestFixture {
57715772
ASSERT(E1->scope == a->valueType()->typeScope);
57725773
}
57735774

5775+
void enum14() {
5776+
GET_SYMBOL_DB("void f() {\n" // #11421
5777+
" enum E { A = 0, B = 0xFFFFFFFFFFFFFFFFull, C = 0x7FFFFFFFFFFFFFFF };\n"
5778+
" E e = B;\n"
5779+
" auto s1 = e >> 32;\n"
5780+
" auto s2 = B >> 32;\n"
5781+
" enum F { F0 = sizeof(int) };\n"
5782+
" F f = F0;\n"
5783+
"}\n");
5784+
ASSERT(db != nullptr);
5785+
auto it = db->scopeList.begin();
5786+
std::advance(it, 2);
5787+
const Enumerator* B = it->findEnumerator("B");
5788+
ASSERT(B);
5789+
TODO_ASSERT(B->value_known);
5790+
const Enumerator* C = it->findEnumerator("C");
5791+
ASSERT(C && C->value_known);
5792+
const Token* const s1 = Token::findsimplematch(tokenizer.tokens(), "s1 =");
5793+
ASSERT(s1 && s1->valueType());
5794+
ASSERT_EQUALS(s1->valueType()->type, ValueType::Type::LONGLONG);
5795+
const Token* const s2 = Token::findsimplematch(s1, "s2 =");
5796+
ASSERT(s2 && s2->valueType());
5797+
ASSERT_EQUALS(s2->valueType()->type, ValueType::Type::LONGLONG);
5798+
++it;
5799+
const Enumerator* F0 = it->findEnumerator("F0");
5800+
ASSERT(F0 && F0->value_known);
5801+
const Token* const f = Token::findsimplematch(s2, "f =");
5802+
ASSERT(f && f->valueType());
5803+
ASSERT_EQUALS(f->valueType()->type, ValueType::Type::INT);
5804+
}
5805+
57745806
void sizeOfType() {
57755807
// #7615 - crash in Symboldatabase::sizeOfType()
57765808
GET_SYMBOL_DB("enum e;\n"

0 commit comments

Comments
 (0)