Skip to content

Commit 0afe8a1

Browse files
authored
#12420: SymbolDatabase: function in blockscope (#5960)
1 parent 3efc6d3 commit 0afe8a1

2 files changed

Lines changed: 48 additions & 0 deletions

File tree

lib/symboldatabase.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,33 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
737737
} else {
738738
tok = tok->link();
739739
}
740+
} else if (Token::Match(tok, "%name% (")) {
741+
if (Token::simpleMatch(tok->linkAt(1), ") ;")) {
742+
const Token *funcStart = nullptr;
743+
const Token *argStart = nullptr;
744+
const Token *declEnd = nullptr;
745+
if (isFunction(tok, scope, &funcStart, &argStart, &declEnd)) {
746+
if (declEnd && declEnd->str() == ";") {
747+
bool newFunc = true; // Is this function already in the database?
748+
auto range = scope->functionMap.equal_range(tok->str());
749+
for (std::multimap<std::string, const Function*>::const_iterator it = range.first; it != range.second; ++it) {
750+
if (it->second->argsMatch(scope, it->second->argDef, argStart, emptyString, 0)) {
751+
newFunc = false;
752+
break;
753+
}
754+
}
755+
// save function prototype in database
756+
if (newFunc) {
757+
Function function(tok, scope, funcStart, argStart);
758+
if (function.isExtern()) {
759+
scope->addFunction(std::move(function));
760+
tok = declEnd;
761+
}
762+
}
763+
continue;
764+
}
765+
}
766+
}
740767
}
741768
// syntax error?
742769
if (!scope)
@@ -5902,6 +5929,10 @@ const Function* SymbolDatabase::findFunction(const Token* const tok) const
59025929
// find the scope this function is in
59035930
const Scope *currScope = tok->scope();
59045931
while (currScope && currScope->isExecutable()) {
5932+
if (const Function* f = currScope->findFunction(tok)) {
5933+
if (f->isExtern())
5934+
return f;
5935+
}
59055936
if (currScope->functionOf)
59065937
currScope = currScope->functionOf;
59075938
else

test/testsymboldatabase.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ class TestSymbolDatabase : public TestFixture {
270270
TEST_CASE(memberFunctionOfUnknownClassMacro2);
271271
TEST_CASE(memberFunctionOfUnknownClassMacro3);
272272
TEST_CASE(functionLinkage);
273+
TEST_CASE(externalFunctionsInsideAFunction); // #12420
273274

274275
TEST_CASE(classWithFriend);
275276

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

2365+
void externalFunctionsInsideAFunction() {
2366+
GET_SYMBOL_DB("void foo( void )\n"
2367+
"{\n"
2368+
" extern void bar( void );\n"
2369+
" bar();\n"
2370+
"}\n");
2371+
2372+
ASSERT(db && errout.str().empty());
2373+
2374+
const Token *f = Token::findsimplematch(tokenizer.tokens(), "bar");
2375+
ASSERT(f && f->function() && f->function()->isExtern() && f == f->function()->tokenDef && f->function()->retDef->str() == "void");
2376+
2377+
const Token *call = Token::findsimplematch(f->next(), "bar");
2378+
ASSERT(call && call->function() == f->function());
2379+
}
2380+
23642381
void classWithFriend() {
23652382
GET_SYMBOL_DB("class Foo {}; class Bar1 { friend class Foo; }; class Bar2 { friend Foo; };");
23662383
// 3 scopes: Global, 3 classes

0 commit comments

Comments
 (0)