fix #10127 (debug: Executable scope 'x' with unknown function.) (#3077)

This commit is contained in:
IOBYTE 2021-01-23 11:55:25 -05:00 committed by GitHub
parent c860de8565
commit a4953575f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 3 deletions

View File

@ -1996,6 +1996,36 @@ bool Tokenizer::isMemberFunction(const Token *openParen) const
isFunctionHead(openParen, "{|:");
}
static bool scopesMatch(const std::string &scope1, const std::string &scope2, const std::list<ScopeInfo3> &scopeList)
{
if (scope1.empty() || scope2.empty())
return false;
// check if scopes match
if (scope1 == scope2)
return true;
if (scopeList.size() < 2)
return false;
// check if scopes only differ by global qualification
if (scope1 == (":: " + scope2)) {
std::string::size_type end = scope2.find_first_of(' ');
if (end == std::string::npos)
end = scope2.size();
if ((++scopeList.begin())->name == scope2.substr(0, end))
return true;
} else if (scope2 == (":: " + scope1)) {
std::string::size_type end = scope1.find_first_of(' ');
if (end == std::string::npos)
end = scope1.size();
if ((++scopeList.begin())->name == scope1.substr(0, end))
return true;
}
return false;
}
bool Tokenizer::simplifyUsing()
{
bool substitute = false;
@ -2159,7 +2189,7 @@ bool Tokenizer::simplifyUsing()
// remove the qualification
std::string fullScope = scope;
std::string removed;
while (tok1->strAt(-1) == "::") {
while (Token::Match(tok1->tokAt(-2), "%name% ::") && !tok1->tokAt(-2)->isKeyword()) {
removed = (tok1->strAt(-2) + " :: ") + removed;
if (fullScope == tok1->strAt(-2)) {
tok1->deletePrevious();
@ -2180,6 +2210,12 @@ bool Tokenizer::simplifyUsing()
}
}
// remove global namespace if present
if (tok1->strAt(-1) == "::") {
removed.insert(0, ":: ");
tok1->deletePrevious();
}
Token * arrayStart = nullptr;
// parse the type
@ -2297,7 +2333,7 @@ bool Tokenizer::simplifyUsing()
std::string::size_type idx = removed1.rfind(" ::");
if (idx != std::string::npos)
removed1.resize(idx);
if (removed1 == scope && !removed1.empty()) {
if (scopesMatch(removed1, scope, scopeList)) {
for (std::list<ScopeInfo3>::const_reverse_iterator it = scopeList.crbegin(); it != scopeList.crend(); ++it) {
if (it->recordTypes.find(start->str()) != it->recordTypes.end()) {
std::string::size_type spaceIdx = 0;

View File

@ -402,7 +402,8 @@ private:
TEST_CASE(findFunction35);
TEST_CASE(findFunction36); // #10122
TEST_CASE(findFunction37); // #10124
TEST_CASE(findFunction38); // #10152
TEST_CASE(findFunction38); // #10125
TEST_CASE(findFunction39); // #10127
TEST_CASE(findFunctionContainer);
TEST_CASE(findFunctionExternC);
TEST_CASE(findFunctionGlobalScope); // ::foo
@ -6322,6 +6323,26 @@ private:
ASSERT_EQUALS(6, functok->function()->tokenDef->linenr());
}
void findFunction39() { // #10127
GET_SYMBOL_DB("namespace external {\n"
" class V {\n"
" public:\n"
" using I = int;\n"
" };\n"
"}\n"
"class A {\n"
" void f(external::V::I);\n"
"};\n"
"using ::external::V;\n"
"void A::f(V::I) {}");
ASSERT_EQUALS("", errout.str());
const Token *functok = Token::findsimplematch(tokenizer.tokens(), "f ( int )");
ASSERT(functok);
ASSERT(functok->function());
ASSERT(functok->function()->name() == "f");
ASSERT_EQUALS(8, functok->function()->tokenDef->linenr());
}
void findFunctionContainer() {
{
GET_SYMBOL_DB("void dostuff(std::vector<int> v);\n"