diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index f398768cd..1c17ca089 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1206,6 +1206,61 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti } } + // fill in enumerators in enum + for (std::list::iterator it = scopeList.begin(); it != scopeList.end(); ++it) { + if (it->type != Scope::eEnum) + continue; + + // add enumerators to enumerator tokens + for (std::size_t i = 0, end = it->enumeratorList.size(); i < end; ++i) + const_cast(it->enumeratorList[i].name)->enumerator(&it->enumeratorList[i]); + } + + // fill in enumerator values + for (std::list::iterator it = scopeList.begin(); it != scopeList.end(); ++it) { + if (it->type != Scope::eEnum) + continue; + + MathLib::bigint value = 0; + + for (std::size_t i = 0, end = it->enumeratorList.size(); i < end; ++i) { + Enumerator & enumerator = it->enumeratorList[i]; + + // look for initialization tokens that can be converted to enumerators and convert them + if (enumerator.start) { + for (const Token * tok3 = enumerator.start; tok3 && tok3 != enumerator.end->next(); tok3 = tok3->next()) { + if (tok3->tokType() == Token::eName) { + const Enumerator * e = findEnumerator(tok3); + if (e) + const_cast(tok3)->enumerator(e); + } + } + + // look for possible constant folding expressions + if (enumerator.start) { + // rhs of operator: + const Token *rhs = enumerator.start->previous()->astOperand2(); + + // constant folding of expression: + ValueFlow::valueFlowConstantFoldAST(rhs); + + // get constant folded value: + if (rhs && rhs->values.size() == 1U && rhs->values.front().isKnown()) { + enumerator.value = rhs->values.front().intvalue; + enumerator.value_known = true; + value = enumerator.value + 1; + } + } + } + + // not initialized so use default value + else { + enumerator.value = value++; + enumerator.value_known = true; + } + } + } + // find enumerators for (const Token* tok = _tokenizer->list.front(); tok != _tokenizer->list.back(); tok = tok->next()) { if (tok->tokType() != Token::eName) @@ -3256,52 +3311,6 @@ const Token * Scope::addEnum(const Token * tok, bool isCpp) } else tok2 = nullptr; - if (tok2) { - // add enumerators to enumerator tokens - for (std::size_t i = 0, end = enumeratorList.size(); i < end; ++i) - const_cast(enumeratorList[i].name)->enumerator(&enumeratorList[i]); - - MathLib::bigint value = 0; - - // fill in enumerator values - for (std::size_t i = 0, end = enumeratorList.size(); i < end; ++i) { - Enumerator & enumerator = enumeratorList[i]; - - // look for initialization tokens that can be converted to enumerators and convert them - if (enumerator.start) { - for (const Token * tok3 = enumerator.start; tok3 && tok3 != enumerator.end->next(); tok3 = tok3->next()) { - if (tok3->tokType() == Token::eName) { - const Enumerator * e = findEnumerator(tok3->str()); - if (e) - const_cast(tok3)->enumerator(e); - } - } - - // look for possible constant folding expressions - if (enumerator.start) { - // rhs of operator: - const Token *rhs = enumerator.start->previous()->astOperand2(); - - // constant folding of expression: - ValueFlow::valueFlowConstantFoldAST(rhs); - - // get constant folded value: - if (rhs && rhs->values.size() == 1U && rhs->values.front().isKnown()) { - enumerator.value = rhs->values.front().intvalue; - enumerator.value_known = true; - value = enumerator.value + 1; - } - } - } - - // not initialized so use default value - else { - enumerator.value = value++; - enumerator.value_known = true; - } - } - } - return tok2; } diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 1d86ca48b..1ac76bc85 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -2300,8 +2300,8 @@ private: } void enum4() { // #7493 - GET_SYMBOL_DB("enum Offsets { O1, O2, O3 };\n" - "enum MyEnums { E1=O1+1, E2=O2+1, E3=O3+1 };"); + GET_SYMBOL_DB("enum Offsets { O1, O2, O3=5, O4 };\n" + "enum MyEnums { E1=O1+1, E2, E3=O3+1 };"); ASSERT(db != nullptr); if (!db) return; @@ -2313,18 +2313,75 @@ private: // Offsets ++scope; ASSERT_EQUALS((unsigned int)Scope::eEnum, (unsigned int)scope->type); - ASSERT_EQUALS(3U, scope->enumeratorList.size()); + ASSERT_EQUALS(4U, scope->enumeratorList.size()); + + ASSERT(scope->enumeratorList[0].name->enumerator() == &scope->enumeratorList[0]); + ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[0].name->tokType()); + ASSERT(scope->enumeratorList[0].scope == &*scope); + ASSERT_EQUALS("O1", scope->enumeratorList[0].name->str()); + ASSERT(scope->enumeratorList[0].start == nullptr); + ASSERT(scope->enumeratorList[0].end == nullptr); ASSERT_EQUALS(true, scope->enumeratorList[0].value_known); + ASSERT_EQUALS(0, scope->enumeratorList[0].value); + + ASSERT(scope->enumeratorList[1].name->enumerator() == &scope->enumeratorList[1]); + ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[1].name->tokType()); + ASSERT(scope->enumeratorList[1].scope == &*scope); + ASSERT_EQUALS("O2", scope->enumeratorList[1].name->str()); + ASSERT(scope->enumeratorList[1].start == nullptr); + ASSERT(scope->enumeratorList[1].end == nullptr); ASSERT_EQUALS(true, scope->enumeratorList[1].value_known); + ASSERT_EQUALS(1, scope->enumeratorList[1].value); + + ASSERT(scope->enumeratorList[2].name->enumerator() == &scope->enumeratorList[2]); + ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[2].name->tokType()); + ASSERT(scope->enumeratorList[2].scope == &*scope); + ASSERT_EQUALS("O3", scope->enumeratorList[2].name->str()); + ASSERT(scope->enumeratorList[2].start != nullptr); + ASSERT(scope->enumeratorList[2].end != nullptr); ASSERT_EQUALS(true, scope->enumeratorList[2].value_known); + ASSERT_EQUALS(5, scope->enumeratorList[2].value); + + ASSERT(scope->enumeratorList[3].name->enumerator() == &scope->enumeratorList[3]); + ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[3].name->tokType()); + ASSERT(scope->enumeratorList[3].scope == &*scope); + ASSERT_EQUALS("O4", scope->enumeratorList[3].name->str()); + ASSERT(scope->enumeratorList[3].start == nullptr); + ASSERT(scope->enumeratorList[3].end == nullptr); + ASSERT_EQUALS(true, scope->enumeratorList[3].value_known); + ASSERT_EQUALS(6, scope->enumeratorList[3].value); // MyEnums ++scope; ASSERT_EQUALS((unsigned int)Scope::eEnum, (unsigned int)scope->type); ASSERT_EQUALS(3U, scope->enumeratorList.size()); - TODO_ASSERT_EQUALS(true, false, scope->enumeratorList[0].value_known); - TODO_ASSERT_EQUALS(true, false, scope->enumeratorList[1].value_known); - TODO_ASSERT_EQUALS(true, false, scope->enumeratorList[2].value_known); + + ASSERT(scope->enumeratorList[0].name->enumerator() == &scope->enumeratorList[0]); + ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[0].name->tokType()); + ASSERT(scope->enumeratorList[0].scope == &*scope); + ASSERT_EQUALS("E1", scope->enumeratorList[0].name->str()); + ASSERT(scope->enumeratorList[0].start != nullptr); + ASSERT(scope->enumeratorList[0].end != nullptr); + ASSERT_EQUALS(true, scope->enumeratorList[0].value_known); + ASSERT_EQUALS(1, scope->enumeratorList[0].value); + + ASSERT(scope->enumeratorList[1].name->enumerator() == &scope->enumeratorList[1]); + ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[1].name->tokType()); + ASSERT(scope->enumeratorList[1].scope == &*scope); + ASSERT_EQUALS("E2", scope->enumeratorList[1].name->str()); + ASSERT(scope->enumeratorList[1].start == nullptr); + ASSERT(scope->enumeratorList[1].end == nullptr); + ASSERT_EQUALS(true, scope->enumeratorList[1].value_known); + ASSERT_EQUALS(2, scope->enumeratorList[1].value); + + ASSERT(scope->enumeratorList[2].name->enumerator() == &scope->enumeratorList[2]); + ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[2].name->tokType()); + ASSERT(scope->enumeratorList[2].scope == &*scope); + ASSERT_EQUALS("E3", scope->enumeratorList[2].name->str()); + ASSERT(scope->enumeratorList[2].start != nullptr); + ASSERT(scope->enumeratorList[2].end != nullptr); + ASSERT_EQUALS(true, scope->enumeratorList[2].value_known); + ASSERT_EQUALS(6, scope->enumeratorList[2].value); } void enum5() {