From 4ae204e46bed12795b655ed7105a0613cbf45dbd Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Thu, 10 Apr 2014 16:11:11 +0200 Subject: [PATCH] Fixed #5659 (False negative: mismatching allocation / deallocation whith using namespace) --- lib/symboldatabase.cpp | 74 ++++++++++++++++++++++++++++++++++++++---- lib/symboldatabase.h | 3 ++ test/testclass.cpp | 3 +- test/testmemleak.cpp | 26 +++++++++++++++ 4 files changed, 97 insertions(+), 9 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 3fcc2cf99..c621ab476 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -198,7 +198,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti Scope::UsingInfo using_info; using_info.start = tok; // save location - using_info.scope = 0; // fill in later + using_info.scope = findNamespace(tok->tokAt(2), scope); scope->usingList.push_back(using_info); @@ -669,12 +669,15 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti // fill in using info for (std::list::iterator it = scopeList.begin(); it != scopeList.end(); ++it) { for (std::list::iterator i = it->usingList.begin(); i != it->usingList.end(); ++i) { - // check scope for match - scope = findScope(i->start->tokAt(2), &(*it)); - if (scope) { - // set found scope - i->scope = scope; - break; + // only find if not already found + if (i->scope == nullptr) { + // check scope for match + scope = findScope(i->start->tokAt(2), &(*it)); + if (scope) { + // set found scope + i->scope = scope; + break; + } } } } @@ -1314,6 +1317,31 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To Scope *scope1 = &(*it1); bool match = false; + + // check in namespace if using found + if (*scope == scope1 && !scope1->usingList.empty()) { + std::list::const_iterator it2; + for (it2 = scope1->usingList.begin(); it2 != scope1->usingList.end(); ++it2) { + if (it2->scope) { + Function * func = findFunctionInScope(tok1, it2->scope); + if (func) { + if (!func->hasBody) { + func->hasBody = true; + func->token = *tok; + func->arg = argStart; + addNewFunction(scope, tok); + if (*scope) { + (*scope)->functionOf = func->nestedIn; + (*scope)->function = &*func; + (*scope)->function->functionScope = *scope; + } + return; + } + } + } + } + } + if (scope1->className == tok1->str() && (scope1->type != Scope::eFunction)) { // do the scopes match (same scope) or do their names match (multiple namespaces) if ((*scope == scope1->nestedIn) || (*scope && @@ -2794,6 +2822,7 @@ const Type* SymbolDatabase::findType(const Token *startTok, const Scope *startSc // not a valid path return 0; } + //--------------------------------------------------------------------------- const Type* SymbolDatabase::findTypeInNested(const Token *startTok, const Scope *startScope) const @@ -2846,3 +2875,34 @@ const Type* SymbolDatabase::findTypeInNested(const Token *startTok, const Scope // not a valid path return 0; } + +//--------------------------------------------------------------------------- + +const Scope * SymbolDatabase::findNamespace(const Token * tok, const Scope * scope) const +{ + const Scope * s = findScope(tok, scope); + + if (s) + return s; + else if (scope->nestedIn) + return findNamespace(tok, scope->nestedIn); + + return 0; +} + +//--------------------------------------------------------------------------- + +Function * SymbolDatabase::findFunctionInScope(const Token *func, const Scope *ns) +{ + const Function * function = ns->findFunction(func); + + if (!function) { + const Scope * scope = ns->findRecordInNestedList(func->str()); + if (scope && func->strAt(1) == "::") { + function = findFunctionInScope(func->tokAt(2), scope); + } + } + + return const_cast(function); +} + diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 9ff2acf98..37ebd6f90 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -828,6 +828,9 @@ private: void addNewFunction(Scope **info, const Token **tok); static bool isFunction(const Token *tok, const Scope* outerScope, const Token **funcStart, const Token **argStart); const Type *findTypeInNested(const Token *tok, const Scope *startScope) const; + const Scope *findNamespace(const Token * tok, const Scope * scope) const; + Function *findFunctionInScope(const Token *func, const Scope *ns); + const Tokenizer *_tokenizer; const Settings *_settings; diff --git a/test/testclass.cpp b/test/testclass.cpp index ef8287224..b356f9b4d 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -4108,8 +4108,7 @@ private: "}\n" "using namespace N;\n" "int Base::getResourceName() { return var; }"); - TODO_ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:6]: (style, inconclusive) Technically the member function 'N::Base::getResourceName' can be const.\n", - "", errout.str()); + ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:6]: (style, inconclusive) Technically the member function 'N::Base::getResourceName' can be const.\n", errout.str()); } void const36() { // ticket #2003 diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index c0b55a7b1..379af287f 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -4348,6 +4348,7 @@ private: TEST_CASE(free_member_in_sub_func); TEST_CASE(mismatch1); + TEST_CASE(mismatch2); // #5659 // allocating member variable in public function TEST_CASE(func1); @@ -5418,6 +5419,31 @@ private: ASSERT_EQUALS("[test.cpp:14]: (error) Mismatching allocation and deallocation: A::pkt_buffer\n", errout.str()); } + void mismatch2() { // #5659 + check("namespace NS\n" + "{\n" + "class Foo\n" + "{\n" + "public:\n" + " void fct();\n" + "\n" + "private:\n" + " char* data_;\n" + "};\n" + "}\n" + "\n" + "using namespace NS;\n" + "\n" + "void Foo::fct()\n" + "{\n" + " data_ = new char[42];\n" + " delete data_;\n" + " data_ = 0;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:16]: (warning) Possible leak in public function. The pointer 'data_' is not deallocated before it is allocated.\n" + "[test.cpp:18]: (error) Mismatching allocation and deallocation: Foo::data_\n", errout.str()); + } + void func1() { check("class Fred\n" "{\n"