Skip to content

Commit cc18720

Browse files
authored
fix #13269: FN: unusedVariable with structured binding (#7701)
1 parent 55e2dc6 commit cc18720

File tree

2 files changed

+71
-2
lines changed

2 files changed

+71
-2
lines changed

lib/checkunusedvar.cpp

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,7 +1186,24 @@ void CheckUnusedVar::checkFunctionVariableUsage()
11861186
const Token* lambdaOrInlineStart{};
11871187
const bool hasLambdaOrInline = scope->hasInlineOrLambdaFunction(&lambdaOrInlineStart);
11881188

1189+
const Token *nextStructuredBindingTok = nullptr;
1190+
std::vector<std::pair<const Token*, const Token*>> unusedStructuredBindingTokens;
1191+
size_t structuredBindingTokCount = 0;
1192+
11891193
for (const Token *tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) {
1194+
if (nextStructuredBindingTok) {
1195+
tok = nextStructuredBindingTok;
1196+
} else {
1197+
if (structuredBindingTokCount > 0 && structuredBindingTokCount == unusedStructuredBindingTokens.size()) {
1198+
for (const auto &pair : unusedStructuredBindingTokens) {
1199+
unreadVariableError(pair.first, pair.second->expressionString(), false);
1200+
}
1201+
}
1202+
structuredBindingTokCount = 0;
1203+
unusedStructuredBindingTokens.clear();
1204+
}
1205+
nextStructuredBindingTok = nullptr;
1206+
11901207
if (findLambdaEndToken(tok))
11911208
// todo: handle lambdas
11921209
break;
@@ -1196,6 +1213,16 @@ void CheckUnusedVar::checkFunctionVariableUsage()
11961213
const Token *varDecl = nullptr;
11971214
if (tok->variable() && tok->variable()->nameToken() == tok) {
11981215
const Token * eq = tok->next();
1216+
if (isStructuredBindingVariable(tok->variable())) {
1217+
structuredBindingTokCount++;
1218+
while (!Token::simpleMatch(eq, "]")) {
1219+
eq = eq->next();
1220+
if (eq->variable() && !nextStructuredBindingTok)
1221+
nextStructuredBindingTok = eq;
1222+
}
1223+
if (eq)
1224+
eq = eq->next();
1225+
}
11991226
while (Token::simpleMatch(eq, "["))
12001227
eq = eq->link()->next();
12011228
if (Token::simpleMatch(eq, ") (") && Token::simpleMatch(eq->linkAt(1), ") ="))
@@ -1333,8 +1360,12 @@ void CheckUnusedVar::checkFunctionVariableUsage()
13331360
continue;
13341361

13351362
// warn
1336-
if (!expr->variable() || !expr->variable()->isMaybeUnused())
1337-
unreadVariableError(tok, expr->expressionString(), false);
1363+
if (!expr->variable() || !expr->variable()->isMaybeUnused()) {
1364+
if (structuredBindingTokCount > 0)
1365+
unusedStructuredBindingTokens.emplace_back(tok, expr);
1366+
else
1367+
unreadVariableError(tok, expr->expressionString(), false);
1368+
}
13381369
}
13391370
}
13401371

test/testunusedvar.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ class TestUnusedVar : public TestFixture {
259259
TEST_CASE(escapeAlias); // #9150
260260
TEST_CASE(volatileData); // #9280
261261
TEST_CASE(globalData);
262+
263+
TEST_CASE(structuredBinding); // #13269
262264
}
263265

264266
struct FunctionVariableUsageOptions
@@ -7197,6 +7199,42 @@ class TestUnusedVar : public TestFixture {
71977199
"}");
71987200
ASSERT_EQUALS("", errout_str());
71997201
}
7202+
7203+
void structuredBinding() { // #13269
7204+
functionVariableUsage("int main()\n"
7205+
"{\n"
7206+
" auto [a, b] = std::make_pair(42, 0.42);\n"
7207+
"}\n");
7208+
ASSERT_EQUALS("[test.cpp:3:17]: (style) Variable 'a' is assigned a value that is never used. [unreadVariable]\n"
7209+
"[test.cpp:3:17]: (style) Variable 'b' is assigned a value that is never used. [unreadVariable]\n", errout_str());
7210+
7211+
functionVariableUsage("int main()\n"
7212+
"{\n"
7213+
" auto [a, b] = std::make_pair(42, 0.42);\n"
7214+
" (void) a;\n"
7215+
"}\n");
7216+
ASSERT_EQUALS("", errout_str());
7217+
7218+
functionVariableUsage("int main()\n"
7219+
"{\n"
7220+
" auto [a, b] = std::make_pair(42, 0.42);\n"
7221+
" (void) b;\n"
7222+
"}\n");
7223+
ASSERT_EQUALS("", errout_str());
7224+
7225+
functionVariableUsage("int main()\n"
7226+
"{\n"
7227+
" auto [a, b, c] = std::make_pair(42, 0.42);\n"
7228+
" (void) b;\n"
7229+
"}\n");
7230+
ASSERT_EQUALS("", errout_str());
7231+
7232+
functionVariableUsage("int main()\n"
7233+
"{\n"
7234+
" [[maybe_unused]] auto [a2, b3] = std::make_pair(42, 0.42);\n"
7235+
"}\n");
7236+
ASSERT_EQUALS("", errout_str());
7237+
}
72007238
};
72017239

72027240
REGISTER_TEST(TestUnusedVar)

0 commit comments

Comments
 (0)