Skip to content

Commit

Permalink
FIX #12432: Crash in setValueTypeInTokenList() (danmar#5978)
Browse files Browse the repository at this point in the history
  • Loading branch information
olabetskyi committed Feb 13, 2024
1 parent 0c82876 commit d145f9c
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 9 deletions.
20 changes: 12 additions & 8 deletions lib/symboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -737,15 +737,21 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
} else {
tok = tok->link();
}
} else if (Token::Match(tok, "%name% (")) {
if (Token::simpleMatch(tok->linkAt(1), ") ;")) {
} else if (Token::Match(tok, "extern %type%")) {
const Token * ftok = tok->next();
while (Token::Match(ftok, "%name%|*|&"))
ftok = ftok->next();
if (!ftok || ftok->str() != "(")
continue;
ftok = ftok->previous();
if (Token::simpleMatch(ftok->linkAt(1), ") ;")) {
const Token *funcStart = nullptr;
const Token *argStart = nullptr;
const Token *declEnd = nullptr;
if (isFunction(tok, scope, &funcStart, &argStart, &declEnd)) {
if (isFunction(ftok, 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());
auto range = scope->functionMap.equal_range(ftok->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;
Expand All @@ -754,13 +760,12 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
}
// save function prototype in database
if (newFunc) {
Function function(tok, scope, funcStart, argStart);
Function function(ftok, scope, funcStart, argStart);
if (function.isExtern()) {
scope->addFunction(std::move(function));
tok = declEnd;
}
}
continue;
}
}
}
Expand Down Expand Up @@ -5930,8 +5935,7 @@ const Function* SymbolDatabase::findFunction(const Token* const tok) const
const Scope *currScope = tok->scope();
while (currScope && currScope->isExecutable()) {
if (const Function* f = currScope->findFunction(tok)) {
if (f->isExtern())
return f;
return f;
}
if (currScope->functionOf)
currScope = currScope->functionOf;
Expand Down
17 changes: 16 additions & 1 deletion test/testsymboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,8 @@ class TestSymbolDatabase : public TestFixture {
TEST_CASE(memberFunctionOfUnknownClassMacro2);
TEST_CASE(memberFunctionOfUnknownClassMacro3);
TEST_CASE(functionLinkage);
TEST_CASE(externalFunctionsInsideAFunction); // #12420
TEST_CASE(externalFunctionsInsideAFunction); // #12420
TEST_CASE(namespacedFunctionInsideExternBlock); // #12420

TEST_CASE(classWithFriend);

Expand Down Expand Up @@ -2378,6 +2379,20 @@ class TestSymbolDatabase : public TestFixture {
ASSERT(call && call->function() == f->function());
}

void namespacedFunctionInsideExternBlock() {
// Should not crash
GET_SYMBOL_DB("namespace N {\n"
" void f();\n"
"}\n"
"extern \"C\" {\n"
" void f() {\n"
" N::f();\n"
" }\n"
"}\n");

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

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 d145f9c

Please sign in to comment.