From 758fc85a12fa586ba59493da890805bc5871d9a9 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Sat, 4 Dec 2010 07:29:12 +0100 Subject: [PATCH] Memory leaks: Determine that some classes are not auto-deallocated. Reduce false negatives. Ticket: #2219 and #1618 --- lib/checkmemoryleak.cpp | 13 +++++++++++-- lib/symboldatabase.cpp | 6 +++++- test/testmemleak.cpp | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 4ee8c7ba2..d3107ad74 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -2616,9 +2616,18 @@ void CheckMemoryLeakInClass::check() variable(info, var->token); } - else + + // known class? + else if (var->type) { - /** @todo false negative: check classes here someday */ + // not derived and no constructor? + if (var->type->derivedFrom.empty() && var->type->numConstructors == 0) + { + if (var->access == SymbolDatabase::Private) + checkPublicFunctions(info, var->token); + + variable(info, var->token); + } } } } diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 97cbf6a15..f18f1b6fe 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1087,21 +1087,25 @@ void SymbolDatabase::SpaceInfo::getVarList() else if (Token::Match(tok, "%type% * %var% ;")) { vartok = tok->tokAt(2); + typetok = tok; tok = vartok->next(); } else if (Token::Match(tok, "%type% %type% * %var% ;")) { vartok = tok->tokAt(3); + typetok = vartok->tokAt(-2); tok = vartok->next(); } else if (Token::Match(tok, "%type% :: %type% * %var% ;")) { vartok = tok->tokAt(4); + typetok = vartok->tokAt(-2); tok = vartok->next(); } else if (Token::Match(tok, "%type% :: %type% :: %type% * %var% ;")) { vartok = tok->tokAt(6); + typetok = vartok->tokAt(-2); tok = vartok->next(); } @@ -1221,7 +1225,7 @@ void SymbolDatabase::SpaceInfo::getVarList() const SpaceInfo *spaceInfo = NULL; - if (isClass) + if (typetok) spaceInfo = check->findVarType(this, typetok); addVar(vartok, varaccess, isMutable, isStatic, isConst, isClass, spaceInfo); diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index 736baecb0..46016970a 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -3579,6 +3579,45 @@ private: " rp2 = new TRadioButton(this);\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + check("class TRadioButton { };\n" + "class Foo\n" + "{\n" + "private:\n" + " TRadioButton* rp1;\n" + " TRadioButton* rp2;\n" + "public:\n" + " Foo();\n" + "};\n" + "Foo::Foo()\n" + "{\n" + " rp1 = new TRadioButton;\n" + " rp2 = new TRadioButton;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:5]: (error) Memory leak: Foo::rp1\n" + "[test.cpp:6]: (error) Memory leak: Foo::rp2\n", errout.str()); + + check("class TRadioButton { };\n" + "class Foo\n" + "{\n" + "private:\n" + " TRadioButton* rp1;\n" + " TRadioButton* rp2;\n" + "public:\n" + " Foo();\n" + " ~Foo();\n" + "};\n" + "Foo::Foo()\n" + "{\n" + " rp1 = new TRadioButton;\n" + " rp2 = new TRadioButton;\n" + "}\n" + "Foo::~Foo()\n" + "{\n" + " delete rp1;\n" + " delete rp2;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void staticvar()