unused variables: fixed false negatives with the help of the symbol database. ticket: #2317

This commit is contained in:
Robert Reif 2010-12-21 08:13:40 +01:00 committed by Daniel Marjamäki
parent f73cce9eca
commit 244974a61a
4 changed files with 80 additions and 5 deletions

View File

@ -1641,10 +1641,31 @@ void CheckOther::functionVariableUsage()
else if (var && var->_type == Variables::pointer &&
Token::Match(start, "%var% = new|malloc|calloc|g_malloc|kmalloc|vmalloc"))
{
if (start->strAt(2) == "new" && !start->tokAt(3)->isStandardType())
variables.write(varid1);
else
bool allocate = true;
if (start->strAt(2) == "new")
{
// is it a user defined type?
if (!start->tokAt(3)->isStandardType())
{
// lookup the type
const SymbolDatabase::SpaceInfo *type = symbolDatabase->findVarType(info, start->tokAt(3));
// unknown type?
if (!type)
allocate = false;
// has default constructor or
// has members with unknown type or default constructor
else if (type->needInitialization == SymbolDatabase::SpaceInfo::False)
allocate = false;
}
}
if (allocate)
variables.allocateMemory(varid1);
else
variables.write(varid1);
}
else
{

View File

@ -957,6 +957,23 @@ SymbolDatabase::SpaceInfo::SpaceInfo(SymbolDatabase *check_, const Token *classD
nestedIn->nestedList.push_back(this);
}
bool
SymbolDatabase::SpaceInfo::hasDefaultConstructor() const
{
if (numConstructors)
{
std::list<Func>::const_iterator func;
for (func = functionList.begin(); func != functionList.end(); ++func)
{
if (func->type == Func::Constructor &&
func->argDef->link() == func->argDef->next())
return true;
}
}
return false;
}
// Get variable list..
void SymbolDatabase::SpaceInfo::getVarList()
{

View File

@ -232,6 +232,8 @@ public:
unsigned int getNestedNonFunctions() const;
bool isBaseClassFunc(const Token *tok);
bool hasDefaultConstructor() const;
};
bool isMemberVar(const SpaceInfo *info, const Token *tok);
@ -246,6 +248,14 @@ public:
/** @brief Information about all namespaces/classes/structrues */
std::list<SpaceInfo *> spaceInfoList;
/**
* @brief find a variable type if it's a user defined type
* @param start scope to start looking in
* @param type token containing variable type
* @return pointer to type if found or NULL if not found
*/
const SpaceInfo *findVarType(const SpaceInfo *start, const Token *type) const;
private:
void addFunction(SpaceInfo **info, const Token **tok, const Token *argStart);
void addNewFunction(SpaceInfo **info, const Token **tok);
@ -253,8 +263,6 @@ private:
bool isFunction(const Token *tok, const Token **funcStart, const Token **argStart) const;
bool argsMatch(const SpaceInfo *info, const Token *first, const Token *second, const std::string &path, unsigned int depth) const;
const SpaceInfo *findVarType(const SpaceInfo *start, const Token *type) const;
const Tokenizer *_tokenizer;
const Settings *_settings;
ErrorLogger *_errorLogger;

View File

@ -79,6 +79,7 @@ private:
TEST_CASE(localvar29); // ticket #2206 (array initialization)
TEST_CASE(localvar30);
TEST_CASE(localvar31); // ticket #2286
TEST_CASE(localvar32); // ticket #2330
TEST_CASE(localvaralias1);
TEST_CASE(localvaralias2); // ticket #1637
TEST_CASE(localvaralias3); // ticket #1639
@ -1334,6 +1335,16 @@ private:
"}\n");
ASSERT_EQUALS("", errout.str());
}
void localvar32() // ticket #2330
{
functionVariableUsage("void f() {\n"
" int x;\n"
" fstream &f = getfile();\n"
" f >> x;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void localvaralias1()
{
@ -2556,6 +2567,24 @@ private:
"}\n");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("struct Fred { int a; };\n"
"void foo()\n"
"{\n"
" Fred* fred = new Fred;\n"
" std::cout << \"test\" << std::endl;\n"
" delete fred;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'fred' is allocated memory that is never used\n", errout.str());
functionVariableUsage("struct Fred { int a; Fred() : a(0) {} };\n"
"void foo()\n"
"{\n"
" Fred* fred = new Fred;\n"
" std::cout << \"test\" << std::endl;\n"
" delete fred;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("void foo()\n"
"{\n"
" Fred* fred = malloc(sizeof(Fred));\n"