diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 7bf69fb2f..e9483fb2b 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -485,6 +485,7 @@ void CheckOther::checkRedundantAssignment() if (!scope.isExecutable()) continue; + std::map> usedByLambda; // map key: lambda function varId. set of varIds used by lambda. std::map varAssignments; std::map memAssignments; std::map > membervars; @@ -510,6 +511,17 @@ void CheckOther::checkRedundantAssignment() } else if (Token::Match(tok, "break|return|continue|throw|goto|asm")) { varAssignments.clear(); memAssignments.clear(); + } else if (Token::Match(tok, "%var% = [ & ] (")) { + const unsigned int lambdaId = tok->varId(); + const Token *lambdaParams = tok->tokAt(5); + if (Token::simpleMatch(lambdaParams->link(), ") {")) { + const Token *lambdaBodyStart = lambdaParams->link()->next(); + const Token * const lambdaBodyEnd = lambdaBodyStart->link(); + for (const Token *tok2 = lambdaBodyStart; tok2 != lambdaBodyEnd; tok2 = tok2->next()) { + if (tok2->varId()) + usedByLambda[lambdaId].insert(tok2->varId()); + } + } } else if (tok->tokType() == Token::eVariable && !Token::Match(tok, "%name% (")) { const Token *eq = nullptr; for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) { @@ -640,9 +652,19 @@ void CheckOther::checkRedundantAssignment() } } else if (Token::Match(tok, "%name% (") && !mSettings->library.isFunctionConst(tok->str(), true)) { // Function call. Global variables might be used. Reset their status const bool memfunc = Token::Match(tok, "memcpy|memmove|memset|strcpy|strncpy|sprintf|snprintf|strcat|strncat|wcscpy|wcsncpy|swprintf|wcscat|wcsncat"); - if (tok->varId()) // operator() or function pointer + if (tok->varId()) { + // operator(), function pointer varAssignments.erase(tok->varId()); + // lambda.. + std::map>::const_iterator lambda = usedByLambda.find(tok->varId()); + if (lambda != usedByLambda.end()) { + for (unsigned int varId : lambda->second) { + varAssignments.erase(varId); + } + } + } + if (memfunc && tok->strAt(-1) != "(" && tok->strAt(-1) != "=") { const Token* param1 = tok->tokAt(2); writtenArgumentsEnd = param1->next(); diff --git a/test/testother.cpp b/test/testother.cpp index 0bed145ce..748f8f256 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -160,6 +160,7 @@ private: TEST_CASE(redundantVarAssignment); TEST_CASE(redundantVarAssignment_7133); TEST_CASE(redundantVarAssignment_stackoverflow); + TEST_CASE(redundantVarAssignment_lambda); TEST_CASE(redundantMemWrite); TEST_CASE(varFuncNullUB); @@ -5976,6 +5977,20 @@ private: ASSERT_EQUALS("", errout.str()); } + void redundantVarAssignment_lambda() { + // #7152 + check("int foo() {\n" + " int x = 0, y = 0;\n" + " auto f = [&]() { if (x < 5) ++y; };\n" + " x = 2;\n" + " f();\n" + " x = 6;\n" + " f();\n" + " return y;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + } + void redundantMemWrite() { // Simple tests check("void f() {\n"