Symbol database: function lookup when :: is used. Ticket #4494

This commit is contained in:
Robert Reif 2013-01-22 06:55:25 +01:00 committed by Daniel Marjamäki
parent f68d6f7c95
commit ddb604d1a5
2 changed files with 84 additions and 5 deletions

View File

@ -2380,6 +2380,7 @@ const Function* SymbolDatabase::findFunctionByNameAndArgsInScope(const Token *to
const Function* SymbolDatabase::findFunctionByNameAndArgs(const Token *tok, const Scope *startScope) const const Function* SymbolDatabase::findFunctionByNameAndArgs(const Token *tok, const Scope *startScope) const
{ {
// find the scope this function is in
const Scope* currScope = startScope; const Scope* currScope = startScope;
while (currScope && currScope->isExecutable()) { while (currScope && currScope->isExecutable()) {
if (currScope->functionOf) if (currScope->functionOf)
@ -2387,11 +2388,60 @@ const Function* SymbolDatabase::findFunctionByNameAndArgs(const Token *tok, cons
else else
currScope = currScope->nestedIn; currScope = currScope->nestedIn;
} }
while (currScope) {
const Function *func = findFunctionByNameAndArgsInScope(tok, currScope); // check for a qualified name and use it when given
if (func) if (tok->strAt(-1) == "::") {
return func; // find start of qualified function name
currScope = currScope->nestedIn; const Token *tok1 = tok;
while (Token::Match(tok1->tokAt(-2), "%type% ::"))
tok1 = tok1->tokAt(-2);
// check for global scope
if (tok1->strAt(-1) == "::") {
currScope = &scopeList.front();
currScope = currScope->findRecordInNestedList(tok1->str());
}
// find start of qualification
else {
while (currScope) {
if (currScope->className == tok1->str())
break;
else {
const Scope *scope = currScope->findRecordInNestedList(tok1->str());
if (scope) {
currScope = scope;
break;
} else
currScope = currScope->nestedIn;
}
}
}
if (currScope) {
while (currScope && !Token::Match(tok1, "%type% :: %any% (")) {
currScope = currScope->findRecordInNestedList(tok1->strAt(2));
tok1 = tok1->tokAt(2);
}
tok1 = tok1->tokAt(2);
if (currScope && tok1)
return findFunctionByNameAndArgsInScope(tok1, currScope);
}
}
// check in enclosing scopes
else {
while (currScope) {
const Function *func = findFunctionByNameAndArgsInScope(tok, currScope);
if (func)
return func;
currScope = currScope->nestedIn;
}
} }
return 0; return 0;
} }

View File

@ -61,6 +61,7 @@ private:
TEST_CASE(uninitvar2_value); // value flow TEST_CASE(uninitvar2_value); // value flow
TEST_CASE(uninitvar2_structmembers); // struct members TEST_CASE(uninitvar2_structmembers); // struct members
TEST_CASE(uninitvar2_while); TEST_CASE(uninitvar2_while);
TEST_CASE(uninitvar2_4494); // #4494
} }
void checkUninitVar(const char code[], const char filename[] = "test.cpp") { void checkUninitVar(const char code[], const char filename[] = "test.cpp") {
@ -2686,6 +2687,34 @@ private:
TODO_ASSERT_EQUALS("error", "", errout.str()); TODO_ASSERT_EQUALS("error", "", errout.str());
} }
void uninitvar2_4494() {
checkUninitVar2("namespace N1 {\n"
" class Fred {\n"
" public:\n"
" static void f1(char *p) { *p = 0; }\n"
" };\n"
" void fa(void) { char *p; Fred::f1(p); }\n"
" void fb(void) { char *p; Fred::f2(p); }\n"
" void fc(void) { char *p; ::N1::Fred::f1(p); }\n"
" void fd(void) { char *p; ::N1::Fred::f2(p); }\n"
"}\n"
"namespace N2 {\n"
" static void f1(char *p) { *p = 0; }\n"
" void fa(void) { char *p; f1(p); }\n"
" void fb(void) { char *p; f2(p); }\n"
" void fc(void) { char *p; N1::Fred::f1(p); }\n"
" void fd(void) { char *p; N1::Fred::f2(p); }\n"
" void fe(void) { char *p; ::N1::Fred::f1(p); }\n"
" void ff(void) { char *p; ::N1::Fred::f2(p); }\n"
" void fg(void) { char *p; Foo::f1(p); }\n"
" void fh(void) { char *p; Foo::f2(p); }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:6]: (error) Uninitialized variable: p\n"
"[test.cpp:8]: (error) Uninitialized variable: p\n"
"[test.cpp:13]: (error) Uninitialized variable: p\n"
"[test.cpp:15]: (error) Uninitialized variable: p\n"
"[test.cpp:17]: (error) Uninitialized variable: p\n", errout.str());
}
}; };
REGISTER_TEST(TestUninitVar) REGISTER_TEST(TestUninitVar)