unused variables: fixed false negatives with the help of the symbol database. ticket: #2317
This commit is contained in:
parent
f73cce9eca
commit
244974a61a
|
@ -1641,10 +1641,31 @@ void CheckOther::functionVariableUsage()
|
||||||
else if (var && var->_type == Variables::pointer &&
|
else if (var && var->_type == Variables::pointer &&
|
||||||
Token::Match(start, "%var% = new|malloc|calloc|g_malloc|kmalloc|vmalloc"))
|
Token::Match(start, "%var% = new|malloc|calloc|g_malloc|kmalloc|vmalloc"))
|
||||||
{
|
{
|
||||||
if (start->strAt(2) == "new" && !start->tokAt(3)->isStandardType())
|
bool allocate = true;
|
||||||
variables.write(varid1);
|
|
||||||
else
|
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);
|
variables.allocateMemory(varid1);
|
||||||
|
else
|
||||||
|
variables.write(varid1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -957,6 +957,23 @@ SymbolDatabase::SpaceInfo::SpaceInfo(SymbolDatabase *check_, const Token *classD
|
||||||
nestedIn->nestedList.push_back(this);
|
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..
|
// Get variable list..
|
||||||
void SymbolDatabase::SpaceInfo::getVarList()
|
void SymbolDatabase::SpaceInfo::getVarList()
|
||||||
{
|
{
|
||||||
|
|
|
@ -232,6 +232,8 @@ public:
|
||||||
unsigned int getNestedNonFunctions() const;
|
unsigned int getNestedNonFunctions() const;
|
||||||
|
|
||||||
bool isBaseClassFunc(const Token *tok);
|
bool isBaseClassFunc(const Token *tok);
|
||||||
|
|
||||||
|
bool hasDefaultConstructor() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool isMemberVar(const SpaceInfo *info, const Token *tok);
|
bool isMemberVar(const SpaceInfo *info, const Token *tok);
|
||||||
|
@ -246,6 +248,14 @@ public:
|
||||||
/** @brief Information about all namespaces/classes/structrues */
|
/** @brief Information about all namespaces/classes/structrues */
|
||||||
std::list<SpaceInfo *> spaceInfoList;
|
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:
|
private:
|
||||||
void addFunction(SpaceInfo **info, const Token **tok, const Token *argStart);
|
void addFunction(SpaceInfo **info, const Token **tok, const Token *argStart);
|
||||||
void addNewFunction(SpaceInfo **info, const Token **tok);
|
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 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;
|
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 Tokenizer *_tokenizer;
|
||||||
const Settings *_settings;
|
const Settings *_settings;
|
||||||
ErrorLogger *_errorLogger;
|
ErrorLogger *_errorLogger;
|
||||||
|
|
|
@ -79,6 +79,7 @@ private:
|
||||||
TEST_CASE(localvar29); // ticket #2206 (array initialization)
|
TEST_CASE(localvar29); // ticket #2206 (array initialization)
|
||||||
TEST_CASE(localvar30);
|
TEST_CASE(localvar30);
|
||||||
TEST_CASE(localvar31); // ticket #2286
|
TEST_CASE(localvar31); // ticket #2286
|
||||||
|
TEST_CASE(localvar32); // ticket #2330
|
||||||
TEST_CASE(localvaralias1);
|
TEST_CASE(localvaralias1);
|
||||||
TEST_CASE(localvaralias2); // ticket #1637
|
TEST_CASE(localvaralias2); // ticket #1637
|
||||||
TEST_CASE(localvaralias3); // ticket #1639
|
TEST_CASE(localvaralias3); // ticket #1639
|
||||||
|
@ -1335,6 +1336,16 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
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()
|
void localvaralias1()
|
||||||
{
|
{
|
||||||
functionVariableUsage("void foo()\n"
|
functionVariableUsage("void foo()\n"
|
||||||
|
@ -2556,6 +2567,24 @@ private:
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
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"
|
functionVariableUsage("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" Fred* fred = malloc(sizeof(Fred));\n"
|
" Fred* fred = malloc(sizeof(Fred));\n"
|
||||||
|
|
Loading…
Reference in New Issue