* Fix #8433 FN unused variable not detected when there is lambda * Format * Fix tests * Check lambda return * Add test * Undo, add test * simpleMatch() * Rename test
This commit is contained in:
parent
e621f721fc
commit
8eabf5c211
|
@ -720,8 +720,6 @@ void CheckMemoryLeakStructMember::check()
|
||||||
continue;
|
continue;
|
||||||
if (var->typeEndToken()->isStandardType())
|
if (var->typeEndToken()->isStandardType())
|
||||||
continue;
|
continue;
|
||||||
if (var->scope()->hasInlineOrLambdaFunction())
|
|
||||||
continue;
|
|
||||||
checkStructVariable(var);
|
checkStructVariable(var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -921,7 +919,7 @@ void CheckMemoryLeakStructMember::checkStructVariable(const Variable * const var
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returning from function..
|
// Returning from function..
|
||||||
else if (tok3->str() == "return") {
|
else if ((tok3->scope()->type != Scope::ScopeType::eLambda || tok3->scope() == variable->scope()) && tok3->str() == "return") {
|
||||||
// Returning from function without deallocating struct member?
|
// Returning from function without deallocating struct member?
|
||||||
if (!Token::Match(tok3, "return %varid% ;", structid) &&
|
if (!Token::Match(tok3, "return %varid% ;", structid) &&
|
||||||
!Token::Match(tok3, "return & %varid%", structid) &&
|
!Token::Match(tok3, "return & %varid%", structid) &&
|
||||||
|
|
|
@ -5149,6 +5149,15 @@ const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *ty
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool hasEmptyCaptureList(const Token* tok) {
|
||||||
|
if (!Token::simpleMatch(tok, "{"))
|
||||||
|
return false;
|
||||||
|
const Token* listTok = tok->astParent();
|
||||||
|
if (Token::simpleMatch(listTok, "("))
|
||||||
|
listTok = listTok->astParent();
|
||||||
|
return Token::simpleMatch(listTok, "[ ]");
|
||||||
|
}
|
||||||
|
|
||||||
bool Scope::hasInlineOrLambdaFunction() const
|
bool Scope::hasInlineOrLambdaFunction() const
|
||||||
{
|
{
|
||||||
return std::any_of(nestedList.begin(), nestedList.end(), [&](const Scope* s) {
|
return std::any_of(nestedList.begin(), nestedList.end(), [&](const Scope* s) {
|
||||||
|
@ -5156,7 +5165,7 @@ bool Scope::hasInlineOrLambdaFunction() const
|
||||||
if (s->type == Scope::eUnconditional && Token::simpleMatch(s->bodyStart->previous(), ") {"))
|
if (s->type == Scope::eUnconditional && Token::simpleMatch(s->bodyStart->previous(), ") {"))
|
||||||
return true;
|
return true;
|
||||||
// Lambda function
|
// Lambda function
|
||||||
if (s->type == Scope::eLambda)
|
if (s->type == Scope::eLambda && !hasEmptyCaptureList(s->bodyStart))
|
||||||
return true;
|
return true;
|
||||||
if (s->hasInlineOrLambdaFunction())
|
if (s->hasInlineOrLambdaFunction())
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -2131,15 +2131,13 @@ private:
|
||||||
" FILE*f=fopen(fname,a);\n"
|
" FILE*f=fopen(fname,a);\n"
|
||||||
" std::shared_ptr<FILE> fp{f, [](FILE* x) { free(f); }};\n"
|
" std::shared_ptr<FILE> fp{f, [](FILE* x) { free(f); }};\n"
|
||||||
"}", true);
|
"}", true);
|
||||||
TODO_ASSERT_EQUALS(
|
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: f\n", errout.str());
|
||||||
"[test.cpp:2] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: f\n", "", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" FILE*f=fopen(fname,a);\n"
|
" FILE*f=fopen(fname,a);\n"
|
||||||
" std::shared_ptr<FILE> fp{f, [](FILE* x) {}};\n"
|
" std::shared_ptr<FILE> fp{f, [](FILE* x) {}};\n"
|
||||||
"}", true);
|
"}", true);
|
||||||
TODO_ASSERT_EQUALS(
|
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: f\n", errout.str());
|
||||||
"[test.cpp:2] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: f\n", "", errout.str());
|
|
||||||
|
|
||||||
check("class C;\n"
|
check("class C;\n"
|
||||||
"void f() {\n"
|
"void f() {\n"
|
||||||
|
|
|
@ -1737,7 +1737,7 @@ private:
|
||||||
|
|
||||||
TEST_CASE(customAllocation);
|
TEST_CASE(customAllocation);
|
||||||
|
|
||||||
TEST_CASE(lambdaInForLoop); // #9793
|
TEST_CASE(lambdaInScope); // #9793
|
||||||
}
|
}
|
||||||
|
|
||||||
void err() {
|
void err() {
|
||||||
|
@ -2228,8 +2228,8 @@ private:
|
||||||
ASSERT_EQUALS("[test.c:7]: (error) Memory leak: abc.a\n", errout.str());
|
ASSERT_EQUALS("[test.c:7]: (error) Memory leak: abc.a\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void lambdaInForLoop() { // #9793
|
void lambdaInScope() {
|
||||||
check(
|
check( // #9793
|
||||||
"struct S { int * p{nullptr}; };\n"
|
"struct S { int * p{nullptr}; };\n"
|
||||||
"int main()\n"
|
"int main()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -2242,6 +2242,35 @@ private:
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"}", true);
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check(
|
||||||
|
"struct S { int* p; };\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" auto g = []() {\n"
|
||||||
|
" S s;\n"
|
||||||
|
" s.p = new int;\n"
|
||||||
|
" };\n"
|
||||||
|
"}\n", true);
|
||||||
|
ASSERT_EQUALS("[test.cpp:6]: (error) Memory leak: s.p\n", errout.str());
|
||||||
|
|
||||||
|
check(
|
||||||
|
"struct S { int* p; };\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" S s;\n"
|
||||||
|
" s.p = new int;\n"
|
||||||
|
" auto g = [&]() {\n"
|
||||||
|
" delete s.p;\n"
|
||||||
|
" };\n"
|
||||||
|
" g();\n"
|
||||||
|
"}\n"
|
||||||
|
"void h() {\n"
|
||||||
|
" S s;\n"
|
||||||
|
" s.p = new int;\n"
|
||||||
|
" [&]() {\n"
|
||||||
|
" delete s.p;\n"
|
||||||
|
" }();\n"
|
||||||
|
"}\n", true);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6328,6 +6328,13 @@ private:
|
||||||
" });\n"
|
" });\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("int f() {\n" // #8433
|
||||||
|
" float a;\n"
|
||||||
|
" auto lambda = []() {};\n"
|
||||||
|
" return 0;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Unused variable: a\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue