Skip to content

Commit

Permalink
#12420: SymbolDatabase: function in blockscope (#5960)
Browse files Browse the repository at this point in the history
  • Loading branch information
olabetskyi authored Feb 12, 2024
1 parent 3efc6d3 commit 0afe8a1
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 0 deletions.
31 changes: 31 additions & 0 deletions lib/symboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,33 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
} else {
tok = tok->link();
}
} else if (Token::Match(tok, "%name% (")) {
if (Token::simpleMatch(tok->linkAt(1), ") ;")) {
const Token *funcStart = nullptr;
const Token *argStart = nullptr;
const Token *declEnd = nullptr;
if (isFunction(tok, scope, &funcStart, &argStart, &declEnd)) {
if (declEnd && declEnd->str() == ";") {
bool newFunc = true; // Is this function already in the database?
auto range = scope->functionMap.equal_range(tok->str());
for (std::multimap<std::string, const Function*>::const_iterator it = range.first; it != range.second; ++it) {
if (it->second->argsMatch(scope, it->second->argDef, argStart, emptyString, 0)) {
newFunc = false;
break;
}
}
// save function prototype in database
if (newFunc) {
Function function(tok, scope, funcStart, argStart);
if (function.isExtern()) {
scope->addFunction(std::move(function));
tok = declEnd;
}
}
continue;
}
}
}
}
// syntax error?
if (!scope)
Expand Down Expand Up @@ -5902,6 +5929,10 @@ const Function* SymbolDatabase::findFunction(const Token* const tok) const
// find the scope this function is in
const Scope *currScope = tok->scope();
while (currScope && currScope->isExecutable()) {
if (const Function* f = currScope->findFunction(tok)) {
if (f->isExtern())
return f;
}
if (currScope->functionOf)
currScope = currScope->functionOf;
else
Expand Down
17 changes: 17 additions & 0 deletions test/testsymboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ class TestSymbolDatabase : public TestFixture {
TEST_CASE(memberFunctionOfUnknownClassMacro2);
TEST_CASE(memberFunctionOfUnknownClassMacro3);
TEST_CASE(functionLinkage);
TEST_CASE(externalFunctionsInsideAFunction); // #12420

TEST_CASE(classWithFriend);

Expand Down Expand Up @@ -2361,6 +2362,22 @@ class TestSymbolDatabase : public TestFixture {
ASSERT(f && f->function() && !f->function()->isExtern() && f->function()->retDef->str() == "void");
}

void externalFunctionsInsideAFunction() {
GET_SYMBOL_DB("void foo( void )\n"
"{\n"
" extern void bar( void );\n"
" bar();\n"
"}\n");

ASSERT(db && errout.str().empty());

const Token *f = Token::findsimplematch(tokenizer.tokens(), "bar");
ASSERT(f && f->function() && f->function()->isExtern() && f == f->function()->tokenDef && f->function()->retDef->str() == "void");

const Token *call = Token::findsimplematch(f->next(), "bar");
ASSERT(call && call->function() == f->function());
}

void classWithFriend() {
GET_SYMBOL_DB("class Foo {}; class Bar1 { friend class Foo; }; class Bar2 { friend Foo; };");
// 3 scopes: Global, 3 classes
Expand Down

0 comments on commit 0afe8a1

Please sign in to comment.