diff --git a/src/checkmemoryleak.cpp b/src/checkmemoryleak.cpp index 03552bf09..7682322ad 100644 --- a/src/checkmemoryleak.cpp +++ b/src/checkmemoryleak.cpp @@ -51,7 +51,7 @@ bool CheckMemoryLeak::isclass(const Tokenizer *_tokenizer, const Token *tok) con } //--------------------------------------------------------------------------- -CheckMemoryLeak::AllocType CheckMemoryLeak::GetAllocationType(const Token *tok2) +CheckMemoryLeak::AllocType CheckMemoryLeak::GetAllocationType(const Token *tok2) const { // What we may have... // * var = (char *)malloc(10); @@ -272,15 +272,57 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Token *tok) { 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(); } + + // Is this the start of a function? + if (!Token::Match(tok, ") const| {")) + return No; + + while (tok->str() != "{") + tok = tok->next(); + tok = tok ? tok->next() : 0; + + // Inspect the statements.. + std::string varname; + AllocType allocType = No; + while (tok) + { + // variable declaration.. + if (Token::Match(tok, "%type% * %var% ;")) + { + tok = tok->tokAt(4); + continue; + } + + if (varname.empty() && Token::Match(tok,"%var% = ")) + { + varname = tok->str(); + allocType = GetAllocationType(tok->tokAt(2)); + if (allocType == No) + return No; + while (tok && tok->str() != ";") + tok = tok->next(); + tok = tok ? tok->next() : 0; + continue; + } + + if (tok->str() == "return") + { + if (varname.size() && Token::Match(tok->next(), (varname + " ;").c_str())) + return allocType; + if (Token::Match(tok, "return new %type% ;")) + return New; + if (Token::Match(tok, "return new %type% [ %any% ] ;")) + return NewArray; + } + + return No; + } + return No; } diff --git a/src/checkmemoryleak.h b/src/checkmemoryleak.h index fe57b9554..49e3be39c 100644 --- a/src/checkmemoryleak.h +++ b/src/checkmemoryleak.h @@ -52,7 +52,7 @@ public: void MemoryLeak(const Token *tok, const char varname[], AllocType alloctype, bool all); void MismatchError(const Token *Tok1, const std::list &callstack, const char varname[]); AllocType GetDeallocationType(const Token *tok, const char *varnames[]); - AllocType GetAllocationType(const Token *tok2); + AllocType GetAllocationType(const Token *tok2) const; AllocType GetReallocationType(const Token *tok2); bool isclass(const Tokenizer *_tokenizer, const Token *typestr) const; diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index 83c7f1169..7ec0ca077 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -70,6 +70,15 @@ private: "{ return new char[100]; }"; ASSERT_EQUALS(CheckMemoryLeak::NewArray, functionReturnType(code)); } + + { + const char code[] = "char *foo()\n" + "{\n" + " char *p = new char[100];\n" + " return p;\n" + "}"; + ASSERT_EQUALS(CheckMemoryLeak::NewArray, functionReturnType(code)); + } } }; @@ -1436,7 +1445,6 @@ private: - void throw1() { check("void foo()\n"