From 4d67e2492010892607c119f2c0c4b1ee4e20b2b0 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 21 Feb 2026 22:30:50 +0100 Subject: [PATCH 1/4] Fix #7091 FN variableScope for variables used in inner loop --- lib/checkother.cpp | 5 ++++- test/testother.cpp | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index cf5ecb65b91..5674b5a433b 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1370,7 +1370,7 @@ bool CheckOther::checkInnerScope(const Token *tok, const Variable* var, bool& us if (tok == forHeadEnd) forHeadEnd = nullptr; - if (loopVariable && noContinue && tok->scope() == scope && !forHeadEnd && scope->type != ScopeType::eSwitch && Token::Match(tok, "%varid% =", var->declarationId())) { // Assigned in outer scope. + if (loopVariable && noContinue && (tok->scope() == scope || tok->scope()->type != ScopeType::eSwitch) && !forHeadEnd && scope->type != ScopeType::eSwitch && Token::Match(tok, "%varid% =", var->declarationId())) { // Assigned in outer scope. loopVariable = false; std::pair range = tok->next()->findExpressionStartEndTokens(); if (range.first) @@ -1546,6 +1546,9 @@ void CheckOther::checkPassByReference() if (!var || !var->isClass() || var->isPointer() || (var->isArray() && !var->isStlType()) || var->isReference() || var->isEnumType()) continue; + if (!var->scope()) + continue; + const bool isRangeBasedFor = astIsRangeBasedForDecl(var->nameToken()); if (!var->isArgument() && !isRangeBasedFor) continue; diff --git a/test/testother.cpp b/test/testother.cpp index 21a640a3c7d..deb0ea7428a 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -123,6 +123,7 @@ class TestOther : public TestFixture { TEST_CASE(varScope43); TEST_CASE(varScope44); TEST_CASE(varScope45); + TEST_CASE(varScope46); TEST_CASE(oldStylePointerCast); TEST_CASE(intToPointerCast); @@ -1984,6 +1985,20 @@ class TestOther : public TestFixture { ASSERT_EQUALS("[test.cpp:2:16]: (style) The scope of the variable 'b' can be reduced. [variableScope]\n", errout_str()); } + void varScope46() { + check("void f() {\n" + " int y1;\n" + " for (int i = 0; i < 3; ++i) {\n" + " for(int j = 0; j < 3; ++j) {\n" + " y1 = 2 * 1;\n" + " y1 += 1;\n" + " }\n" + " }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:9]: (style) The scope of the variable 'y1' can be reduced. [variableScope]\n", + errout_str()); + } + #define checkOldStylePointerCast(...) checkOldStylePointerCast_(__FILE__, __LINE__, __VA_ARGS__) template void checkOldStylePointerCast_(const char* file, int line, const char (&code)[size], Standards::cppstd_t std = Standards::CPPLatest) { From e7e52bb9e8211166cb5f9c3f007e9b602bbacad8 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 21 Feb 2026 22:35:22 +0100 Subject: [PATCH 2/4] Undo --- lib/checkother.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 5674b5a433b..c369d38bf2e 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1546,9 +1546,6 @@ void CheckOther::checkPassByReference() if (!var || !var->isClass() || var->isPointer() || (var->isArray() && !var->isStlType()) || var->isReference() || var->isEnumType()) continue; - if (!var->scope()) - continue; - const bool isRangeBasedFor = astIsRangeBasedForDecl(var->nameToken()); if (!var->isArgument() && !isRangeBasedFor) continue; From c6daf4347c78892a53b1687724139e3b94d61321 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sun, 22 Feb 2026 00:10:08 +0100 Subject: [PATCH 3/4] Fix --- lib/checkother.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index c369d38bf2e..3ce723b7656 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1331,6 +1331,13 @@ static bool mayDependOn(const ValueType *other, const ValueType *original) return otherPtr > originalPtr; } +static bool isOnlyUsedInCurrentScope(const Variable* var, const Token *tok, const Scope* scope) +{ + if (tok->scope() == scope) + return true; + return !Token::findmatch(tok->scope()->bodyEnd, "%varid%", scope->bodyEnd, var->declarationId()); +} + bool CheckOther::checkInnerScope(const Token *tok, const Variable* var, bool& used) const { const Scope* scope = tok->next()->scope(); @@ -1370,7 +1377,8 @@ bool CheckOther::checkInnerScope(const Token *tok, const Variable* var, bool& us if (tok == forHeadEnd) forHeadEnd = nullptr; - if (loopVariable && noContinue && (tok->scope() == scope || tok->scope()->type != ScopeType::eSwitch) && !forHeadEnd && scope->type != ScopeType::eSwitch && Token::Match(tok, "%varid% =", var->declarationId())) { // Assigned in outer scope. + if (loopVariable && noContinue && !forHeadEnd && scope->type != ScopeType::eSwitch && Token::Match(tok, "%varid% =", var->declarationId()) && + isOnlyUsedInCurrentScope(var, tok, scope)) { // Assigned in outer scope. loopVariable = false; std::pair range = tok->next()->findExpressionStartEndTokens(); if (range.first) @@ -1869,6 +1877,8 @@ void CheckOther::checkConstPointer() continue; if (!var->isLocal() && !var->isArgument()) continue; + if (var->isArgument() && var->scope() && var->scope()->type == ScopeType::eLambda) + continue; const Token* const nameTok = var->nameToken(); if (tok == nameTok && var->isLocal() && !astIsRangeBasedForDecl(nameTok)) { if (var->isReference() && var->isPointer()) { From 6241809fe8ec657a099ae585c6bf77cd3d5b1d1a Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sun, 22 Feb 2026 10:42:10 +0100 Subject: [PATCH 4/4] Fix --- lib/checkother.cpp | 2 ++ test/testother.cpp | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 3ce723b7656..16d42f6fff7 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1335,6 +1335,8 @@ static bool isOnlyUsedInCurrentScope(const Variable* var, const Token *tok, cons { if (tok->scope() == scope) return true; + if (tok->scope()->type == ScopeType::eSwitch) + return false; return !Token::findmatch(tok->scope()->bodyEnd, "%varid%", scope->bodyEnd, var->declarationId()); } diff --git a/test/testother.cpp b/test/testother.cpp index deb0ea7428a..cc1124963ba 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -1986,7 +1986,7 @@ class TestOther : public TestFixture { } void varScope46() { - check("void f() {\n" + check("void f() {\n" // #7091 " int y1;\n" " for (int i = 0; i < 3; ++i) {\n" " for(int j = 0; j < 3; ++j) {\n" @@ -1997,6 +1997,24 @@ class TestOther : public TestFixture { "}\n"); ASSERT_EQUALS("[test.cpp:2:9]: (style) The scope of the variable 'y1' can be reduced. [variableScope]\n", errout_str()); + + check("bool f() {\n" + "bool b = false;\n" + "do {\n" + " switch (g()) {\n" + " case 0:\n" + " b = true;\n" + " break;\n" + " case 1:\n" + " return b;\n" + " break;\n" + " default:\n" + " break;\n" + " }\n" + "}\n" + "while (true);\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } #define checkOldStylePointerCast(...) checkOldStylePointerCast_(__FILE__, __LINE__, __VA_ARGS__)