diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index ebeb7f44f..15bf0ac70 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -2430,19 +2430,28 @@ void CheckStl::localMutexError(const Token* tok) void CheckStl::checkMutexes() { for (const Scope *function : mTokenizer->getSymbolDatabase()->functionScopes) { + std::set checkedVars; for (const Token *tok = function->bodyStart; tok != function->bodyEnd; tok = tok->next()) { + if (!Token::Match(tok, "%var%")) + continue; const Variable* var = tok->variable(); if (!var) continue; if (Token::Match(tok, "%var% . lock ( )")) { if (!isMutex(var)) continue; + if (!checkedVars.insert(var->declarationId()).second) + continue; if (isLocalMutex(var, tok->scope())) localMutexError(tok); } else if (Token::Match(tok, "%var% (|{ %var% )|}|,")) { if (!isLockGuard(var)) continue; const Variable* mvar = tok->tokAt(2)->variable(); + if (!mvar) + continue; + if (!checkedVars.insert(mvar->declarationId()).second) + continue; if (var->isStatic() || var->isGlobal()) globalLockGuardError(tok); else if (isLocalMutex(mvar, tok->scope())) diff --git a/test/teststl.cpp b/test/teststl.cpp index 240e20709..931fdc73f 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -4554,6 +4554,36 @@ private: "}\n", true); ASSERT_EQUALS("[test.cpp:5]: (warning) The lock is ineffective because the mutex is locked at the same scope as the mutex itself.\n", errout.str()); + + check("void foo();\n" + "void bar();\n" + "void f() {\n" + " std::mutex m;\n" + " std::thread t([&m](){\n" + " m.lock();\n" + " foo();\n" + " m.unlock();\n" + " });\n" + " m.lock();\n" + " bar();\n" + " m.unlock();\n" + "}\n", + true); + ASSERT_EQUALS("", errout.str()); + + check("void foo();\n" + "void bar();\n" + "void f() {\n" + " std::mutex m;\n" + " std::thread t([&m](){\n" + " std::unique_lock g{m};\n" + " foo();\n" + " });\n" + " std::unique_lock g{m};\n" + " bar();\n" + "}\n", + true); + ASSERT_EQUALS("", errout.str()); } };