diff --git a/CheckOther.cpp b/CheckOther.cpp index 6ea1b4393..fb9b8abcc 100644 --- a/CheckOther.cpp +++ b/CheckOther.cpp @@ -832,6 +832,21 @@ void CheckOther::unreachableCode() // Usage of function variables //--------------------------------------------------------------------------- +static bool isOp(const TOKEN *tok) +{ + return bool(tok && + (tok->str() == "&&" || + tok->str() == "||" || + tok->str() == "==" || + tok->str() == "!=" || + tok->str() == "<" || + tok->str() == "<=" || + tok->str() == ">" || + tok->str() == ">=" || + tok->str() == "<<" || + TOKEN::Match(tok, "[+-*/&|,]"))); +} + void CheckOther::functionVariableUsage() { // Parse all executing scopes.. @@ -856,18 +871,29 @@ void CheckOther::functionVariableUsage() break; } - if ( TOKEN::Match(tok, "[;{}] %type% %var% ;|=") ) - { - if ( TOKEN::Match(tok->next, "delete|return") ) - varUsage[ tok->strAt(2) ] |= USAGE_READ; - else - varUsage[ tok->strAt(2) ] = USAGE_DECLARE; - } + if ( TOKEN::Match(tok, "[;{}] bool|char|short|int|long|float|double %var% ;|=") ) + varUsage[ tok->strAt(2) ] = USAGE_DECLARE; - else if ( TOKEN::Match(tok, "[;{}] %var% =") ) - { + else if ( TOKEN::Match(tok, "[;{}] bool|char|short|int|long|float|double * %var% ;|=") ) + varUsage[ tok->strAt(3) ] = USAGE_DECLARE; + + else if ( TOKEN::Match(tok, "delete|return %var%") ) + varUsage[ tok->strAt(1) ] |= USAGE_READ; + + else if ( TOKEN::Match(tok, "%var% =") ) + varUsage[ tok->str() ] |= USAGE_WRITE; + + else if ( TOKEN::Match(tok, "else %var% =") ) varUsage[ tok->strAt(1) ] |= USAGE_WRITE; - } + + else if ( TOKEN::Match(tok, ">>|& %var%") ) + varUsage[ tok->strAt(1) ] |= USAGE_WRITE; + + else if ((TOKEN::Match(tok,"[(=&]") || isOp(tok)) && TOKEN::Match(tok->next, "%var%")) + varUsage[ tok->strAt(1) ] |= USAGE_READ; + + else if (TOKEN::Match(tok, "%var%") && (tok->next->str()==")" || isOp(tok->next))) + varUsage[ tok->str() ] |= USAGE_READ; } // Check usage of all variables in the current scope.. diff --git a/cppcheck.cpp b/cppcheck.cpp index 92d6fed71..273b64ecd 100644 --- a/cppcheck.cpp +++ b/cppcheck.cpp @@ -325,6 +325,9 @@ void CppCheck::checkFile(const std::string &code, const char FileName[]) // Unreachable code below a 'return' statement checkOther.unreachableCode(); + + // Usage of local functions + checkOther.functionVariableUsage(); } } //--------------------------------------------------------------------------- diff --git a/testunusedvar.cpp b/testunusedvar.cpp index faab6f077..d07a9b4dd 100644 --- a/testunusedvar.cpp +++ b/testunusedvar.cpp @@ -59,6 +59,8 @@ private: TEST_CASE( localvar1 ); TEST_CASE( localvar2 ); + TEST_CASE( localvar3 ); + TEST_CASE( localvar4 ); } void structmember1() @@ -152,6 +154,28 @@ private: ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is not assigned a value\n"), errout.str() ); } + void localvar3() + { + functionVariableUsage( "void foo()\n" + "{\n" + " int i;\n" + " if ( abc )\n" + " ;\n" + " else i = 0;\n" + "}\n" ); + ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is assigned a value that is never used\n"), errout.str() ); + } + + void localvar4() + { + functionVariableUsage( "void foo()\n" + "{\n" + " int i = 0;\n" + " f(i); + "}\n" ); + ASSERT_EQUALS( std::string(""), errout.str() ); + } + };