diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index 9d9c113035f..3a38fe28e3c 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -1534,34 +1534,29 @@ void CheckUnusedVar::checkStructMemberUsage() if (bailout) continue; - // Structured binding assigned to variable - std::vector structBindUsage; - for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { - if (!Token::Match(tok, "] %assign% %var%")) + // Bailout if struct is used in structured binding + for (const Variable *var : symbolDatabase->variableList()) { + if (!var || !Token::simpleMatch(var->typeStartToken(), "auto")) continue; - const Variable *const var = tok->tokAt(2)->variable(); - if (!var || var->type()->classScope != &scope) + const Token *tok = var->nameToken()->previous(); + if (!Token::simpleMatch(tok, "[")) continue; - const Token *const startBracket = tok->link(); - if (!startBracket || - (!Token::Match(startBracket->tokAt(-2), "auto &|&&") && - !Token::simpleMatch(startBracket->previous(), "auto"))) + tok = tok->link(); + if (!Token::Match(tok, "] %assign%")) continue; - std::size_t bindCount = 1; - const Token *comma = startBracket->astOperand2(); - while (Token::simpleMatch(comma, ",")) { - ++bindCount; - comma = comma->astOperand1(); - } + tok = tok->next()->astOperand2(); + const ValueType *valueType = tok->valueType(); - auto end = scope.varlist.cbegin(); - std::advance(end, bindCount); - for (auto it = scope.varlist.cbegin(); it != end; ++it) - structBindUsage.push_back(it->index()); + if (valueType && valueType->typeScope == &scope) { + bailout = true; + break; + } } + if (bailout) + continue; for (const Variable &var : scope.varlist) { // only warn for variables without side effects @@ -1570,9 +1565,6 @@ void CheckUnusedVar::checkStructMemberUsage() if (isInherited && !var.isPrivate()) continue; - if (std::find(structBindUsage.cbegin(), structBindUsage.cend(), var.index()) != structBindUsage.cend()) - continue; - // 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()) { diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index c7af45b0e70..5262221b1c0 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -2036,13 +2036,14 @@ class TestUnusedVar : public TestFixture { ASSERT_EQUALS("", errout_str()); checkStructMemberUsage("struct S { int a, b; };\n" - "S f() {\n" - " S s{};\n" - " auto& [x] = s;\n" - " x = 1;\n" - " return s;\n" + "struct T { S s; };\n" + "T f() {\n" + " T t{};\n" + " auto& [x, y] = t.s;\n" + " x = y = 1;\n" + " return t;\n" "}\n"); - ASSERT_EQUALS("[test.cpp:1]: (style) struct member 'S::b' is never used.\n", errout_str()); + ASSERT_EQUALS("", errout_str()); } void functionVariableUsage_(const char* file, int line, const char code[], bool cpp = true) {