diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 1a205cbd4..5982ae449 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -193,6 +193,19 @@ static bool isVarUsedInTree(const Token *tok, unsigned int varid) return isVarUsedInTree(tok->astOperand1(), varid) || isVarUsedInTree(tok->astOperand2(), varid); } +static bool isPointerReleased(const Token *startToken, const Token *endToken, unsigned int varid) +{ + for (const Token *tok = startToken; tok && tok != endToken; tok = tok->next()) { + if (tok->varId() != varid) + continue; + if(Token::Match(tok, "%var% . release ( )")) + return true; + if(Token::Match(tok, "%var% =")) + return false; + } + return false; +} + void CheckLeakAutoVar::checkScope(const Token * const startToken, VarInfo *varInfo, std::set notzero) @@ -565,6 +578,12 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken, if (!Token::Match(typeEndTok, "> %var% {|( %var% ,|)|}")) continue; + tok = typeEndTok->linkAt(2); + + unsigned varid = typeEndTok->next()->varId(); + if(isPointerReleased(typeEndTok->tokAt(2), endToken, varid)) + continue; + bool arrayDelete = false; if (Token::findsimplematch(ftok->next(), "[ ]", typeEndTok)) arrayDelete = true; diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index 081a739b7..131d22d15 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -109,6 +109,7 @@ private: TEST_CASE(mismatchAllocDealloc); TEST_CASE(smartPointerDeleter); + TEST_CASE(smartPointerRelease); // Execution reaches a 'return' TEST_CASE(return1); @@ -1253,6 +1254,22 @@ private: "}\n", true); ASSERT_EQUALS("", errout.str()); } + void smartPointerRelease() { + check("void f() {\n" + " int * i = new int;\n" + " std::unique_ptr x(i);\n" + " x.release();\n" + " delete i;\n" + "}\n", true); + ASSERT_EQUALS("", errout.str()); + + check("void f() {\n" + " int * i = new int;\n" + " std::unique_ptr x(i);\n" + " x.release();\n" + "}\n", true); + ASSERT_EQUALS("[test.cpp:5]: (error) Memory leak: i\n", errout.str()); + } void return1() { check("int f() {\n"