From a65ad1928626946ac1da7556c79f00c4b67755ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Thu, 30 Jul 2026 15:04:26 +0200 Subject: [PATCH 1/2] add test --- test/testsymboldatabase.cpp | 17 +++++++++++++++++ test/testunusedvar.cpp | 12 ++++++++++++ 2 files changed, 29 insertions(+) diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 1ce349cf969..eeaed0cbf3f 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -233,6 +233,7 @@ class TestSymbolDatabase : public TestFixture { TEST_CASE(rangeBasedFor); TEST_CASE(memberVar1); + TEST_CASE(memberVar2); TEST_CASE(arrayMemberVar1); TEST_CASE(arrayMemberVar2); TEST_CASE(arrayMemberVar3); @@ -1864,6 +1865,22 @@ class TestSymbolDatabase : public TestFixture { ASSERT(Token::simpleMatch(tok->variable()->typeStartToken(), "int x ;")); } + void memberVar2() { + GET_SYMBOL_DB( "struct S { void (*fp)(); };\n" + "void g();\n" + "void f() {\n" + " S s;\n" + " s.fp = g;\n" + " s.fp();\n" + "}\n"); + + ASSERT(db != nullptr); + const Token *fp1 = Token::findsimplematch(tokenizer.tokens(), "fp ="); + const Token *fp2 = Token::findsimplematch(tokenizer.tokens(), "fp ("); + ASSERT(fp1->varId()); + ASSERT_EQUALS(fp2->varId(), fp1->varId()); + } + void arrayMemberVar1() { GET_SYMBOL_DB("struct Foo {\n" " int x;\n" diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 0cf50a5ceb9..a56af38c0f5 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -158,6 +158,7 @@ class TestUnusedVar : public TestFixture { TEST_CASE(localvar71); TEST_CASE(localvar72); TEST_CASE(localvar73); + TEST_CASE(localvar74); TEST_CASE(localvarloops); // loops TEST_CASE(localvaralias1); TEST_CASE(localvaralias2); // ticket #1637 @@ -4100,6 +4101,17 @@ class TestUnusedVar : public TestFixture { ASSERT_EQUALS("", errout_str()); } + void localvar74() { + functionVariableUsage("struct S { void (*fp)(); };\n" + "void g();\n" + "void f() {\n" + " S s;\n" + " s.fp = g;\n" + " s.fp();\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + } + void localvarloops() { // loops functionVariableUsage("void fun(int c) {\n" From c55bdc9ae590f380f97e47386c2fe054514ed7c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Thu, 30 Jul 2026 15:02:20 +0200 Subject: [PATCH 2/2] fix --- lib/tokenize.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 5ebf6c51951..07ffa4c666c 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -4549,7 +4549,7 @@ static void setVarIdStructMembers(Token *&tok1, return; } - while (Token::Match(tok->next(), ")| . %name% !!(")) { + while (Token::Match(tok->next(), ")| . %name%")) { // Don't set varid for trailing return type if (tok->strAt(1) == ")" && Token::Match(tok->linkAt(1)->tokAt(-1), "%name%|]") && !tok->linkAt(1)->tokAt(-1)->isKeyword() && TokenList::isFunctionHead(tok->linkAt(1), "{;")) { @@ -4571,6 +4571,8 @@ static void setVarIdStructMembers(Token *&tok1, std::map& members = structMembers[struct_varid]; const auto it = utils::as_const(members).find(tok->str()); if (it == members.cend()) { + if (Token::Match(tok, "%name% (")) + break; members[tok->str()] = ++varId; tok->varId(varId); } else {