Move and refactor the CheckMemoryLeak::isclass
This commit is contained in:
parent
8513fb81d2
commit
5800692fa1
|
@ -53,6 +53,29 @@ static const CWE CWE415(415U);
|
|||
static const int NEW_ARRAY = -2;
|
||||
static const int NEW = -1;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Is variable type some class with automatic deallocation?
|
||||
* @param vartok variable token
|
||||
* @return true unless it can be seen there is no automatic deallocation
|
||||
*/
|
||||
static bool isAutoDealloc(const Variable *var)
|
||||
{
|
||||
if (var->valueType() && var->valueType()->type != ValueType::Type::RECORD && var->valueType()->type != ValueType::Type::UNKNOWN_TYPE)
|
||||
return false;
|
||||
|
||||
// return false if the type is a simple record type without side effects
|
||||
// a type that has no side effects (no constructors and no members with constructors)
|
||||
/** @todo false negative: check base class for side effects */
|
||||
/** @todo false negative: check constructors for side effects */
|
||||
if (var->typeScope() && var->typeScope()->numConstructors == 0 &&
|
||||
(var->typeScope()->varlist.empty() || var->type()->needInitialization == Type::True) &&
|
||||
var->type()->derivedFrom.empty())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void VarInfo::print()
|
||||
|
@ -222,7 +245,7 @@ static bool checkVariable(const Token *varTok, const bool isCpp)
|
|||
if (!var)
|
||||
return false;
|
||||
// Possibly automatically deallocated memory
|
||||
if (!var->typeStartToken()->isStandardType() && Token::Match(varTok, "%var% = new"))
|
||||
if (isAutoDealloc(var) && Token::Match(varTok, "%var% = new"))
|
||||
return false;
|
||||
if (!var->isPointer() && !var->typeStartToken()->isStandardType())
|
||||
return false;
|
||||
|
|
|
@ -94,26 +94,6 @@ static const std::set<std::string> call_func_white_list = {
|
|||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CheckMemoryLeak::isclass(const Token *tok, unsigned int varid) const
|
||||
{
|
||||
if (tok->isStandardType())
|
||||
return false;
|
||||
|
||||
const Variable * var = mTokenizer_->getSymbolDatabase()->getVariableFromVarId(varid);
|
||||
|
||||
// return false if the type is a simple record type without side effects
|
||||
// a type that has no side effects (no constructors and no members with constructors)
|
||||
/** @todo false negative: check base class for side effects */
|
||||
/** @todo false negative: check constructors for side effects */
|
||||
if (var && var->typeScope() && var->typeScope()->numConstructors == 0 &&
|
||||
(var->typeScope()->varlist.empty() || var->type()->needInitialization == Type::True) &&
|
||||
var->type()->derivedFrom.empty())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2, unsigned int varid, std::list<const Function*> *callstack) const
|
||||
{
|
||||
// What we may have...
|
||||
|
|
|
@ -114,14 +114,6 @@ public:
|
|||
*/
|
||||
static AllocType getReallocationType(const Token *tok2, unsigned int varid);
|
||||
|
||||
/**
|
||||
* @brief Is a typename the name of a class?
|
||||
* @param tok type token
|
||||
* @param varid variable id
|
||||
* @return true if the type name is the name of a class
|
||||
*/
|
||||
bool isclass(const Token *tok, unsigned int varid) const;
|
||||
|
||||
/**
|
||||
* Report that there is a memory leak (new/malloc/etc)
|
||||
* @param tok token where memory is leaked
|
||||
|
|
|
@ -68,6 +68,8 @@ private:
|
|||
TEST_CASE(assign18);
|
||||
TEST_CASE(assign19);
|
||||
|
||||
TEST_CASE(isAutoDealloc);
|
||||
|
||||
TEST_CASE(realloc1);
|
||||
TEST_CASE(realloc2);
|
||||
TEST_CASE(realloc3);
|
||||
|
@ -93,7 +95,6 @@ private:
|
|||
TEST_CASE(doublefree8);
|
||||
TEST_CASE(doublefree9);
|
||||
|
||||
|
||||
// exit
|
||||
TEST_CASE(exit1);
|
||||
TEST_CASE(exit2);
|
||||
|
@ -399,6 +400,23 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void isAutoDealloc() {
|
||||
check("void f() {\n"
|
||||
" char *p = new char[100];"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("[test.cpp:2]: (error) Memory leak: p\n", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" Fred *fred = new Fred;"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" std::string *str = new std::string;"
|
||||
"}", true);
|
||||
TODO_ASSERT_EQUALS("[test.cpp:2]: (error) Memory leak: str\n", "", errout.str());
|
||||
}
|
||||
|
||||
void realloc1() {
|
||||
check("void f() {\n"
|
||||
" void *p = malloc(10);\n"
|
||||
|
|
Loading…
Reference in New Issue