diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 32c30f9521f..4881ebb6871 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -5190,6 +5190,22 @@ static const Scope* findEnumScopeInBase(const Scope* scope, const std::string& t return nullptr; } +static const Enumerator* findEnumeratorInUsingList(const Scope* scope, const std::string& name) +{ + for (const auto& u : scope->usingList) { + if (!u.scope) + continue; + for (const Scope* nested : u.scope->nestedList) { + if (nested->type != Scope::eEnum) + continue; + const Enumerator* e = nested->findEnumerator(name); + if (e && !(e->scope && e->scope->enumClass)) + return e; + } + } + return nullptr; +} + const Enumerator * SymbolDatabase::findEnumerator(const Token * tok, std::set& tokensThatAreNotEnumeratorValues) const { if (tok->isKeyword()) @@ -5268,6 +5284,8 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok, std::setfindEnumerator(tokStr); + if (!enumerator) + enumerator = findEnumeratorInUsingList(scope, tokStr); if (enumerator && !(enumerator->scope && enumerator->scope->enumClass)) return enumerator; @@ -5310,6 +5328,8 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok, std::setnestedIn; enumerator = scope->findEnumerator(tokStr); + if (!enumerator) + enumerator = findEnumeratorInUsingList(scope, tokStr); if (enumerator && !(enumerator->scope && enumerator->scope->enumClass)) return enumerator; @@ -5319,6 +5339,17 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok, std::setscope && enumerator->scope->enumClass)) return enumerator; + + if (tok->isCpp() && (*s)->type == Scope::eNamespace && Token::simpleMatch((*s)->classDef, "namespace {")) { + for (const Scope* nested : (*s)->nestedList) { + if (nested->type != Scope::eEnum) + continue; + enumerator = nested->findEnumerator(tokStr); + + if (enumerator && !(enumerator->scope && enumerator->scope->enumClass)) + return enumerator; + } + } } } } @@ -6097,6 +6128,14 @@ S* findRecordInNestedListImpl(S& thisScope, const std::string & name, bool isC) } } + for (const auto& u : thisScope.usingList) { + if (!u.scope) + continue; + S* nestedScope = const_cast(u.scope)->findRecordInNestedList(name, false); + if (nestedScope) + return nestedScope; + } + T * nested_type = thisScope.findType(name); if (nested_type) { diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 082eda73141..94c6030364a 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -451,6 +451,7 @@ class TestSymbolDatabase : public TestFixture { TEST_CASE(enum15); TEST_CASE(enum16); TEST_CASE(enum17); + TEST_CASE(enum18); TEST_CASE(sizeOfType); @@ -6452,6 +6453,79 @@ class TestSymbolDatabase : public TestFixture { } } + void enum18() { + { + GET_SYMBOL_DB("namespace {\n" + " enum { E0 };\n" + "}\n" + "void f() {\n" + " if (0 > E0) {}\n" + "}\n"); + ASSERT(db != nullptr); + auto it = db->scopeList.begin(); + std::advance(it, 2); + const Enumerator* E0 = it->findEnumerator("E0"); + ASSERT(E0 && E0->value_known && E0->value == 0); + const Token* const e = Token::findsimplematch(tokenizer.tokens(), "E0 )"); + ASSERT(e && e->enumerator()); + ASSERT_EQUALS(E0, e->enumerator()); + } + { + GET_SYMBOL_DB("namespace ns {\n" // #12114 + " enum { V1 };\n" + " struct C1 {\n" + " enum { V2 };\n" + " };\n" + "}\n" + "using namespace ns;\n" + "void f() {\n" + " if (0 > V1) {}\n" + " if (0 > C1::V2) {}\n" + "}\n"); + ASSERT(db != nullptr); + auto it = db->scopeList.begin(); + std::advance(it, 2); + const Enumerator* V1 = it->findEnumerator("V1"); + ASSERT(V1 && V1->value_known && V1->value == 0); + const Token* const e1 = Token::findsimplematch(tokenizer.tokens(), "V1 )"); + ASSERT(e1 && e1->enumerator()); + ASSERT_EQUALS(V1, e1->enumerator()); + std::advance(it, 2); + const Enumerator* V2 = it->findEnumerator("V2"); + ASSERT(V2 && V2->value_known && V2->value == 0); + const Token* const e2 = Token::findsimplematch(tokenizer.tokens(), "V2 )"); + ASSERT(e2 && e2->enumerator()); + ASSERT_EQUALS(V2, e2->enumerator()); + } + { + GET_SYMBOL_DB("namespace ns {\n" + " enum { V1 };\n" + " struct C1 {\n" + " enum { V2 };\n" + " };\n" + "}\n" + "void f() {\n" + " using namespace ns;\n" + " if (0 > V1) {}\n" + " if (0 > C1::V2) {}\n" + "}\n"); + ASSERT(db != nullptr); + auto it = db->scopeList.begin(); + std::advance(it, 2); + const Enumerator* V1 = it->findEnumerator("V1"); + ASSERT(V1 && V1->value_known && V1->value == 0); + const Token* const e1 = Token::findsimplematch(tokenizer.tokens(), "V1 )"); + ASSERT(e1 && e1->enumerator()); + ASSERT_EQUALS(V1, e1->enumerator()); + std::advance(it, 2); + const Enumerator* V2 = it->findEnumerator("V2"); + ASSERT(V2 && V2->value_known && V2->value == 0); + const Token* const e2 = Token::findsimplematch(tokenizer.tokens(), "V2 )"); + ASSERT(e2 && e2->enumerator()); + ASSERT_EQUALS(V2, e2->enumerator()); + } + } + void sizeOfType() { // #7615 - crash in Symboldatabase::sizeOfType() GET_SYMBOL_DB("enum e;\n"