add support for detecting unused function variables of type class or struct

This commit is contained in:
Robert Reif 2011-06-30 21:58:11 -04:00
parent 6d4799e0b8
commit 7826b5e22d
3 changed files with 121 additions and 1 deletions

View File

@ -1671,6 +1671,21 @@ static bool nextIsStandardTypeOrVoid(const Token *tok)
return tok->isStandardType() || tok->str() == "void";
}
bool CheckOther::isRecordTypeWithoutSideEffects(const Token *tok)
{
const Variable * var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok->varId());
// 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->type() && var->type()->numConstructors == 0 &&
(var->type()->varlist.empty() || var->type()->needInitialization == Scope::True) &&
var->type()->derivedFrom.empty())
return true;
return false;
}
void CheckOther::functionVariableUsage()
{
if (!_settings->_checkCodingStyle)
@ -1738,7 +1753,7 @@ void CheckOther::functionVariableUsage()
// standard type declaration with possible initialization
// int i; int j = 0; static int k;
if (Token::Match(tok, "[;{}] static| %type% %var% ;|=") &&
nextIsStandardType(tok))
(nextIsStandardType(tok) || isRecordTypeWithoutSideEffects(tok->strAt(1) == "static" ? tok->tokAt(3) : tok->tokAt(2))))
{
tok = tok->next();

View File

@ -224,6 +224,9 @@ public:
/** @brief %Check for suspicious code that compares string literals for equality */
void checkAlwaysTrueOrFalseStringCompare();
/** @brief check if token is a record type without side effects */
bool isRecordTypeWithoutSideEffects(const Token *tok);
// Error messages..
void cstyleCastError(const Token *tok);
void dangerousUsageStrtolError(const Token *tok);

View File

@ -104,6 +104,7 @@ private:
TEST_CASE(localvarStruct2);
TEST_CASE(localvarStruct3);
TEST_CASE(localvarStruct4); // Ticket #31: sigsegv on incomplete struct
TEST_CASE(localvarStruct5);
TEST_CASE(localvarOp); // Usage with arithmetic operators
TEST_CASE(localvarInvert); // Usage with inverted variable
@ -2348,6 +2349,107 @@ private:
" struct { \n");
}
void localvarStruct5()
{
functionVariableUsage("int foo() {\n"
" A a;\n"
" return a.i;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("int foo() {\n"
" A a;\n"
" return 0;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("struct A { int i; };\n"
"int foo() {\n"
" A a;\n"
" return a.i;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("class A { int i; };\n"
"int foo() {\n"
" A a;\n"
" return a.i;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("struct A { int i; };\n"
"int foo() {\n"
" A a;\n"
" a.i = 0;\n"
" return 0;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("class A { int i; };\n"
"int foo() {\n"
" A a;\n"
" a.i = 0;\n"
" return 0;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("struct A { int i; };\n"
"int foo() {\n"
" A a = { 0 };\n"
" return 0;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'a' is assigned a value that is never used\n", errout.str());
functionVariableUsage("class A { int i; };\n"
"int foo() {\n"
" A a = { 0 };\n"
" return 0;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'a' is assigned a value that is never used\n", errout.str());
functionVariableUsage("class A { int i; public: A(); { } };\n"
"int foo() {\n"
" A a;\n"
" return 0;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("struct A { int i; };\n"
"int foo() {\n"
" A a;\n"
" return 0;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: a\n", errout.str());
functionVariableUsage("class A { int i; };\n"
"int foo() {\n"
" A a;\n"
" return 0;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: a\n", errout.str());
functionVariableUsage("class A { int i; public: A(); { } };\n"
"int foo() {\n"
" A a;\n"
" return 0;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("class A { unknown i; };\n"
"int foo() {\n"
" A a;\n"
" return 0;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("class A : public Fred { int i; };\n"
"int foo() {\n"
" A a;\n"
" return 0;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void localvarOp()
{
const char op[] = "+-*/%&|^";