diff --git a/cfg/cppcheck-cfg.rng b/cfg/cppcheck-cfg.rng
index 1f7b37de2..df57b95af 100644
--- a/cfg/cppcheck-cfg.rng
+++ b/cfg/cppcheck-cfg.rng
@@ -551,6 +551,9 @@
+
+
+
diff --git a/cfg/std.cfg b/cfg/std.cfg
index 2dc34f5fe..86dede187 100644
--- a/cfg/std.cfg
+++ b/cfg/std.cfg
@@ -8664,16 +8664,16 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
- std::insert_iterator
- std::lock_guard
- std::unique_lock
- std::shared_lock
std::fstream
std::wfstream
std::ofstream
std::wofstream
std::basic_fstream
std::basic_ofstream
+ std::insert_iterator
+ std::lock_guard
+ std::unique_lock
+ std::shared_lock
std::pair
std::exception
std::logic_error
diff --git a/lib/checkother.cpp b/lib/checkother.cpp
index 43cc9a06e..ac09970f5 100644
--- a/lib/checkother.cpp
+++ b/lib/checkother.cpp
@@ -2077,7 +2077,7 @@ void CheckOther::checkMisusedScopedObject()
const Token* endTok = tok;
if (Token::Match(endTok, "%name% <"))
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
return tok;
}
@@ -2085,7 +2085,8 @@ void CheckOther::checkMisusedScopedObject()
};
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 mSettings->library.detectContainerOrIterator(tok);
};
diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp
index 6c8562d6f..7340dd5c3 100644
--- a/lib/checkunusedvar.cpp
+++ b/lib/checkunusedvar.cpp
@@ -1268,6 +1268,7 @@ void CheckUnusedVar::checkFunctionVariableUsage()
case Library::TypeCheck::check:
break;
case Library::TypeCheck::suppress:
+ case Library::TypeCheck::checkFiniteLifetime:
continue;
}
}
@@ -1365,6 +1366,7 @@ void CheckUnusedVar::checkFunctionVariableUsage()
case Library::TypeCheck::check:
break;
case Library::TypeCheck::suppress:
+ case Library::TypeCheck::checkFiniteLifetime:
error = false;
}
}
diff --git a/lib/library.cpp b/lib/library.cpp
index 1ab7e34f9..35b6618be 100644
--- a/lib/library.cpp
+++ b/lib/library.cpp
@@ -553,6 +553,8 @@ Library::Error Library::load(const tinyxml2::XMLDocument &doc)
mTypeChecks[std::pair(checkName, typeName)] = TypeCheck::check;
else if (checkTypeName == "suppress")
mTypeChecks[std::pair(checkName, typeName)] = TypeCheck::suppress;
+ else if (checkTypeName == "checkFiniteLifetime")
+ mTypeChecks[std::pair(checkName, typeName)] = TypeCheck::checkFiniteLifetime;
}
}
}
diff --git a/lib/library.h b/lib/library.h
index 1e9ad3325..333c1d453 100644
--- a/lib/library.h
+++ b/lib/library.h
@@ -554,7 +554,11 @@ public:
static bool isContainerYield(const Token * const cond, Library::Container::Yield y, const std::string& fallback=emptyString);
/** 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;
private:
diff --git a/test/testother.cpp b/test/testother.cpp
index 98f6b6b9f..68922a7e0 100644
--- a/test/testother.cpp
+++ b/test/testother.cpp
@@ -138,7 +138,6 @@ private:
TEST_CASE(testMisusedScopeObjectDoesNotPickPureC);
TEST_CASE(testMisusedScopeObjectDoesNotPickNestedClass);
TEST_CASE(testMisusedScopeObjectInConstructor);
- TEST_CASE(testMisusedScopeObjectNoCodeAfter);
TEST_CASE(testMisusedScopeObjectStandardType);
TEST_CASE(testMisusedScopeObjectNamespace);
TEST_CASE(trac2071);
@@ -5044,14 +5043,6 @@ private:
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() {
check("int g();\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:4]: (style) Instance of 'std::pair' object is destroyed immediately.\n",
errout.str());
+
+ check("struct S {\n" // #10083
+ " void f() {\n"
+ " std::lock_guard(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() {