From a197e94573cbb5c30ee1f347fb1240f8d2de3e63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 8 May 2021 13:40:52 +0200 Subject: [PATCH] Fixed #10266 (False positive; parameter can be const) --- lib/checkother.cpp | 34 ++++++++++++++++++++++++++++------ test/testother.cpp | 6 ++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index f565b35cf..92e4eaf11 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1413,12 +1413,34 @@ void CheckOther::checkConstVariable() //Is it the right side of an initialization of a non-const reference bool usedInAssignment = false; for (const Token* tok = var->nameToken(); tok != scope->bodyEnd && tok != nullptr; tok = tok->next()) { - if (!Token::Match(tok, "& %var% = %varid%", var->declarationId())) - continue; - const Variable* refvar = tok->next()->variable(); - if (refvar && !refvar->isConst() && refvar->nameToken() == tok->next()) { - usedInAssignment = true; - break; + if (Token::Match(tok, "& %var% = %varid%", var->declarationId())) { + const Variable* refvar = tok->next()->variable(); + if (refvar && !refvar->isConst() && refvar->nameToken() == tok->next()) { + usedInAssignment = true; + break; + } + } else if (Token::Match(tok, "auto &| [")) { + // structured binding taking reference.. + const Token *tok2 = tok->next(); + if (tok2->str() == "&") + tok2 = tok2->next(); + tok2 = tok2->link(); + if (Token::Match(tok2, "] [:=] %varid% [);]", var->declarationId())) { + if (tok->next()->str() == "&") { + usedInAssignment = true; + break; + } + while (tok2 != tok) { + if (tok2->varId()) { + const Variable* refvar = tok2->variable(); + if (!refvar || (!refvar->isConst() && refvar->isReference())) { + usedInAssignment = true; + break; + } + } + tok2 = tok2->previous(); + } + } } } if (usedInAssignment) diff --git a/test/testother.cpp b/test/testother.cpp index 0761b3e4d..e5c13ae29 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -2596,6 +2596,12 @@ private: "{\n" "}"); TODO_ASSERT_EQUALS("[test.cpp:16]: (style) Parameter 'i' can be declared with const\n", "", errout.str()); + + check("void f(std::map> &map) {\n" // #10266 + " for (auto &[slave, panels] : map)\n" + " panels.erase(it);\n" + "}"); + ASSERT_EQUALS("", errout.str()); } void constParameterCallback() {