* Fix #9389 ("debug: Executable scope 'x' with unknown function." with "using namespace") * use static rather than anonymous namespace for new functions
This commit is contained in:
parent
1c23366ea6
commit
fe1f601b91
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue