From f2510228cb9b528969a19f1ce2040d850bb1a674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Tue, 20 Jun 2023 22:34:54 +0200 Subject: [PATCH] Fix #10847 (FP: unusedStructMember) (#5177) --- lib/checkunusedvar.cpp | 5 +++++ test/testunusedvar.cpp | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index b15f0175d..d427d730c 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -1515,6 +1515,11 @@ void CheckUnusedVar::checkStructMemberUsage() // Check if the struct member variable is used anywhere in the file bool use = false; for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { + if (Token::Match(tok, ". %name%") && !tok->next()->variable() && !tok->next()->function() && tok->next()->str() == var.name()) { + // not known => assume variable is used + use = true; + break; + } if (tok->variable() != &var) continue; if (tok != var.nameToken()) { diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index a1c580262..51562221b 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -71,6 +71,7 @@ private: TEST_CASE(structmember21); // #4759 TEST_CASE(structmember22); // #11016 TEST_CASE(structmember23); + TEST_CASE(structmember24); // #10847 TEST_CASE(structmember_macro); TEST_CASE(classmember); @@ -275,6 +276,9 @@ private: } void checkStructMemberUsageP(const char code[]) { + // Clear the error buffer.. + errout.str(""); + // Raw tokens.. std::vector files(1, "test.cpp"); std::istringstream istr(code); @@ -300,6 +304,9 @@ private: void checkFunctionVariableUsageP(const char code[], const char* filename = "test.cpp") { + // Clear the error buffer.. + errout.str(""); + // Raw tokens.. std::vector files(1, filename); std::istringstream istr(code); @@ -1707,7 +1714,7 @@ private: " t.i = 0;\n" // <- used " g(t);\n" "};\n"); - TODO_ASSERT_EQUALS("", "[test.cpp:1]: (style) struct member 'T::i' is never used.\n", errout.str()); // due to removeMacroInClassDef() + ASSERT_EQUALS("", errout.str()); // due to removeMacroInClassDef() } void structmember18() { // #10684 @@ -1869,7 +1876,7 @@ private: "public:\n" " int f() { return 0; }\n" "};\n" - "C C;\n" + "C c;\n" "int g() {\n" " return c.f();\n" "}\n" @@ -1905,6 +1912,29 @@ private: ASSERT_EQUALS("", errout.str()); } + void structmember24() { // #10847 + checkStructMemberUsage("struct S { std::map m; };\n" + "std::map u;\n" + "std::map::iterator f() {\n" + " return u.find(0)->second->m.begin();\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + checkStructMemberUsage("struct S { int i; };\n" + "void f() {\n" + " std::map m = { { 0, S() } };\n" + " m[0].i = 1;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + checkStructMemberUsage("struct S { bool b; };\n" + "std::vector v;\n" + "bool f() {\n" + " return v.begin()->b;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + } + void structmember_macro() { checkStructMemberUsageP("#define S(n) struct n { int a, b, c; };\n" "S(unused);\n");