Fix #10083 FN unusedScopedObject: temporary lock 'std::lock_guard<std::mutex>(m)' (#4522)

* Fix #10083 FN unusedScopedObject: temporary lock 'std::lock_guard<std::mutex>(m)'

* Format

* Fix cppcheck-cfg.rng

* Format
This commit is contained in:
chrchr-github 2022-09-30 07:25:33 +02:00 committed by GitHub
parent 40b5521bf0
commit 4d13266e99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 28 additions and 16 deletions

View File

@ -551,6 +551,9 @@
<element name="suppress"> <element name="suppress">
<ref name="DATA-EXTNAME"/> <ref name="DATA-EXTNAME"/>
</element> </element>
<element name="checkFiniteLifetime">
<ref name="DATA-EXTNAME"/>
</element>
</choice> </choice>
</zeroOrMore> </zeroOrMore>
</element> </element>

View File

@ -8664,16 +8664,16 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
<smart-pointer class-name="std::weak_ptr"/> <smart-pointer class-name="std::weak_ptr"/>
<type-checks> <type-checks>
<unusedvar> <unusedvar>
<suppress>std::insert_iterator</suppress>
<suppress>std::lock_guard</suppress>
<suppress>std::unique_lock</suppress>
<suppress>std::shared_lock</suppress>
<suppress>std::fstream</suppress> <suppress>std::fstream</suppress>
<suppress>std::wfstream</suppress> <suppress>std::wfstream</suppress>
<suppress>std::ofstream</suppress> <suppress>std::ofstream</suppress>
<suppress>std::wofstream</suppress> <suppress>std::wofstream</suppress>
<suppress>std::basic_fstream</suppress> <suppress>std::basic_fstream</suppress>
<suppress>std::basic_ofstream</suppress> <suppress>std::basic_ofstream</suppress>
<checkFiniteLifetime>std::insert_iterator</checkFiniteLifetime>
<checkFiniteLifetime>std::lock_guard</checkFiniteLifetime>
<checkFiniteLifetime>std::unique_lock</checkFiniteLifetime>
<checkFiniteLifetime>std::shared_lock</checkFiniteLifetime>
<check>std::pair</check> <check>std::pair</check>
<check>std::exception</check> <check>std::exception</check>
<check>std::logic_error</check> <check>std::logic_error</check>

View File

@ -2077,7 +2077,7 @@ void CheckOther::checkMisusedScopedObject()
const Token* endTok = tok; const Token* endTok = tok;
if (Token::Match(endTok, "%name% <")) if (Token::Match(endTok, "%name% <"))
endTok = endTok->linkAt(1); endTok = endTok->linkAt(1);
if (Token::Match(endTok, "%name%|> (|{") && Token::Match(endTok->linkAt(1), ")|} ; !!}") && if (Token::Match(endTok, "%name%|> (|{") && Token::Match(endTok->linkAt(1), ")|} ;") &&
!Token::simpleMatch(endTok->next()->astParent(), ";")) { // for loop condition !Token::simpleMatch(endTok->next()->astParent(), ";")) { // for loop condition
return tok; return tok;
} }
@ -2085,7 +2085,8 @@ void CheckOther::checkMisusedScopedObject()
}; };
auto isLibraryConstructor = [&](const Token* tok, const std::string& typeStr) -> bool { auto isLibraryConstructor = [&](const Token* tok, const std::string& typeStr) -> bool {
if (mSettings->library.getTypeCheck("unusedvar", typeStr) == Library::TypeCheck::check) const Library::TypeCheck typeCheck = mSettings->library.getTypeCheck("unusedvar", typeStr);
if (typeCheck == Library::TypeCheck::check || typeCheck == Library::TypeCheck::checkFiniteLifetime)
return true; return true;
return mSettings->library.detectContainerOrIterator(tok); return mSettings->library.detectContainerOrIterator(tok);
}; };

View File

@ -1268,6 +1268,7 @@ void CheckUnusedVar::checkFunctionVariableUsage()
case Library::TypeCheck::check: case Library::TypeCheck::check:
break; break;
case Library::TypeCheck::suppress: case Library::TypeCheck::suppress:
case Library::TypeCheck::checkFiniteLifetime:
continue; continue;
} }
} }
@ -1365,6 +1366,7 @@ void CheckUnusedVar::checkFunctionVariableUsage()
case Library::TypeCheck::check: case Library::TypeCheck::check:
break; break;
case Library::TypeCheck::suppress: case Library::TypeCheck::suppress:
case Library::TypeCheck::checkFiniteLifetime:
error = false; error = false;
} }
} }

View File

@ -553,6 +553,8 @@ Library::Error Library::load(const tinyxml2::XMLDocument &doc)
mTypeChecks[std::pair<std::string,std::string>(checkName, typeName)] = TypeCheck::check; mTypeChecks[std::pair<std::string,std::string>(checkName, typeName)] = TypeCheck::check;
else if (checkTypeName == "suppress") else if (checkTypeName == "suppress")
mTypeChecks[std::pair<std::string,std::string>(checkName, typeName)] = TypeCheck::suppress; mTypeChecks[std::pair<std::string,std::string>(checkName, typeName)] = TypeCheck::suppress;
else if (checkTypeName == "checkFiniteLifetime")
mTypeChecks[std::pair<std::string,std::string>(checkName, typeName)] = TypeCheck::checkFiniteLifetime;
} }
} }
} }

View File

@ -554,7 +554,11 @@ public:
static bool isContainerYield(const Token * const cond, Library::Container::Yield y, const std::string& fallback=emptyString); static bool isContainerYield(const Token * const cond, Library::Container::Yield y, const std::string& fallback=emptyString);
/** Suppress/check a type */ /** Suppress/check a type */
enum class TypeCheck { def, check, suppress }; enum class TypeCheck { def,
check,
suppress,
checkFiniteLifetime, // (unusedvar) object has side effects, but immediate destruction is wrong
};
TypeCheck getTypeCheck(std::string check, std::string typeName) const; TypeCheck getTypeCheck(std::string check, std::string typeName) const;
private: private:

View File

@ -138,7 +138,6 @@ private:
TEST_CASE(testMisusedScopeObjectDoesNotPickPureC); TEST_CASE(testMisusedScopeObjectDoesNotPickPureC);
TEST_CASE(testMisusedScopeObjectDoesNotPickNestedClass); TEST_CASE(testMisusedScopeObjectDoesNotPickNestedClass);
TEST_CASE(testMisusedScopeObjectInConstructor); TEST_CASE(testMisusedScopeObjectInConstructor);
TEST_CASE(testMisusedScopeObjectNoCodeAfter);
TEST_CASE(testMisusedScopeObjectStandardType); TEST_CASE(testMisusedScopeObjectStandardType);
TEST_CASE(testMisusedScopeObjectNamespace); TEST_CASE(testMisusedScopeObjectNamespace);
TEST_CASE(trac2071); TEST_CASE(trac2071);
@ -5044,14 +5043,6 @@ private:
ASSERT_EQUALS("[test.cpp:4]: (style) Instance of 'Foo' object is destroyed immediately.\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (style) Instance of 'Foo' object is destroyed immediately.\n", errout.str());
} }
void testMisusedScopeObjectNoCodeAfter() {
check("class Foo {};\n"
"void f() {\n"
" Foo();\n" // No code after class => don't warn
"}", "test.cpp");
ASSERT_EQUALS("", errout.str());
}
void testMisusedScopeObjectStandardType() { void testMisusedScopeObjectStandardType() {
check("int g();\n" check("int g();\n"
"void f(int i) {\n" "void f(int i) {\n"
@ -5111,6 +5102,15 @@ private:
"[test.cpp:3]: (style) Instance of 'std::string' object is destroyed immediately.\n" "[test.cpp:3]: (style) Instance of 'std::string' object is destroyed immediately.\n"
"[test.cpp:4]: (style) Instance of 'std::pair' object is destroyed immediately.\n", "[test.cpp:4]: (style) Instance of 'std::pair' object is destroyed immediately.\n",
errout.str()); errout.str());
check("struct S {\n" // #10083
" void f() {\n"
" std::lock_guard<std::mutex>(m);\n"
" }\n"
" std::mutex m;\n"
"}\n", "test.cpp");
ASSERT_EQUALS("[test.cpp:3]: (style) Instance of 'std::lock_guard' object is destroyed immediately.\n",
errout.str());
} }
void trac2084() { void trac2084() {