Fixed #5659 (False negative: mismatching allocation / deallocation whith using namespace)
This commit is contained in:
parent
c8ae1e4751
commit
4ae204e46b
|
@ -198,7 +198,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
Scope::UsingInfo using_info;
|
Scope::UsingInfo using_info;
|
||||||
|
|
||||||
using_info.start = tok; // save location
|
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);
|
scope->usingList.push_back(using_info);
|
||||||
|
|
||||||
|
@ -669,6 +669,8 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
// fill in using info
|
// fill in using info
|
||||||
for (std::list<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
|
for (std::list<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
|
||||||
for (std::list<Scope::UsingInfo>::iterator i = it->usingList.begin(); i != it->usingList.end(); ++i) {
|
for (std::list<Scope::UsingInfo>::iterator i = it->usingList.begin(); i != it->usingList.end(); ++i) {
|
||||||
|
// only find if not already found
|
||||||
|
if (i->scope == nullptr) {
|
||||||
// check scope for match
|
// check scope for match
|
||||||
scope = findScope(i->start->tokAt(2), &(*it));
|
scope = findScope(i->start->tokAt(2), &(*it));
|
||||||
if (scope) {
|
if (scope) {
|
||||||
|
@ -678,6 +680,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// fill in variable info
|
// fill in variable info
|
||||||
for (std::list<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
|
for (std::list<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
|
||||||
|
@ -1314,6 +1317,31 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To
|
||||||
Scope *scope1 = &(*it1);
|
Scope *scope1 = &(*it1);
|
||||||
|
|
||||||
bool match = false;
|
bool match = false;
|
||||||
|
|
||||||
|
// check in namespace if using found
|
||||||
|
if (*scope == scope1 && !scope1->usingList.empty()) {
|
||||||
|
std::list<Scope::UsingInfo>::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)) {
|
if (scope1->className == tok1->str() && (scope1->type != Scope::eFunction)) {
|
||||||
// do the scopes match (same scope) or do their names match (multiple namespaces)
|
// do the scopes match (same scope) or do their names match (multiple namespaces)
|
||||||
if ((*scope == scope1->nestedIn) || (*scope &&
|
if ((*scope == scope1->nestedIn) || (*scope &&
|
||||||
|
@ -2794,6 +2822,7 @@ const Type* SymbolDatabase::findType(const Token *startTok, const Scope *startSc
|
||||||
// not a valid path
|
// not a valid path
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
const Type* SymbolDatabase::findTypeInNested(const Token *startTok, const Scope *startScope) const
|
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
|
// not a valid path
|
||||||
return 0;
|
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 *>(function);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -828,6 +828,9 @@ private:
|
||||||
void addNewFunction(Scope **info, const Token **tok);
|
void addNewFunction(Scope **info, const Token **tok);
|
||||||
static bool isFunction(const Token *tok, const Scope* outerScope, const Token **funcStart, const Token **argStart);
|
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 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 Tokenizer *_tokenizer;
|
||||||
const Settings *_settings;
|
const Settings *_settings;
|
||||||
|
|
|
@ -4108,8 +4108,7 @@ private:
|
||||||
"}\n"
|
"}\n"
|
||||||
"using namespace N;\n"
|
"using namespace N;\n"
|
||||||
"int Base::getResourceName() { return var; }");
|
"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",
|
ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:6]: (style, inconclusive) Technically the member function 'N::Base::getResourceName' can be const.\n", errout.str());
|
||||||
"", errout.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void const36() { // ticket #2003
|
void const36() { // ticket #2003
|
||||||
|
|
|
@ -4348,6 +4348,7 @@ private:
|
||||||
TEST_CASE(free_member_in_sub_func);
|
TEST_CASE(free_member_in_sub_func);
|
||||||
|
|
||||||
TEST_CASE(mismatch1);
|
TEST_CASE(mismatch1);
|
||||||
|
TEST_CASE(mismatch2); // #5659
|
||||||
|
|
||||||
// allocating member variable in public function
|
// allocating member variable in public function
|
||||||
TEST_CASE(func1);
|
TEST_CASE(func1);
|
||||||
|
@ -5418,6 +5419,31 @@ private:
|
||||||
ASSERT_EQUALS("[test.cpp:14]: (error) Mismatching allocation and deallocation: A::pkt_buffer\n", errout.str());
|
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() {
|
void func1() {
|
||||||
check("class Fred\n"
|
check("class Fred\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
|
Loading…
Reference in New Issue