diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index 09be7b408..e4aef04d0 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -1082,6 +1082,18 @@ void CheckUnusedVar::checkStructMemberUsage() if (Token::findmatch(tok, s.c_str())) structname.clear(); + // Bail out if instance is initialized with {}.. + if (!structname.empty()) { + const std::string pattern1(structname + " %var% ;"); + const Token *tok2 = tok; + while (NULL != (tok2 = Token::findmatch(tok2->next(), pattern1.c_str()))) { + if (Token::simpleMatch(tok2->tokAt(3), (tok2->strAt(1) + " = {").c_str())) { + structname.clear(); + break; + } + } + } + // Try to prevent false positives when struct members are not used directly. if (Token::findmatch(tok, (structname + " *").c_str())) structname.clear(); diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 4910b0799..80107b5fd 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -45,6 +45,7 @@ private: TEST_CASE(structmember9); // #2017 - struct is inherited TEST_CASE(structmember_extern); // No false positives for extern structs TEST_CASE(structmember10); + TEST_CASE(structmember11); // #4168 - initialization with {} / passed by address to unknown function TEST_CASE(localvar1); TEST_CASE(localvar2); @@ -333,6 +334,18 @@ private: ASSERT_EQUALS("", errout.str()); } + void structmember11() { // #4168 + checkStructMemberUsage("struct abc { int x; };\n" + "struct abc s = {0};\n" + "void f() { do_something(&s); }\n"); + ASSERT_EQUALS("", errout.str()); + + checkStructMemberUsage("struct abc { int x; };\n" + "struct abc s = {0};\n" + "void f() { }\n"); + TODO_ASSERT_EQUALS("abc::x is not used", "", errout.str()); + } + void structmember_extern() { // extern struct => no false positive checkStructMemberUsage("extern struct AB\n"