Finally fixed ticket #284 (style check: redundant condition improvement)

http://sourceforge.net/apps/trac/cppcheck/ticket/284
This commit is contained in:
Slava Semushin 2009-07-18 21:42:08 +07:00
parent d04eeb4fd4
commit d3490abd64
2 changed files with 114 additions and 45 deletions

View File

@ -73,65 +73,120 @@ void CheckOther::warningRedundantCode()
// if (p) delete p // if (p) delete p
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{ {
if (tok->str() != "if") if (! Token::simpleMatch(tok, "if ("))
continue; continue;
const char *varname1 = NULL; const char *varname = NULL;
const Token *tok2 = NULL; const Token *tok2 = tok->tokAt(2);
if (Token::Match(tok, "if ( %var% )")) /*
{ * Possible if-constructions:
varname1 = tok->strAt(2); *
tok2 = tok->tokAt(4); * if (0 != var)
} * if (0 != this->var)
else if (Token::Match(tok, "if ( %var% != 0 )")) * if (0 != Foo::var)
{ * if (var)
varname1 = tok->strAt(2); * if (this->var)
tok2 = tok->tokAt(6); * if (Foo::var)
* if (var != 0)
* if (this->var != 0)
* if (Foo::var != 0)
*
**/
if (Token::simpleMatch(tok2, "0 !=")) {
tok2 = tok2->tokAt(2);
} }
if (varname1 == NULL || tok2 == NULL) if (Token::simpleMatch(tok2, "this .") ||
Token::Match(tok2, "%var% ::")) {
tok2 = tok2->tokAt(2);
}
if (Token::Match(tok2, "%var%")) {
varname = tok2->strAt(0);
tok2 = tok2->next();
}
if (Token::simpleMatch(tok2, "!= 0")) {
tok2 = tok2->tokAt(2);
}
if (tok2->str() == ")") {
tok2 = tok2->next();
} else {
varname = NULL;
}
if (varname == NULL)
continue; continue;
bool err = false; bool ifHasBracket = false;
if (tok2->str() == "{") if (tok2->str() == "{")
{ {
tok2 = tok2->next(); tok2 = tok2->next();
ifHasBracket = true;
}
if (Token::Match(tok2, "delete %var% ; }")) bool err = false;
{ bool funcHasBracket = false;
err = (strcmp(tok2->strAt(1), varname1) == 0);
} /*
else if (Token::Match(tok2, "delete [ ] %var% ; }")) * Possible constructions:
{ *
err = (strcmp(tok2->strAt(3), varname1) == 0); * - delete %var%
} * - delete [] %var%
else if (Token::Match(tok2, "free ( %var% ) ; }")) * - free ( %var )
{ * - kfree ( %var% )
err = (strcmp(tok2->strAt(2), varname1) == 0); *
} * Where %var% may be:
else if (Token::Match(tok2, "kfree ( %var% ) ; }")) * - just variable name (var)
{ * - class member (this->var)
err = (strcmp(tok2->strAt(2), varname1) == 0); * - static member (Class::var)
*
**/
if (Token::Match(tok2, "free|kfree (")) {
tok2 = tok2->tokAt(2);
funcHasBracket = true;
} else if (tok2->str() == "delete") {
tok2 = tok2->next();
if (Token::simpleMatch(tok2, "[ ]")) {
tok2 = tok2->tokAt(2);
} }
} }
else
{ if (Token::simpleMatch(tok2, "this .") ||
if (Token::Match(tok2, "delete %var% ;")) Token::Match(tok2, "%var% ::")) {
{ tok2 = tok2->tokAt(2);
err = (strcmp(tok2->strAt(1), varname1) == 0);
} }
else if (Token::Match(tok2, "delete [ ] %var% ;"))
{ if (Token::Match(tok2, "%var%") && (strcmp(tok2->strAt(0), varname) == 0)) {
err = (strcmp(tok2->strAt(3), varname1) == 0); tok2 = tok2->next();
err = true;
} }
else if (Token::Match(tok2, "free ( %var% ) ;"))
{ if (funcHasBracket) {
err = (strcmp(tok2->strAt(2), varname1) == 0); if (tok2->str() != ")") {
err = false;
} else {
tok2 = tok2->next();
} }
else if (Token::Match(tok2, "kfree ( %var% ) ;")) }
{
err = (strcmp(tok2->strAt(2), varname1) == 0); if (tok2->str() != ";") {
err = false;
} else {
tok2 = tok2->next();
}
if (ifHasBracket) {
if (tok2->str() != "}") {
err = false;
} }
} }

View File

@ -163,6 +163,20 @@ private:
" delete [] p;\n" " delete [] p;\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:3]: (style) Redundant condition. It is safe to deallocate a NULL pointer\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (style) Redundant condition. It is safe to deallocate a NULL pointer\n", errout.str());
check("void foo()\n"
"{\n"
" if (0 != this->p)\n"
" delete this->p;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (style) Redundant condition. It is safe to deallocate a NULL pointer\n", errout.str());
check("void Foo::deleteInstance()\n"
"{\n"
" if (Foo::instance != NULL)\n"
" delete Foo::instance;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (style) Redundant condition. It is safe to deallocate a NULL pointer\n", errout.str());
} }
void unreachable1() void unreachable1()