From 523c41a60b19159048204ea6555dd53e8a079b13 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 13 Sep 2023 11:39:09 +0200 Subject: [PATCH] Fix #11978 debug: Executable scope 'x' with unknown function. (#5437) --- lib/tokenize.cpp | 28 ++++++++++++++++++++++------ test/testsimplifytypedef.cpp | 14 ++++++++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 82edfe5e9b1..d1c5c1d0499 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1673,7 +1673,7 @@ void Tokenizer::simplifyTypedefCpp() } // check for member functions - else if (isCPP() && tok2->str() == "(" && isFunctionHead(tok2, "{")) { + else if (isCPP() && tok2->str() == "(" && isFunctionHead(tok2, "{:")) { const Token *func = tok2->previous(); /** @todo add support for multi-token operators */ @@ -4878,6 +4878,24 @@ static Token * matchMemberFunctionName(const Member &func, const std::list +static T* skipInitializerList(T* tok) +{ + T* const start = tok; + while (Token::Match(tok, "[:,] ::| %name%")) { + tok = tok->tokAt(tok->strAt(1) == "::" ? 1 : 2); + while (Token::Match(tok, ":: %name%")) + tok = tok->tokAt(2); + if (!Token::Match(tok, "[({<]") || !tok->link()) + return start; + const bool isTemplate = tok->str() == "<"; + tok = tok->link()->next(); + if (isTemplate && tok && tok->link()) + tok = tok->link()->next(); + } + return tok; +} + void Tokenizer::setVarIdPass2() { std::map> structMembers; @@ -5042,8 +5060,8 @@ void Tokenizer::setVarIdPass2() tok2 = tok2->link(); // Skip initialization list - while (Token::Match(tok2, ") [:,] %name% (")) - tok2 = tok2->linkAt(3); + if (Token::simpleMatch(tok2, ") :")) + tok2 = skipInitializerList(tok2->next()); } } @@ -8637,9 +8655,7 @@ void Tokenizer::simplifyFunctionTryCatch() if (!isFunctionHead(tok->previous(), "try")) continue; - Token* tryStartToken = tok->next(); - while (Token::Match(tryStartToken, "[:,] %name% (|{")) // skip init list - tryStartToken = tryStartToken->linkAt(2)->next(); + Token* tryStartToken = skipInitializerList(tok->next()); if (!Token::simpleMatch(tryStartToken, "{")) syntaxError(tryStartToken, "Invalid function-try-catch block code. Did not find '{' for try body."); diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index a87595e3e87..401266212d3 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -210,6 +210,7 @@ class TestSimplifyTypedef : public TestFixture { TEST_CASE(simplifyTypedef143); // #11506 TEST_CASE(simplifyTypedef144); // #9353 TEST_CASE(simplifyTypedef145); // #9353 + TEST_CASE(simplifyTypedef146); TEST_CASE(simplifyTypedefFunction1); TEST_CASE(simplifyTypedefFunction2); // ticket #1685 @@ -3365,6 +3366,19 @@ class TestSimplifyTypedef : public TestFixture { ASSERT_EQUALS("void g ( ) { sizeof ( t ) ; }", tok(code)); // TODO: handle implicit int } + void simplifyTypedef146() { + const char* code{}; + code = "namespace N {\n" // #11978 + " typedef int T;\n" + " struct C {\n" + " C(T*);\n" + " void* p;\n" + " };\n" + "}\n" + "N::C::C(T*) : p(nullptr) {}\n"; + ASSERT_EQUALS("namespace N { struct C { C ( int * ) ; void * p ; } ; } N :: C :: C ( int * ) : p ( nullptr ) { }", tok(code)); + } + void simplifyTypedefFunction1() { { const char code[] = "typedef void (*my_func)();\n"