diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 8b9a0c658..54668f038 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2001,6 +2001,45 @@ Function::Function(const Tokenizer *mTokenizer, } } +static std::string qualifiedName(const Scope *scope) +{ + std::string name = scope->className; + while (scope->nestedIn) { + if (!scope->nestedIn->className.empty()) + name = (scope->nestedIn->className + " :: ") + name; + scope = scope->nestedIn; + } + return name; +} + +static bool usingNamespace(const Scope *scope, const Token *first, const Token *second, int &offset) +{ + offset = 0; + std::string name = first->str(); + + while (Token::Match(first, "%type% :: %type%")) { + if (offset) + name += (" :: " + first->str()); + offset += 2; + first = first->tokAt(2); + if (first->str() == second->str()) { + break; + } + } + + if (offset) { + while (scope) { + for (const auto & info : scope->usingList) { + if (name == qualifiedName(info.scope)) + return true; + } + scope = scope->nestedIn; + } + } + + return false; +} + bool Function::argsMatch(const Scope *scope, const Token *first, const Token *second, const std::string &path, nonneg int path_length) { const bool isCPP = scope->check->isCPP(); @@ -2008,6 +2047,7 @@ bool Function::argsMatch(const Scope *scope, const Token *first, const Token *se return true; int arg_path_length = path_length; + int offset = 0; while (first->str() == second->str() && first->isLong() == second->isLong() && @@ -2120,6 +2160,10 @@ bool Function::argsMatch(const Scope *scope, const Token *first, const Token *se } } + // using namespace + else if (usingNamespace(scope, first->next(), second->next(), offset)) + first = first->tokAt(offset); + // variable with class path else if (arg_path_length && Token::Match(first->next(), "%name%") && first->strAt(1) != "const") { std::string param = path; diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 055c48800..e0808027f 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -302,6 +302,7 @@ private: TEST_CASE(symboldatabase77); // #8663 TEST_CASE(symboldatabase78); // #9147 TEST_CASE(symboldatabase79); // #9392 + TEST_CASE(symboldatabase80); // #9389 TEST_CASE(createSymbolDatabaseFindAllScopes1); @@ -4287,6 +4288,67 @@ private: ASSERT(db->scopeList.back().functionList.front().isDefault() == true); } + void symboldatabase80() { // #9389 + { + GET_SYMBOL_DB("namespace ns {\n" + "class A {};\n" + "}\n" + "class AA {\n" + "private:\n" + " void f(const ns::A&);\n" + "};\n" + "using namespace ns;\n" + "void AA::f(const A&) { }"); + ASSERT(db->scopeList.size() == 5); + ASSERT(db->functionScopes.size() == 1); + const Scope *scope = db->findScopeByName("AA"); + ASSERT(scope); + ASSERT(scope->functionList.size() == 1); + ASSERT(scope->functionList.front().name() == "f"); + ASSERT(scope->functionList.front().hasBody() == true); + } + { + GET_SYMBOL_DB("namespace ns {\n" + "namespace ns1 {\n" + "class A {};\n" + "}\n" + "}\n" + "class AA {\n" + "private:\n" + " void f(const ns::ns1::A&);\n" + "};\n" + "using namespace ns::ns1;\n" + "void AA::f(const A&) { }"); + ASSERT(db->scopeList.size() == 6); + ASSERT(db->functionScopes.size() == 1); + const Scope *scope = db->findScopeByName("AA"); + ASSERT(scope); + ASSERT(scope->functionList.size() == 1); + ASSERT(scope->functionList.front().name() == "f"); + ASSERT(scope->functionList.front().hasBody() == true); + } + { + GET_SYMBOL_DB("namespace ns {\n" + "namespace ns1 {\n" + "class A {};\n" + "}\n" + "}\n" + "class AA {\n" + "private:\n" + " void f(const ns::ns1::A&);\n" + "};\n" + "using namespace ns;\n" + "void AA::f(const ns1::A&) { }"); + ASSERT(db->scopeList.size() == 6); + ASSERT(db->functionScopes.size() == 1); + const Scope *scope = db->findScopeByName("AA"); + ASSERT(scope); + ASSERT(scope->functionList.size() == 1); + ASSERT(scope->functionList.front().name() == "f"); + ASSERT(scope->functionList.front().hasBody() == true); + } + } + void createSymbolDatabaseFindAllScopes1() { GET_SYMBOL_DB("void f() { union {int x; char *p;} a={0}; }"); ASSERT(db->scopeList.size() == 3);