Fixed #3989 (false positive: memory leak (inline function))
This commit is contained in:
parent
8b088a472f
commit
38741868b5
|
@ -140,6 +140,9 @@ void CheckLeakAutoVar::check()
|
||||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
for (std::size_t i = 0; i < functions; ++i) {
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
|
if (scope->hasInlineFunction())
|
||||||
|
continue;
|
||||||
|
|
||||||
// Empty variable info
|
// Empty variable info
|
||||||
VarInfo varInfo;
|
VarInfo varInfo;
|
||||||
|
|
||||||
|
|
|
@ -2177,8 +2177,8 @@ void CheckMemoryLeakInFunction::check()
|
||||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
for (std::size_t i = 0; i < functions; ++i) {
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
|
if (!scope->hasInlineFunction())
|
||||||
checkScope(scope->classStart->next(), "", 0, scope->functionOf != nullptr, 1);
|
checkScope(scope->classStart->next(), "", 0, scope->functionOf != nullptr, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check variables..
|
// Check variables..
|
||||||
|
@ -2197,6 +2197,9 @@ void CheckMemoryLeakInFunction::check()
|
||||||
if (var->isPointer() && var->type() && !var->typeScope())
|
if (var->isPointer() && var->type() && !var->typeScope())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (var->scope()->hasInlineFunction())
|
||||||
|
continue;
|
||||||
|
|
||||||
unsigned int sz = _tokenizer->sizeOfType(var->typeStartToken());
|
unsigned int sz = _tokenizer->sizeOfType(var->typeStartToken());
|
||||||
if (sz < 1)
|
if (sz < 1)
|
||||||
sz = 1;
|
sz = 1;
|
||||||
|
|
|
@ -3493,7 +3493,16 @@ const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *ty
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
bool Scope::hasInlineFunction() const
|
||||||
|
{
|
||||||
|
for (std::list<Scope*>::const_iterator it = nestedList.begin(); it != nestedList.end(); ++it) {
|
||||||
|
const Scope *s = *it;
|
||||||
|
// Inline function
|
||||||
|
if (s->type == Scope::eUnconditional && Token::Match(s->classStart->previous(), ") {"))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void Scope::findFunctionInBase(const std::string & name, size_t args, std::vector<const Function *> & matches) const
|
void Scope::findFunctionInBase(const std::string & name, size_t args, std::vector<const Function *> & matches) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -898,6 +898,9 @@ public:
|
||||||
type == eTry || type == eCatch);
|
type == eTry || type == eCatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is there lambda/inline function(s) in this scope?
|
||||||
|
bool hasInlineFunction() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief find a function
|
* @brief find a function
|
||||||
* @param tok token of function call
|
* @param tok token of function call
|
||||||
|
|
|
@ -121,6 +121,8 @@ private:
|
||||||
|
|
||||||
TEST_CASE(nestedAllocation);
|
TEST_CASE(nestedAllocation);
|
||||||
TEST_CASE(testKeywords); // #6767
|
TEST_CASE(testKeywords); // #6767
|
||||||
|
|
||||||
|
TEST_CASE(inlineFunction); // #3989
|
||||||
}
|
}
|
||||||
|
|
||||||
void check(const char code[], bool cpp = false) {
|
void check(const char code[], bool cpp = false) {
|
||||||
|
@ -1223,6 +1225,19 @@ private:
|
||||||
"}", false);
|
"}", false);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void inlineFunction() {
|
||||||
|
check("int test() {\n"
|
||||||
|
" char *c;\n"
|
||||||
|
" int ret() {\n"
|
||||||
|
" free(c);\n"
|
||||||
|
" return 0;\n"
|
||||||
|
" }\n"
|
||||||
|
" c = malloc(128);\n"
|
||||||
|
" return ret();\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST(TestLeakAutoVar)
|
REGISTER_TEST(TestLeakAutoVar)
|
||||||
|
|
|
@ -250,6 +250,8 @@ private:
|
||||||
TEST_CASE(allocfunc13); // Ticket #4494 and #4540 - class function
|
TEST_CASE(allocfunc13); // Ticket #4494 and #4540 - class function
|
||||||
TEST_CASE(allocfunc14); // Use pointer before returning it
|
TEST_CASE(allocfunc14); // Use pointer before returning it
|
||||||
|
|
||||||
|
TEST_CASE(inlineFunction); // #3989 - inline function
|
||||||
|
|
||||||
TEST_CASE(throw1);
|
TEST_CASE(throw1);
|
||||||
TEST_CASE(throw2);
|
TEST_CASE(throw2);
|
||||||
|
|
||||||
|
@ -2679,6 +2681,19 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void inlineFunction() { // #3989 - inline function
|
||||||
|
check("int test() {\n"
|
||||||
|
" char *c;\n"
|
||||||
|
" int ret() {\n"
|
||||||
|
" free(c);\n"
|
||||||
|
" return 0;\n"
|
||||||
|
" }\n"
|
||||||
|
" c = malloc(128);\n"
|
||||||
|
" return ret();\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void throw1() {
|
void throw1() {
|
||||||
check("void foo()\n"
|
check("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
|
Loading…
Reference in New Issue