Improve support of using a lambda as a deleter (#1246)
* Improve support of using a lambda as a deleter * Use simple match
This commit is contained in:
parent
42ed5a6b98
commit
406aa6cf1c
|
@ -600,16 +600,35 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
|||
endDeleterToken = typeEndTok->linkAt(2);
|
||||
}
|
||||
if (deleterToken) {
|
||||
// Skip the decaying plus in expressions like +[](T*){}
|
||||
if (deleterToken->str() == "+") {
|
||||
deleterToken = deleterToken->next();
|
||||
}
|
||||
// Check if its a pointer to a function
|
||||
const Token * dtok = Token::findmatch(deleterToken, "& %name%", endDeleterToken);
|
||||
if (dtok) {
|
||||
af = _settings->library.dealloc(dtok->tokAt(1));
|
||||
} else {
|
||||
const Token * tscopeStart = nullptr;
|
||||
const Token * tscopeEnd = nullptr;
|
||||
// If the deleter is a lambda, check if it calls the dealloc function
|
||||
if (deleterToken->str() == "[" &&
|
||||
Token::simpleMatch(deleterToken->link(), "] (") &&
|
||||
// TODO: Check for mutable keyword
|
||||
Token::simpleMatch(deleterToken->link()->linkAt(1), ") {")) {
|
||||
tscopeStart = deleterToken->link()->linkAt(1)->tokAt(1);
|
||||
tscopeEnd = tscopeStart->link();
|
||||
// If the deleter is a class, check if class calls the dealloc function
|
||||
dtok = Token::findmatch(deleterToken, "%type%", endDeleterToken);
|
||||
if (dtok && dtok->type()) {
|
||||
const Scope * tscope = dtok->type()->classScope;
|
||||
for (const Token *tok2 = tscope->bodyStart; tok2 != tscope->bodyEnd; tok2 = tok2->next()) {
|
||||
} else if ((dtok = Token::findmatch(deleterToken, "%type%", endDeleterToken)) && dtok->type()) {
|
||||
const Scope * tscope = dtok->type()->classScope;
|
||||
if(tscope) {
|
||||
tscopeStart = tscope->bodyStart;
|
||||
tscopeEnd = tscope->bodyEnd;
|
||||
}
|
||||
}
|
||||
|
||||
if(tscopeStart && tscopeEnd) {
|
||||
for (const Token *tok2 = tscopeStart; tok2 != tscopeEnd; tok2 = tok2->next()) {
|
||||
af = _settings->library.dealloc(tok2);
|
||||
if (af)
|
||||
break;
|
||||
|
|
|
@ -1255,6 +1255,44 @@ private:
|
|||
" std::unique_ptr<int, decltype(&destroy)> xp(x, &destroy());\n"
|
||||
"}\n", true);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" FILE*f=fopen(fname,a);\n"
|
||||
" std::shared_ptr<FILE> fp{f, [](FILE* x) { fclose(x); }};\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" FILE*f=fopen(fname,a);\n"
|
||||
" std::shared_ptr<FILE> fp{f, +[](FILE* x) { fclose(x); }};\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" FILE*f=fopen(fname,a);\n"
|
||||
" std::shared_ptr<FILE> fp{f, [](FILE* x) { free(f); }};\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Mismatching allocation and deallocation: f\n", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" FILE*f=fopen(fname,a);\n"
|
||||
" std::shared_ptr<FILE> fp{f, [](FILE* x) {}};\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Mismatching allocation and deallocation: f\n", errout.str());
|
||||
|
||||
check("class C;\n"
|
||||
"void f() {\n"
|
||||
" C* c = new C{};\n"
|
||||
" std::shared_ptr<C> a{c, [](C*) {}};\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("class C;\n"
|
||||
"void f() {\n"
|
||||
" C* c = new C{};\n"
|
||||
" std::shared_ptr<C> a{c, [](C* x) { delete x; }};\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
void smartPointerRelease() {
|
||||
check("void f() {\n"
|
||||
|
|
Loading…
Reference in New Issue