diff --git a/src/checkmemoryleak.cpp b/src/checkmemoryleak.cpp index c5726905c..03552bf09 100644 --- a/src/checkmemoryleak.cpp +++ b/src/checkmemoryleak.cpp @@ -252,7 +252,37 @@ void CheckMemoryLeak::mismatchAllocDealloc(const std::list &calls error(callstack, "error", "mismatchAllocDealloc", "Mismatching allocation and deallocation: " + varname); } +CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Token *tok) const +{ + // Locate the start of the function.. + unsigned int parlevel = 0; + while (tok) + { + if (tok->str() == "{" || tok->str() == "}") + return No; + if (tok->str() == "(") + { + if (parlevel != 0) + return No; + ++parlevel; + } + + else if (tok->str() == ")") + { + if (parlevel != 1) + return No; + if (Token::Match(tok, ") const| { return new %type% ; }")) + return New; + if (Token::Match(tok, ") const| { return new %type% [ %any% ] ; }")) + return NewArray; + break; + } + + tok = tok->next(); + } + return No; +} @@ -355,6 +385,14 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::listGetFunctionTokenByName(funcname.c_str()); + AllocType a = functionReturnType(ftok); + if (a != No) + return "alloc"; + } + // how many parameters is there in the function call? int numpar = countParameters(tok); if (numpar <= 0) diff --git a/src/checkmemoryleak.h b/src/checkmemoryleak.h index 4f8947922..fe57b9554 100644 --- a/src/checkmemoryleak.h +++ b/src/checkmemoryleak.h @@ -43,7 +43,7 @@ class Token; class CheckMemoryLeak { -protected: +public: CheckMemoryLeak() { } /** What type of allocation are used.. the "Many" means that several types of allocation and deallocation are used */ @@ -68,6 +68,9 @@ protected: // error message virtual void error(const Token *tok, const std::string &severity, const std::string &id, const std::string &msg) = 0; virtual void error(const std::list &callstack, const std::string &severity, const std::string &id, const std::string &msg) = 0; + + /** What type of allocated memory does the given function return? */ + AllocType functionReturnType(const Token *tok) const; }; diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index 57335d48a..83c7f1169 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -24,11 +24,61 @@ #include "../src/checkmemoryleak.h" #include "testsuite.h" -#include #include extern std::ostringstream errout; + +class TestMemleak : private TestFixture +{ +public: + TestMemleak() : TestFixture("TestMemleak") + { } + +private: + void run() + { + TEST_CASE(testFunctionReturnType); + } + + CheckMemoryLeak::AllocType functionReturnType(const char code[]) + { + // Tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + return ((const CheckMemoryLeak *)0)->functionReturnType(tokenizer.tokens()); + } + + void testFunctionReturnType() + { + { + const char code[] = "const char *foo()\n" + "{ return 0; }"; + ASSERT_EQUALS(CheckMemoryLeak::No, functionReturnType(code)); + } + + { + const char code[] = "Fred *newFred()\n" + "{ return new Fred; }"; + ASSERT_EQUALS(CheckMemoryLeak::New, functionReturnType(code)); + } + + { + const char code[] = "char *foo()\n" + "{ return new char[100]; }"; + ASSERT_EQUALS(CheckMemoryLeak::NewArray, functionReturnType(code)); + } + } +}; + +static TestMemleak testMemleak; + + + + + class TestMemleakInFunction : public TestFixture { public: @@ -145,6 +195,8 @@ private: TEST_CASE(func13); TEST_CASE(func14); + TEST_CASE(allocfunc1); + TEST_CASE(throw1); TEST_CASE(throw2); @@ -1366,38 +1418,20 @@ private: } - /* - void func3() - { - check( "static char *dmalloc()\n" - "{\n" - " char *p = new char[100];\n" - " return p;\n" - "}\n" - "static void f()\n" - "{\n" - " char *p = dmalloc();\n" - "}\n" ); - ASSERT_EQUALS( std::string("[test.cpp:9]: Memory leak: p\n"), errout.str() ); - } + void allocfunc1() + { + check("static char *a()\n" + "{\n" + " return new char[100];\n" + "}\n" + "static void b()\n" + "{\n" + " char *p = a();\n" + "}\n"); + ASSERT_EQUALS(std::string("[test.cpp:8]: (error) Memory leak: p\n"), errout.str()); + } - void func4() - { - check( "static char *dmalloc()\n" - "{\n" - " char *p = new char[100];\n" - " return p;\n" - "}\n" - "static void f()\n" - "{\n" - " char *p = dmalloc();\n" - " delete p;\n" - "}\n" ); - ASSERT_EQUALS( std::string("[test.cpp:9]: Mismatching allocation and deallocation: p\n"), errout.str() ); - } - */ -