Symbol database: function lookup when :: is used. Ticket #4494
This commit is contained in:
parent
f68d6f7c95
commit
ddb604d1a5
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue