diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 1d6a286ae..0be2ecb1e 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -844,6 +844,22 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() void SymbolDatabase::createSymbolDatabaseClassInfo() { if (!_tokenizer->isC()) { + // fill in using info + for (std::list::iterator it = scopeList.begin(); it != scopeList.end(); ++it) { + for (std::list::iterator i = it->usingList.begin(); i != it->usingList.end(); ++i) { + // only find if not already found + if (i->scope == nullptr) { + // check scope for match + Scope *scope = findScope(i->start->tokAt(2), &(*it)); + if (scope) { + // set found scope + i->scope = scope; + break; + } + } + } + } + // fill in base class info for (std::list::iterator it = typeList.begin(); it != typeList.end(); ++it) { // finish filling in base class info @@ -864,22 +880,6 @@ void SymbolDatabase::createSymbolDatabaseClassInfo() i->type = findType(i->nameStart, it->enclosingScope); } } - - // fill in using info - for (std::list::iterator it = scopeList.begin(); it != scopeList.end(); ++it) { - for (std::list::iterator i = it->usingList.begin(); i != it->usingList.end(); ++i) { - // only find if not already found - if (i->scope == nullptr) { - // check scope for match - Scope *scope = findScope(i->start->tokAt(2), &(*it)); - if (scope) { - // set found scope - i->scope = scope; - break; - } - } - } - } } } @@ -4401,14 +4401,16 @@ const Type* SymbolDatabase::findType(const Token *startTok, const Scope *startSc if (startTok->str() == startScope->className && startScope->isClassOrStruct() && startTok->strAt(1) != "::") return startScope->definedType; + const Scope* start_scope = startScope; + // absolute path - directly start in global scope if (startTok->str() == "::") { startTok = startTok->next(); - startScope = &scopeList.front(); + start_scope = &scopeList.front(); } const Token* tok = startTok; - const Scope* scope = startScope; + const Scope* scope = start_scope; while (scope && tok && tok->isName()) { if (tok->strAt(1) == "::") { @@ -4416,14 +4418,51 @@ const Type* SymbolDatabase::findType(const Token *startTok, const Scope *startSc if (scope) { tok = tok->tokAt(2); } else { - startScope = startScope->nestedIn; - if (!startScope) + start_scope = start_scope->nestedIn; + if (!start_scope) break; - scope = startScope; + scope = start_scope; tok = startTok; } - } else - return scope->findType(tok->str()); + } else { + const Type * type = scope->findType(tok->str()); + if (type) + return type; + else + break; + } + } + + // check using namespaces + while (startScope) { + for (std::list::const_iterator it = startScope->usingList.begin(); + it != startScope->usingList.end(); ++it) { + tok = startTok; + scope = it->scope; + start_scope = startScope; + + while (scope && tok && tok->isName()) { + if (tok->strAt(1) == "::") { + scope = scope->findRecordInNestedList(tok->str()); + if (scope) { + tok = tok->tokAt(2); + } else { + start_scope = start_scope->nestedIn; + if (!start_scope) + break; + scope = start_scope; + tok = startTok; + } + } else { + const Type * type = scope->findType(tok->str()); + if (type) + return type; + else + break; + } + } + } + startScope = startScope->nestedIn; } // not a valid path diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index a6cb3d49a..09e8b3381 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -255,6 +255,7 @@ private: TEST_CASE(symboldatabase55); // #7767 (return unknown macro) TEST_CASE(symboldatabase56); // #7909 TEST_CASE(symboldatabase57); + TEST_CASE(symboldatabase58); // #6985 (using namespace type lookup) TEST_CASE(enum1); TEST_CASE(enum2); @@ -2778,6 +2779,39 @@ private: } } + void symboldatabase58() { // #6985 (using namespace type lookup) + GET_SYMBOL_DB("namespace N2\n" + "{\n" + "class B { };\n" + "}\n" + "using namespace N2;\n" + "class C {\n" + " class A : public B\n" + " {\n" + " };\n" + "};"); + ASSERT(db != nullptr); + if (db) { + ASSERT(db->typeList.size() == 3U); + if (db->typeList.size() == 3U) { + std::list::const_iterator it = db->typeList.begin(); + const Type * classB = &(*it); + const Type * classC = &(*(++it)); + const Type * classA = &(*(++it)); + ASSERT(classA->name() == "A" && classB->name() == "B" && classC->name() == "C"); + if (classA->name() == "A" && classB->name() == "B" && classC->name() == "C") { + ASSERT(classA->derivedFrom.size() == 1U); + if (classA->derivedFrom.size() == 1) { + ASSERT(classA->derivedFrom[0].type); + if (classA->derivedFrom[0].type) { + ASSERT(classA->derivedFrom[0].type == classB); + } + } + } + } + } + } + void enum1() { GET_SYMBOL_DB("enum BOOL { FALSE, TRUE }; enum BOOL b;");