From 2452a2c01dff4b821d15264fdc73df21fdf9b867 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 1 Jun 2022 21:15:41 +0200 Subject: [PATCH] Fix #11099 FP: variableScope when using range constructor to vector (#4161) * Fix #11099 FP: variableScope when using range constructor to vector * Format --- lib/checkother.cpp | 26 +++++++++++++-- test/testother.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 2 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index a4e638a74..12f83b70e 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -945,10 +945,32 @@ void CheckOther::checkVariableScope() if (forHead) continue; + auto isSimpleExpr = [](const Token* tok) { + return tok && (tok->isNumber() || tok->tokType() == Token::eString || tok->tokType() == Token::eChar || tok->isBoolean()); + }; + const Token* tok = var->nameToken()->next(); - if (Token::Match(tok, "; %varid% = %any% ;", var->declarationId())) { + if (Token::Match(tok, "; %varid% = %any% ;", var->declarationId())) { // bail for assignment tok = tok->tokAt(3); - if (!tok->isNumber() && tok->tokType() != Token::eString && tok->tokType() != Token::eChar && !tok->isBoolean()) + if (!isSimpleExpr(tok)) + continue; + } + else if (Token::Match(tok, "{|(")) { // bail for constructor + const Token* argTok = tok->astOperand2(); + bool bail = false; + do { + if (Token::simpleMatch(argTok, ",")) { + if (!isSimpleExpr(argTok->astOperand2())) { + bail = true; + break; + } + } else if (!isSimpleExpr(argTok)) { + bail = true; + break; + } + argTok = argTok->astOperand1(); + } while (argTok); + if (bail) continue; } // bailout if initialized with function call that has possible side effects diff --git a/test/testother.cpp b/test/testother.cpp index 537e28eaf..81dfb05ff 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -98,6 +98,7 @@ private: TEST_CASE(varScope28); // #10527 TEST_CASE(varScope29); // #10888 TEST_CASE(varScope30); // #8541 + TEST_CASE(varScope31); // #11099 TEST_CASE(oldStylePointerCast); TEST_CASE(invalidPointerCast); @@ -1380,6 +1381,86 @@ private: ASSERT_EQUALS("", errout.str()); } + void varScope31() { // #11099 + check("bool g(std::vector&);\n" + "void h(std::vector);\n" + "void f0(std::vector v) {\n" + " std::vector w{ v };" + " bool b = g(v);\n" + " if (b)\n" + " h(w);\n" + " h(v);\n" + "}\n" + "void f1(std::vector v) {\n" + " std::vector w{ v.begin(), v.end() };" + " bool b = g(v);\n" + " if (b)\n" + " h(w);\n" + " h(v);\n" + "}\n" + "void f2(std::vector v) {\n" + " std::vector w{ 10, 0, std::allocator() };" // FN + " bool b = g(v);\n" + " if (b)\n" + " h(w);\n" + " h(v);\n" + "}\n" + "void f3(std::vector v) {\n" + " std::vector w{ 10, 0 };" // warn + " bool b = g(v);\n" + " if (b)\n" + " h(w);\n" + " h(v);\n" + "}\n" + "void f4(std::vector v) {\n" + " std::vector w{ 10 };" // warn + " bool b = g(v);\n" + " if (b)\n" + " h(w);\n" + " h(v);\n" + "}\n" + "void f5(std::vector v) {\n" + " std::vector w(v);" + " bool b = g(v);\n" + " if (b)\n" + " h(w);\n" + " h(v);\n" + "}\n" + "void f6(std::vector v) {\n" + " std::vector w(v.begin(), v.end());" + " bool b = g(v);\n" + " if (b)\n" + " h(w);\n" + " h(v);\n" + "}\n" + "void f7(std::vector v) {\n" + " std::vector w(10, 0, std::allocator);" // FN + " bool b = g(v);\n" + " if (b)\n" + " h(w);\n" + " h(v);\n" + "}\n" + "void f8(std::vector v) {\n" + " std::vector w(10, 0);" // warn + " bool b = g(v);\n" + " if (b)\n" + " h(w);\n" + " h(v);\n" + "}\n" + "void f9(std::vector v) {\n" + " std::vector w(10);" // warn + " bool b = g(v);\n" + " if (b)\n" + " h(w);\n" + " h(v);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:22]: (style) The scope of the variable 'w' can be reduced.\n" + "[test.cpp:28]: (style) The scope of the variable 'w' can be reduced.\n" + "[test.cpp:52]: (style) The scope of the variable 'w' can be reduced.\n" + "[test.cpp:58]: (style) The scope of the variable 'w' can be reduced.\n", + errout.str()); + } + #define checkOldStylePointerCast(code) checkOldStylePointerCast_(code, __FILE__, __LINE__) void checkOldStylePointerCast_(const char code[], const char* file, int line) { // Clear the error buffer..