diff --git a/checkmemoryleak.cpp b/checkmemoryleak.cpp index 4edf33688..d3cee674e 100644 --- a/checkmemoryleak.cpp +++ b/checkmemoryleak.cpp @@ -566,8 +566,8 @@ TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, std::list } // throw.. - if ( tok->str() == "throw" ) - addtoken("throw"); + if ( TOKEN::Match(tok, "try|throw|catch") ) + addtoken(tok->strAt(0)); // Assignment.. if ( TOKEN::Match(tok,"[)=] %var1% [+;)]", varnames) || @@ -616,6 +616,25 @@ void CheckMemoryLeakClass::erase(TOKEN *begin, const TOKEN *end) void CheckMemoryLeakClass::simplifycode(TOKEN *tok) { + // Replace "throw" that is not in a try block with "return" + int indentlevel = 0; + int trylevel = -1; + for (TOKEN *tok2 = tok; tok2; tok2 = tok2->next()) + { + if ( tok2->str() == "{" ) + ++indentlevel; + else if ( tok2->str() == "}" ) + { + --indentlevel; + if ( indentlevel <= trylevel ) + trylevel = -1; + } + else if ( trylevel == -1 && tok2->str() == "try" ) + trylevel = indentlevel; + else if ( trylevel == -1 && tok2->str() == "throw" ) + tok2->setstr("return"); + } + // reduce the code.. bool done = false; while ( ! done ) @@ -779,6 +798,12 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok) done = false; } + // Remove "catch ;" + if ( TOKEN::simpleMatch(tok2->next(), "catch ;") ) + { + erase(tok2, tok2->tokAt(3)); + done = false; + } // Reduce "if* ;" that is not followed by an else.. if (TOKEN::Match(tok2->next(), "if(var)|if(!var)|if(true)|if(false)|ifv ; !!else") ) @@ -1032,12 +1057,6 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok) } } } - - if ( TOKEN::Match(tok2, "throw") ) - { - tok2->setstr( "return" ); - done = false; - } } } } diff --git a/testmemleak.cpp b/testmemleak.cpp index 25f226244..314fed7be 100644 --- a/testmemleak.cpp +++ b/testmemleak.cpp @@ -131,6 +131,7 @@ private: // TODO TEST_CASE( class3 ); TEST_CASE( throw1 ); + TEST_CASE( throw2 ); TEST_CASE( linux_list_1 ); @@ -1138,6 +1139,27 @@ private: ASSERT_EQUALS( std::string("[test.cpp:5]: Memory leak: str\n"), errout.str() ); } + void throw2() + { + check( "void foo()\n" + "{\n" + " char *str = 0;\n" + " try\n" + " {\n" + " str = new char[100];\n" + " if ( somecondition )\n" + " throw exception;\n" + " delete [] str;\n" + " }\n" + " catch ( ... )\n" + " {\n" + " delete [] str;\n" + " }\n" + "}\n" ); + + ASSERT_EQUALS( std::string(""), errout.str() ); + } +