diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index fe7bcf38d0a..3fd3b4c88de 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -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; } diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 6472602e8ab..87570be0355 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -388,6 +388,7 @@ class TestSymbolDatabase : public TestFixture { TEST_CASE(enum11); TEST_CASE(enum12); TEST_CASE(enum13); + TEST_CASE(enum14); TEST_CASE(sizeOfType); @@ -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"