Skip to content

Commit

Permalink
Fix #11978 debug: Executable scope 'x' with unknown function. (danmar…
Browse files Browse the repository at this point in the history
  • Loading branch information
chrchr-github authored Sep 13, 2023
1 parent 5eb1750 commit 523c41a
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 6 deletions.
28 changes: 22 additions & 6 deletions lib/tokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -4878,6 +4878,24 @@ static Token * matchMemberFunctionName(const Member &func, const std::list<Scope
return Token::Match(tok, "~| %name% (") ? tok : nullptr;
}

template<typename T>
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<nonneg int, std::map<std::string, nonneg int>> structMembers;
Expand Down Expand Up @@ -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());
}
}

Expand Down Expand Up @@ -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.");
Expand Down
14 changes: 14 additions & 0 deletions test/testsimplifytypedef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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"
Expand Down

0 comments on commit 523c41a

Please sign in to comment.