Skip to content

Commit f4eb733

Browse files
authored
fix #13967: SymbolDatabase: Set correct scope for namespaced struct declaration outside namespace (danmar#7634)
1 parent dfa16af commit f4eb733

File tree

2 files changed

+45
-2
lines changed

2 files changed

+45
-2
lines changed

lib/symboldatabase.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,30 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
173173

174174
const bool doProgress = (mSettings.reportProgress != -1);
175175

176+
std::map<Scope *, std::set<std::string>> forwardDecls;
177+
178+
const std::function<Scope *(const Token *, Scope *)> findForwardDeclScope = [&](const Token *tok, Scope *startScope) {
179+
if (tok->str() == "::")
180+
return findForwardDeclScope(tok->next(), &scopeList.front());
181+
182+
if (Token::Match(tok, "%name% :: %name%")) {
183+
auto it = std::find_if(startScope->nestedList.cbegin(), startScope->nestedList.cend(), [&](const Scope *scope) {
184+
return scope->className == tok->str();
185+
});
186+
187+
if (it == startScope->nestedList.cend())
188+
return static_cast<Scope *>(nullptr);
189+
190+
return findForwardDeclScope(tok->tokAt(2), *it);
191+
}
192+
193+
auto it = forwardDecls.find(startScope);
194+
if (it == forwardDecls.cend())
195+
return static_cast<Scope *>(nullptr);
196+
197+
return it->second.count(tok->str()) > 0 ? startScope : nullptr;
198+
};
199+
176200
// find all scopes
177201
for (const Token *tok = mTokenizer.tokens(); tok; tok = tok ? tok->next() : nullptr) {
178202
// #5593 suggested to add here:
@@ -291,7 +315,11 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
291315
scope = new_scope;
292316
tok = tok2;
293317
} else {
294-
scopeList.emplace_back(*this, tok, scope);
318+
319+
const Scope *forwardDeclScope = findForwardDeclScope(tok->next(), scope);
320+
const Scope *nestedIn = forwardDeclScope ? forwardDeclScope : scope;
321+
322+
scopeList.emplace_back(*this, tok, nestedIn);
295323
new_scope = &scopeList.back();
296324

297325
if (tok->str() == "class")
@@ -303,7 +331,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
303331
if (new_scope->isClassOrStructOrUnion() || new_scope->type == ScopeType::eEnum) {
304332
Type* new_type = findType(name, scope);
305333
if (!new_type) {
306-
typeList.emplace_back(new_scope->classDef, new_scope, scope);
334+
typeList.emplace_back(new_scope->classDef, new_scope, nestedIn);
307335
new_type = &typeList.back();
308336
scope->definedTypesMap[new_type->name()] = new_type;
309337
} else
@@ -386,6 +414,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
386414
typeList.emplace_back(tok, nullptr, scope);
387415
Type* new_type = &typeList.back();
388416
scope->definedTypesMap[new_type->name()] = new_type;
417+
forwardDecls[scope].insert(tok->strAt(1));
389418
}
390419
tok = tok->tokAt(2);
391420
}

test/testsymboldatabase.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ class TestSymbolDatabase : public TestFixture {
319319
TEST_CASE(namespaces2);
320320
TEST_CASE(namespaces3); // #3854 - unknown macro
321321
TEST_CASE(namespaces4);
322+
TEST_CASE(namespaces5); // #13967
322323
TEST_CASE(needInitialization);
323324

324325
TEST_CASE(tryCatch1);
@@ -3210,6 +3211,19 @@ class TestSymbolDatabase : public TestFixture {
32103211
ASSERT_EQUALS(2U, fredAType->classDef->linenr());
32113212
}
32123213

3214+
void namespaces5() { // #13967
3215+
GET_SYMBOL_DB("namespace test {\n"
3216+
" template <int S>\n"
3217+
" struct Test { int x[S]; };\n"
3218+
" const Test<64> test;\n"
3219+
"}\n");
3220+
const Variable *x = db->getVariableFromVarId(2U);
3221+
ASSERT_EQUALS("x", x->name());
3222+
const Scope *scope = x->scope();
3223+
ASSERT(scope->nestedIn);
3224+
ASSERT_EQUALS("test", scope->nestedIn->className);
3225+
}
3226+
32133227
void needInitialization() {
32143228
{
32153229
GET_SYMBOL_DB_DBG("template <typename T>\n" // #10259

0 commit comments

Comments
 (0)