Skip to content

Commit

Permalink
fix #10305
Browse files Browse the repository at this point in the history
  • Loading branch information
ludviggunne committed Sep 12, 2024
1 parent 4cf5cc2 commit 7cf50ca
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 0 deletions.
23 changes: 23 additions & 0 deletions lib/checkunusedvar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1534,7 +1534,14 @@ void CheckUnusedVar::checkStructMemberUsage()
if (bailout)
continue;

// Keep track of number of non-static members encountered so far
int nummembs = 0;

for (const Variable &var : scope.varlist) {
if (!var.isStatic()) {
nummembs++;
}

// only warn for variables without side effects
if (!var.typeStartToken()->isStandardType() && !var.isPointer() && !astIsContainer(var.nameToken()) && !isRecordTypeWithoutSideEffects(var.type()))
continue;
Expand All @@ -1544,6 +1551,22 @@ 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->previous() || !Token::Match(tok->previous(), "class|struct")) && tok->str() == scope.className) {
const Token *inner = tok->next()->astOperand2();
// Find number of initialized members in braced initalizer
int initmembs = 0;
while (inner) {
initmembs++;
if (!inner->isInitComma()) {
break;
}
inner = inner->astOperand1();
}
if (initmembs >= nummembs) {
use = true;
break;
}
}
if (Token::Match(tok, ". %name%") && !tok->next()->variable() && !tok->next()->function() && tok->strAt(1) == var.name()) {
// not known => assume variable is used
use = true;
Expand Down
51 changes: 51 additions & 0 deletions test/testunusedvar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ class TestUnusedVar : public TestFixture {
TEST_CASE(structmember23);
TEST_CASE(structmember24); // #10847
TEST_CASE(structmember25);
TEST_CASE(structmember26); // #10305
TEST_CASE(structmember27);
TEST_CASE(structmember28);
TEST_CASE(structmember_macro);
TEST_CASE(classmember);

Expand Down Expand Up @@ -1962,6 +1965,54 @@ class TestUnusedVar : public TestFixture {
errout_str());
}

void structmember26() { // #10305
checkStructMemberUsage("struct S {\n"
" const int* p{};\n"
"};\n"
"struct C {\n"
" int i{};\n"
" S f() const {\n"
" return S{ &i };\n"
" }\n"
"};\n");
ASSERT_EQUALS("", errout_str());
}

void structmember27() {
checkStructMemberUsage("struct S {\n"
" const int* p{};\n"
" static int* q;\n"
" const int* r{};\n"
"};\n"
"struct C {\n"
" int i{};\n"
" int j{};\n"
" S f() const {\n"
" return S{ &i, &j };\n"
" }\n"
"};\n"
"int *S::q = 0;\n");
ASSERT_EQUALS("", errout_str());
}

void structmember28() {
checkStructMemberUsage("struct S {\n"
" const int* p{};\n"
" static int* q;\n"
" const int* r{};\n"
" const int* s{};"
"};\n"
"struct C {\n"
" int i{};\n"
" int j{};\n"
" S f() const {\n"
" return S{ &i, &j };\n"
" }\n"
"};\n"
"int *S::q = 0;\n");
ASSERT_EQUALS("[test.cpp:5]: (style) struct member 'S::s' is never used.\n", errout_str());
}

void structmember_macro() {
checkStructMemberUsageP("#define S(n) struct n { int a, b, c; };\n"
"S(unused);\n");
Expand Down

0 comments on commit 7cf50ca

Please sign in to comment.