diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index f5ffa4e1604..f1c2ee0a14a 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -5266,6 +5266,26 @@ const Variable *Scope::getVariable(const std::string &varname) const static const Token* skipPointers(const Token* tok) { + const Token *start = tok; + bool memberPointer = false; + while (tok) { + if (Token::simpleMatch(tok, "::")) { + tok = tok->next(); + continue; + } + if (Token::Match(tok, "%type% ::")) { + tok = tok->tokAt(2); + memberPointer = true; + continue; + } + if (Token::Match(tok, "%type% <") && tok->linkAt(1)) { + tok = tok->linkAt(1)->next(); + continue; + } + break; + } + if (memberPointer && !Token::simpleMatch(tok, "*")) + return start; while (Token::Match(tok, "*|&|&&") || (Token::Match(tok, "( [*&]") && Token::Match(tok->link()->next(), "(|["))) { tok = tok->next(); if (tok && tok->strAt(-1) == "(" && Token::Match(tok, "%type% ::")) diff --git a/test/testother.cpp b/test/testother.cpp index fadb61426a4..d72d3a37940 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -10429,7 +10429,7 @@ class TestOther : public TestFixture { // Member variable pointers check("void podMemPtrs() {\n" - " int POD::*memptr;\n" + " const int POD::*memptr;\n" " memptr = &POD::a;\n" " memptr = &POD::b;\n" " if (memptr)\n" diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 0a676d00218..50f67823b4e 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -77,6 +77,8 @@ class TestUnusedVar : public TestFixture { TEST_CASE(structmember29); // #14075 TEST_CASE(structmember30); // #14131 TEST_CASE(structmember31); // #14130 + TEST_CASE(structmember32); // #14483 + TEST_CASE(structmember33); TEST_CASE(structmember_macro); TEST_CASE(structmember_template_argument); // #13887 - do not report that member used in template argument is unused TEST_CASE(classmember); @@ -2066,6 +2068,20 @@ class TestUnusedVar : public TestFixture { ASSERT_EQUALS("", errout_str()); } + void structmember32() { // #14483 + checkStructMemberUsage("struct S {\n" + " int S::* mp;\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:2:12]: (style) struct member 'S::mp' is never used. [unusedStructMember]\n", errout_str()); + } + + void structmember33() { + checkStructMemberUsage("struct S {\n" + " int A::B::C::* mp;\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:2:23]: (style) struct member 'S::mp' is never used. [unusedStructMember]\n", errout_str()); + } + void structmember_macro() { checkStructMemberUsageP("#define S(n) struct n { int a, b, c; };\n" "S(unused);\n");