Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions lib/symboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::string>& tokensThatAreNotEnumeratorValues) const
{
if (tok->isKeyword())
Expand Down Expand Up @@ -5268,6 +5284,8 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok, std::set<st
}
}
const Enumerator * enumerator = scope->findEnumerator(tokStr);
if (!enumerator)
enumerator = findEnumeratorInUsingList(scope, tokStr);

if (enumerator && !(enumerator->scope && enumerator->scope->enumClass))
return enumerator;
Expand Down Expand Up @@ -5310,6 +5328,8 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok, std::set<st
scope = scope->nestedIn;

enumerator = scope->findEnumerator(tokStr);
if (!enumerator)
enumerator = findEnumeratorInUsingList(scope, tokStr);

if (enumerator && !(enumerator->scope && enumerator->scope->enumClass))
return enumerator;
Expand All @@ -5319,6 +5339,17 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok, std::set<st

if (enumerator && !(enumerator->scope && 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;
}
}
}
}
}
Expand Down Expand Up @@ -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<S*>(u.scope)->findRecordInNestedList(name, false);
if (nestedScope)
return nestedScope;
}

T * nested_type = thisScope.findType(name);

if (nested_type) {
Expand Down
74 changes: 74 additions & 0 deletions test/testsymboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ class TestSymbolDatabase : public TestFixture {
TEST_CASE(enum15);
TEST_CASE(enum16);
TEST_CASE(enum17);
TEST_CASE(enum18);

TEST_CASE(sizeOfType);

Expand Down Expand Up @@ -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"
Expand Down