diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index c59fcb35e..f8a7ddda4 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -583,6 +583,11 @@ void CheckClass::privateFunctions() if (Token::findmatch(_tokenizer->tokens(), "; __property ;")) return; + // skip checking if there are friends + // Todo: check if each class has friends + if (Token::findmatch(_tokenizer->tokens(), "friend")) + return; + // #2407 calls from operator() is not detected // TODO: Don't bailout. Detect the call. if (Token::findmatch(_tokenizer->tokens(), "operator ( )")) diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 72e58f20c..dcb203360 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -3101,7 +3101,8 @@ void CheckMemoryLeakStructMember::check() else if (tok3->str() == "return") { // Returning from function without deallocating struct member? - if (!Token::Match(tok3, "return %varid% ;", structid)) + if (!Token::Match(tok3, "return %varid% ;", structid) && + !Token::Match(tok3, "return & %varid% .", structid)) { memoryLeak(tok3, (vartok->str() + "." + tok2->strAt(2)).c_str(), Malloc); } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 8fdc5bc5e..bab1685a7 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2651,35 +2651,6 @@ static void removeTemplates(Token *tok) void Tokenizer::simplifyTemplates() { - // Don't simplify C files - { - if (_files.empty()) - return; - - std::string::size_type pos = _files[0].rfind("."); - if (pos == std::string::npos) - return; - - const std::string ext(_files[0].substr(pos)); - if (ext == ".c" || ext == ".C") - return; - } - - // Remove "typename" unless used in template arguments.. - for (Token *tok = _tokens; tok; tok = tok->next()) - { - if (tok->str() == "typename") - tok->deleteThis(); - - if (Token::simpleMatch(tok, "template <")) - { - while (tok && tok->str() != ">") - tok = tok->next(); - if (!tok) - break; - } - } - std::set expandedtemplates; // Locate specialized templates.. @@ -2775,6 +2746,22 @@ void Tokenizer::simplifyTemplates() return; } + // There are templates.. + // Remove "typename" unless used in template arguments.. + for (Token *tok = _tokens; tok; tok = tok->next()) + { + if (tok->str() == "typename") + tok->deleteThis(); + + if (Token::simpleMatch(tok, "template <")) + { + while (tok && tok->str() != ">") + tok = tok->next(); + if (!tok) + break; + } + } + // Locate possible instantiations of templates.. std::list used; for (Token *tok = _tokens; tok; tok = tok->next()) diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index 36978ff79..4cebd567f 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -4206,7 +4206,8 @@ private: TEST_CASE(goto_); // Don't report errors if the struct is returned - TEST_CASE(ret); + TEST_CASE(ret1); + TEST_CASE(ret2); // assignments TEST_CASE(assign); @@ -4284,7 +4285,7 @@ private: ASSERT_EQUALS("", errout.str()); } - void ret() + void ret1() { check("static ABC * foo()\n" "{\n" @@ -4301,6 +4302,17 @@ private: ASSERT_EQUALS("", errout.str()); } + void ret2() + { + check("static ABC * foo()\n" + "{\n" + " struct ABC *abc = malloc(sizeof(struct ABC));\n" + " abc->a = malloc(10);\n" + " return &abc->self;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + } + void assign() { check("static void foo()\n" diff --git a/test/testunusedprivfunc.cpp b/test/testunusedprivfunc.cpp index d5e6c3c8c..ff6f84c60 100644 --- a/test/testunusedprivfunc.cpp +++ b/test/testunusedprivfunc.cpp @@ -53,6 +53,8 @@ private: TEST_CASE(derivedClass); // skip warning for derived classes. It might be a virtual function. + TEST_CASE(friendClass); + TEST_CASE(borland); // skip FP when using __property // No false positives when there are "unused" templates that are removed in the simplified token list @@ -387,6 +389,17 @@ private: ASSERT_EQUALS("", errout.str()); } + void friendClass() + { + // ticket #2459 - friend class + check("class Foo {\n" + "private:\n" + " friend Bar;\n" + " void f() { }\n" + "};"); + ASSERT_EQUALS("", errout.str()); + } + void borland() { // ticket #2034 - Borland C++ __property