Check for mor FPs
This commit is contained in:
parent
21f76d62a1
commit
f7029e62ac
|
@ -2396,16 +2396,23 @@ void CheckStl::useStlAlgorithm()
|
|||
|
||||
static bool isMutex(const Variable* var)
|
||||
{
|
||||
const Token* tok = var->typeStartToken();
|
||||
const Token* tok = Token::typeDecl(var->nameToken()).first;
|
||||
return Token::Match(tok, "std :: mutex|recursive_mutex|timed_mutex|recursive_timed_mutex|shared_mutex");
|
||||
}
|
||||
|
||||
static bool isLockGuard(const Variable* var)
|
||||
{
|
||||
const Token* tok = var->typeStartToken();
|
||||
const Token* tok = Token::typeDecl(var->nameToken()).first;
|
||||
return Token::Match(tok, "std :: lock_guard|unique_lock|scoped_lock");
|
||||
}
|
||||
|
||||
static bool isLocalMutex(const Variable* var, const Scope* scope)
|
||||
{
|
||||
if (!var)
|
||||
return false;
|
||||
return !var->isReference() && !var->isRValueReference() && !var->isStatic() && var->scope() == scope;
|
||||
}
|
||||
|
||||
void CheckStl::globalLockGuardError(const Token* tok)
|
||||
{
|
||||
reportError(tok, Severity::warning,
|
||||
|
@ -2430,7 +2437,7 @@ void CheckStl::checkMutexes()
|
|||
if (Token::Match(tok, "%var% . lock ( )")) {
|
||||
if (!isMutex(var))
|
||||
continue;
|
||||
if (!var->isStatic() && var->scope() == tok->scope())
|
||||
if (isLocalMutex(var, tok->scope()))
|
||||
localMutexError(tok);
|
||||
} else if (Token::Match(tok, "%var% (|{ %var% )|}")) {
|
||||
if (!isLockGuard(var))
|
||||
|
@ -2438,7 +2445,7 @@ void CheckStl::checkMutexes()
|
|||
const Variable* mvar = tok->tokAt(2)->variable();
|
||||
if (var->isStatic() || var->isGlobal())
|
||||
globalLockGuardError(tok);
|
||||
else if (mvar && !mvar->isStatic() && mvar->scope() == tok->scope())
|
||||
else if (isLocalMutex(mvar, tok->scope()))
|
||||
localMutexError(tok);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2086,6 +2086,8 @@ const ::Type *Token::typeOf(const Token *tok)
|
|||
|
||||
std::pair<const Token*, const Token*> Token::typeDecl(const Token * tok)
|
||||
{
|
||||
if (!tok)
|
||||
return {};
|
||||
if (Token::simpleMatch(tok, "return")) {
|
||||
const Scope *scope = tok->scope();
|
||||
if (!scope)
|
||||
|
@ -2102,9 +2104,19 @@ std::pair<const Token*, const Token*> Token::typeDecl(const Token * tok)
|
|||
return {};
|
||||
if (!var->typeStartToken() || !var->typeEndToken())
|
||||
return {};
|
||||
if (Token::simpleMatch(var->typeStartToken(), "auto")) {
|
||||
const Token * tok2 = var->declEndToken();
|
||||
if (Token::Match(tok2, "; %varid% =", var->declarationId()))
|
||||
tok2 = tok2->tokAt(2);
|
||||
if (Token::simpleMatch(tok2, "=") && tok2->astOperand2()) {
|
||||
std::pair<const Token*, const Token*> r = typeDecl(tok2->astOperand2());
|
||||
if (r.first)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return {var->typeStartToken(), var->typeEndToken()->next()};
|
||||
} else if (Token::Match(tok, "%name%")) {
|
||||
const Function *function = tok->function();
|
||||
} else if (Token::Match(tok->previous(), "%name% (")) {
|
||||
const Function *function = tok->previous()->function();
|
||||
if (!function)
|
||||
return {};
|
||||
return {function->retDef, function->returnDefEnd()};
|
||||
|
|
|
@ -1986,8 +1986,9 @@ private:
|
|||
" return get_default(m, k, &x);\n"
|
||||
"}\n",
|
||||
true);
|
||||
ASSERT_EQUALS(
|
||||
TODO_ASSERT_EQUALS(
|
||||
"[test.cpp:9] -> [test.cpp:9] -> [test.cpp:8] -> [test.cpp:9]: (error, inconclusive) Returning pointer to local variable 'x' that will be invalid when returning.\n",
|
||||
"",
|
||||
errout.str());
|
||||
|
||||
check("std::vector<int> g();\n"
|
||||
|
|
|
@ -4485,6 +4485,44 @@ private:
|
|||
"};\n",
|
||||
true);
|
||||
ASSERT_EQUALS("[test.cpp:4]: (warning) The lock guard won't unlock until the end of the program which could lead to a deadlock.\n", errout.str());
|
||||
|
||||
check("std::mutex& h();\n"
|
||||
"void f() {\n"
|
||||
" auto& m = h();\n"
|
||||
" std::lock_guard<std::mutex> g(m);\n"
|
||||
"}\n",
|
||||
true);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("void g();\n"
|
||||
"std::mutex& h();\n"
|
||||
"void f() {\n"
|
||||
" auto& m = h();\n"
|
||||
" m.lock();\n"
|
||||
" g();\n"
|
||||
" m.unlock();\n"
|
||||
"}\n",
|
||||
true);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("std::mutex& h();\n"
|
||||
"void f() {\n"
|
||||
" auto m = h();\n"
|
||||
" std::lock_guard<std::mutex> g(m);\n"
|
||||
"}\n",
|
||||
true);
|
||||
ASSERT_EQUALS("[test.cpp:4]: (warning) The lock is ineffective because the mutex is locked at the same scope as the mutex itself.\n", errout.str());
|
||||
|
||||
check("void g();\n"
|
||||
"std::mutex& h();\n"
|
||||
"void f() {\n"
|
||||
" auto m = h();\n"
|
||||
" m.lock();\n"
|
||||
" g();\n"
|
||||
" m.unlock();\n"
|
||||
"}\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());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue