Redundant conditions: some refactorings
* removed the 'redundant null pointer' check. sometimes it's unsafe to delete NULL pointer. and this check doesn't point out errors anyway. * moved the 'redundant condition' check for set::remove. Moved it to CheckStl.
This commit is contained in:
parent
a56f6d276a
commit
f843678a07
4
Makefile
4
Makefile
|
@ -54,7 +54,6 @@ TESTOBJ = test/testautovariables.o \
|
||||||
test/testobsoletefunctions.o \
|
test/testobsoletefunctions.o \
|
||||||
test/testother.o \
|
test/testother.o \
|
||||||
test/testpreprocessor.o \
|
test/testpreprocessor.o \
|
||||||
test/testredundantif.o \
|
|
||||||
test/testrunner.o \
|
test/testrunner.o \
|
||||||
test/testsettings.o \
|
test/testsettings.o \
|
||||||
test/testsimplifytokens.o \
|
test/testsimplifytokens.o \
|
||||||
|
@ -227,9 +226,6 @@ test/testother.o: test/testother.cpp lib/tokenize.h lib/classinfo.h lib/token.h
|
||||||
test/testpreprocessor.o: test/testpreprocessor.cpp test/testsuite.h lib/errorlogger.h lib/preprocessor.h lib/tokenize.h lib/classinfo.h lib/token.h lib/settings.h
|
test/testpreprocessor.o: test/testpreprocessor.cpp test/testsuite.h lib/errorlogger.h lib/preprocessor.h lib/tokenize.h lib/classinfo.h lib/token.h lib/settings.h
|
||||||
$(CXX) $(CXXFLAGS) -Ilib -Icli -c -o test/testpreprocessor.o test/testpreprocessor.cpp
|
$(CXX) $(CXXFLAGS) -Ilib -Icli -c -o test/testpreprocessor.o test/testpreprocessor.cpp
|
||||||
|
|
||||||
test/testredundantif.o: test/testredundantif.cpp lib/tokenize.h lib/classinfo.h lib/token.h lib/checkother.h lib/check.h lib/settings.h lib/errorlogger.h test/testsuite.h
|
|
||||||
$(CXX) $(CXXFLAGS) -Ilib -Icli -c -o test/testredundantif.o test/testredundantif.cpp
|
|
||||||
|
|
||||||
test/testrunner.o: test/testrunner.cpp test/testsuite.h lib/errorlogger.h
|
test/testrunner.o: test/testrunner.cpp test/testsuite.h lib/errorlogger.h
|
||||||
$(CXX) $(CXXFLAGS) -Ilib -Icli -c -o test/testrunner.o test/testrunner.cpp
|
$(CXX) $(CXXFLAGS) -Ilib -Icli -c -o test/testrunner.o test/testrunner.cpp
|
||||||
|
|
||||||
|
|
|
@ -73,151 +73,6 @@ void CheckOther::warningOldStylePointerCast()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// Redundant code..
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void CheckOther::warningRedundantCode()
|
|
||||||
{
|
|
||||||
if (!_settings->_checkCodingStyle)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// if (p) delete p
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
|
||||||
{
|
|
||||||
if (! Token::simpleMatch(tok, "if ("))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const Token *tok2 = tok->tokAt(2);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Possible if-constructions:
|
|
||||||
*
|
|
||||||
* if (var)
|
|
||||||
* if (this->var)
|
|
||||||
* if (Foo::var)
|
|
||||||
*
|
|
||||||
**/
|
|
||||||
std::string varname = concatNames(&tok2);
|
|
||||||
|
|
||||||
if (!Token::Match(tok2, "%var% ) {"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
tok2 = tok2->tokAt(3);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Possible constructions:
|
|
||||||
*
|
|
||||||
* - delete %var%
|
|
||||||
* - delete [] %var%
|
|
||||||
* - free ( %var )
|
|
||||||
* - kfree ( %var% )
|
|
||||||
*
|
|
||||||
* Where %var% may be:
|
|
||||||
* - just variable name (var)
|
|
||||||
* - class member (this->var)
|
|
||||||
* - static member (Class::var)
|
|
||||||
*
|
|
||||||
**/
|
|
||||||
|
|
||||||
bool funcHasBracket = false;
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string varname2 = concatNames(&tok2);
|
|
||||||
|
|
||||||
if (Token::Match(tok2, "%var%") && varname == varname2)
|
|
||||||
tok2 = tok2->next();
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (funcHasBracket)
|
|
||||||
{
|
|
||||||
if (tok2->str() != ")")
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tok2 = tok2->next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Possible constructions:
|
|
||||||
*
|
|
||||||
* - if (%var%) { delete %var%; }
|
|
||||||
* - if (%var%) { delete %var%; %var% = 0; }
|
|
||||||
*
|
|
||||||
**/
|
|
||||||
if (Token::Match(tok2, "; } !!else"))
|
|
||||||
{
|
|
||||||
redundantIfDelete0Error(tok);
|
|
||||||
}
|
|
||||||
else if (Token::Match(tok2, "; %var%"))
|
|
||||||
{
|
|
||||||
tok2 = tok2->next();
|
|
||||||
std::string varname3 = concatNames(&tok2);
|
|
||||||
if (Token::Match(tok2, "%var% = 0 ; } !!else") && varname2 == varname3)
|
|
||||||
{
|
|
||||||
redundantIfDelete0Error(tok);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Redundant condition
|
|
||||||
// if (haystack.find(needle) != haystack.end())
|
|
||||||
// haystack.remove(needle);
|
|
||||||
redundantCondition2();
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void CheckOther::redundantCondition2()
|
|
||||||
{
|
|
||||||
const char pattern[] = "if ( %var% . find ( %any% ) != %var% . end ( ) ) "
|
|
||||||
"{|{|"
|
|
||||||
" %var% . remove ( %any% ) ; "
|
|
||||||
"}|}|";
|
|
||||||
const Token *tok = Token::findmatch(_tokenizer->tokens(), pattern);
|
|
||||||
while (tok)
|
|
||||||
{
|
|
||||||
bool b(tok->tokAt(15)->str() == "{");
|
|
||||||
|
|
||||||
// Get tokens for the fields %var% and %any%
|
|
||||||
const Token *var1 = tok->tokAt(2);
|
|
||||||
const Token *any1 = tok->tokAt(6);
|
|
||||||
const Token *var2 = tok->tokAt(9);
|
|
||||||
const Token *var3 = tok->tokAt(b ? 16 : 15);
|
|
||||||
const Token *any2 = tok->tokAt(b ? 20 : 19);
|
|
||||||
|
|
||||||
// Check if all the "%var%" fields are the same and if all the "%any%" are the same..
|
|
||||||
if (var1->str() == var2->str() &&
|
|
||||||
var2->str() == var3->str() &&
|
|
||||||
any1->str() == any2->str())
|
|
||||||
{
|
|
||||||
redundantIfRemoveError(tok);
|
|
||||||
}
|
|
||||||
|
|
||||||
tok = Token::findmatch(tok->next(), pattern);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// "if (strlen(s))" can be rewritten as "if (*s != '\0')"
|
// "if (strlen(s))" can be rewritten as "if (*s != '\0')"
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -4045,16 +3900,6 @@ void CheckOther::cstyleCastError(const Token *tok)
|
||||||
reportError(tok, Severity::style, "cstyleCast", "C-style pointer casting");
|
reportError(tok, Severity::style, "cstyleCast", "C-style pointer casting");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckOther::redundantIfDelete0Error(const Token *tok)
|
|
||||||
{
|
|
||||||
reportError(tok, Severity::style, "redundantIfDelete0", "Redundant condition. It is safe to deallocate a NULL pointer");
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckOther::redundantIfRemoveError(const Token *tok)
|
|
||||||
{
|
|
||||||
reportError(tok, Severity::style, "redundantIfRemove", "Redundant condition. The remove function in the STL will not do anything if element doesn't exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckOther::dangerousUsageStrtolError(const Token *tok)
|
void CheckOther::dangerousUsageStrtolError(const Token *tok)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::error, "dangerousUsageStrtol", "Invalid radix in call to strtol or strtoul. Must be 0 or 2-36");
|
reportError(tok, Severity::error, "dangerousUsageStrtol", "Invalid radix in call to strtol or strtoul. Must be 0 or 2-36");
|
||||||
|
|
|
@ -71,7 +71,6 @@ public:
|
||||||
CheckOther checkOther(tokenizer, settings, errorLogger);
|
CheckOther checkOther(tokenizer, settings, errorLogger);
|
||||||
|
|
||||||
// Coding style checks
|
// Coding style checks
|
||||||
checkOther.warningRedundantCode();
|
|
||||||
checkOther.checkConstantFunctionParameter();
|
checkOther.checkConstantFunctionParameter();
|
||||||
checkOther.checkIncompleteStatement();
|
checkOther.checkIncompleteStatement();
|
||||||
checkOther.checkEmptyStringTest();
|
checkOther.checkEmptyStringTest();
|
||||||
|
@ -104,9 +103,6 @@ public:
|
||||||
/** @brief Are there C-style pointer casts in a c++ file? */
|
/** @brief Are there C-style pointer casts in a c++ file? */
|
||||||
void warningOldStylePointerCast();
|
void warningOldStylePointerCast();
|
||||||
|
|
||||||
/** @brief Redundant code: if (p) delete p; */
|
|
||||||
void warningRedundantCode();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Invalid function usage (invalid radix / overlapping data)
|
* @brief Invalid function usage (invalid radix / overlapping data)
|
||||||
*
|
*
|
||||||
|
@ -163,11 +159,6 @@ public:
|
||||||
|
|
||||||
void lookupVar(const Token *tok1, const std::string &varname);
|
void lookupVar(const Token *tok1, const std::string &varname);
|
||||||
|
|
||||||
// Redundant condition
|
|
||||||
// if (haystack.find(needle) != haystack.end())
|
|
||||||
// haystack.remove(needle);
|
|
||||||
void redundantCondition2();
|
|
||||||
|
|
||||||
/** @brief %Check for inefficient empty string test*/
|
/** @brief %Check for inefficient empty string test*/
|
||||||
void checkEmptyStringTest();
|
void checkEmptyStringTest();
|
||||||
|
|
||||||
|
@ -194,8 +185,6 @@ public:
|
||||||
|
|
||||||
// Error messages..
|
// Error messages..
|
||||||
void cstyleCastError(const Token *tok);
|
void cstyleCastError(const Token *tok);
|
||||||
void redundantIfDelete0Error(const Token *tok);
|
|
||||||
void redundantIfRemoveError(const Token *tok);
|
|
||||||
void dangerousUsageStrtolError(const Token *tok);
|
void dangerousUsageStrtolError(const Token *tok);
|
||||||
void sprintfOverlappingDataError(const Token *tok, const std::string &varname);
|
void sprintfOverlappingDataError(const Token *tok, const std::string &varname);
|
||||||
void udivError(const Token *tok);
|
void udivError(const Token *tok);
|
||||||
|
@ -236,8 +225,6 @@ public:
|
||||||
|
|
||||||
// style
|
// style
|
||||||
cstyleCastError(0);
|
cstyleCastError(0);
|
||||||
redundantIfDelete0Error(0);
|
|
||||||
redundantIfRemoveError(0);
|
|
||||||
dangerousUsageStrtolError(0);
|
dangerousUsageStrtolError(0);
|
||||||
unusedStructMemberError(0, "structname", "variable");
|
unusedStructMemberError(0, "structname", "variable");
|
||||||
passedByValueError(0, "parametername");
|
passedByValueError(0, "parametername");
|
||||||
|
|
|
@ -711,3 +711,40 @@ void CheckStl::sizeError(const Token *tok)
|
||||||
const bool verbose(_settings ? _settings->_verbose : true);
|
const bool verbose(_settings ? _settings->_verbose : true);
|
||||||
reportError(tok, Severity::style, "stlSize", "Use " + varname + ".empty() instead of " + varname + ".size() to guarantee fast code." + (verbose ? " size() can take linear time but empty() is guaranteed to take constant time." : ""));
|
reportError(tok, Severity::style, "stlSize", "Use " + varname + ".empty() instead of " + varname + ".size() to guarantee fast code." + (verbose ? " size() can take linear time but empty() is guaranteed to take constant time." : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void CheckStl::redundantCondition()
|
||||||
|
{
|
||||||
|
const char pattern[] = "if ( %var% . find ( %any% ) != %var% . end ( ) ) "
|
||||||
|
"{|{|"
|
||||||
|
" %var% . remove ( %any% ) ; "
|
||||||
|
"}|}|";
|
||||||
|
const Token *tok = Token::findmatch(_tokenizer->tokens(), pattern);
|
||||||
|
while (tok)
|
||||||
|
{
|
||||||
|
bool b(tok->tokAt(15)->str() == "{");
|
||||||
|
|
||||||
|
// Get tokens for the fields %var% and %any%
|
||||||
|
const Token *var1 = tok->tokAt(2);
|
||||||
|
const Token *any1 = tok->tokAt(6);
|
||||||
|
const Token *var2 = tok->tokAt(9);
|
||||||
|
const Token *var3 = tok->tokAt(b ? 16 : 15);
|
||||||
|
const Token *any2 = tok->tokAt(b ? 20 : 19);
|
||||||
|
|
||||||
|
// Check if all the "%var%" fields are the same and if all the "%any%" are the same..
|
||||||
|
if (var1->str() == var2->str() &&
|
||||||
|
var2->str() == var3->str() &&
|
||||||
|
any1->str() == any2->str())
|
||||||
|
{
|
||||||
|
redundantIfRemoveError(tok);
|
||||||
|
}
|
||||||
|
|
||||||
|
tok = Token::findmatch(tok->next(), pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckStl::redundantIfRemoveError(const Token *tok)
|
||||||
|
{
|
||||||
|
reportError(tok, Severity::style, "redundantIfRemove", "Redundant condition. The remove function in the STL will not do anything if element doesn't exist");
|
||||||
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ public:
|
||||||
|
|
||||||
// Style check
|
// Style check
|
||||||
checkStl.size();
|
checkStl.size();
|
||||||
|
checkStl.redundantCondition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -105,6 +106,11 @@ public:
|
||||||
*/
|
*/
|
||||||
void size();
|
void size();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for redundant condition 'if (ints.find(1) != ints.end()) ints.remove(123);'
|
||||||
|
* */
|
||||||
|
void redundantCondition();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -125,6 +131,7 @@ private:
|
||||||
void if_findError(const Token *tok, bool str);
|
void if_findError(const Token *tok, bool str);
|
||||||
void sizeError(const Token *tok);
|
void sizeError(const Token *tok);
|
||||||
void eraseByValueError(const Token *tok, const std::string &containername, const std::string &itername);
|
void eraseByValueError(const Token *tok, const std::string &containername, const std::string &itername);
|
||||||
|
void redundantIfRemoveError(const Token *tok);
|
||||||
|
|
||||||
void getErrorMessages()
|
void getErrorMessages()
|
||||||
{
|
{
|
||||||
|
@ -141,6 +148,7 @@ private:
|
||||||
if_findError(0, true);
|
if_findError(0, true);
|
||||||
sizeError(0);
|
sizeError(0);
|
||||||
eraseByValueError(0, "container", "iterator");
|
eraseByValueError(0, "container", "iterator");
|
||||||
|
redundantIfRemoveError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string name() const
|
std::string name() const
|
||||||
|
@ -157,7 +165,8 @@ private:
|
||||||
"* dereferencing an erased iterator\n"
|
"* dereferencing an erased iterator\n"
|
||||||
"* for vectors: using iterator/pointer after push_back has been used\n"
|
"* for vectors: using iterator/pointer after push_back has been used\n"
|
||||||
"* optimisation: use empty() instead of size() to guarantee fast code\n"
|
"* optimisation: use empty() instead of size() to guarantee fast code\n"
|
||||||
"* suspicious condition when using find\n";
|
"* suspicious condition when using find\n"
|
||||||
|
"* redundant condition\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isStlContainer(const Token *tok);
|
bool isStlContainer(const Token *tok);
|
||||||
|
|
|
@ -24,7 +24,6 @@ SOURCES += testautovariables.cpp \
|
||||||
testmemleak.cpp \
|
testmemleak.cpp \
|
||||||
testother.cpp \
|
testother.cpp \
|
||||||
testpreprocessor.cpp \
|
testpreprocessor.cpp \
|
||||||
testredundantif.cpp \
|
|
||||||
testrunner.cpp \
|
testrunner.cpp \
|
||||||
testsimplifytokens.cpp \
|
testsimplifytokens.cpp \
|
||||||
teststl.cpp \
|
teststl.cpp \
|
||||||
|
|
|
@ -39,9 +39,6 @@ private:
|
||||||
TEST_CASE(zeroDiv3);
|
TEST_CASE(zeroDiv3);
|
||||||
TEST_CASE(zeroDiv4);
|
TEST_CASE(zeroDiv4);
|
||||||
|
|
||||||
TEST_CASE(delete1);
|
|
||||||
TEST_CASE(delete2);
|
|
||||||
|
|
||||||
TEST_CASE(sprintf1); // Dangerous usage of sprintf
|
TEST_CASE(sprintf1); // Dangerous usage of sprintf
|
||||||
TEST_CASE(sprintf2);
|
TEST_CASE(sprintf2);
|
||||||
TEST_CASE(sprintf3);
|
TEST_CASE(sprintf3);
|
||||||
|
@ -130,7 +127,6 @@ private:
|
||||||
// Simplify token list..
|
// Simplify token list..
|
||||||
tokenizer.simplifyTokenList();
|
tokenizer.simplifyTokenList();
|
||||||
|
|
||||||
checkOther.warningRedundantCode();
|
|
||||||
checkOther.checkZeroDivision();
|
checkOther.checkZeroDivision();
|
||||||
checkOther.checkMathFunctions();
|
checkOther.checkMathFunctions();
|
||||||
checkOther.checkEmptyStringTest();
|
checkOther.checkEmptyStringTest();
|
||||||
|
@ -249,137 +245,6 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete1()
|
|
||||||
{
|
|
||||||
check("void foo()\n"
|
|
||||||
"{\n"
|
|
||||||
" if (p)\n"
|
|
||||||
" {\n"
|
|
||||||
" delete p;\n"
|
|
||||||
" z = 0;\n"
|
|
||||||
" }\n"
|
|
||||||
"}\n");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void foo()\n"
|
|
||||||
"{\n"
|
|
||||||
" if (p)\n"
|
|
||||||
" delete p;\n"
|
|
||||||
" else\n"
|
|
||||||
" p = new P();\n"
|
|
||||||
"}\n");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void foo()\n"
|
|
||||||
"{\n"
|
|
||||||
" if (0 != g->p)\n"
|
|
||||||
" delete this->p;\n"
|
|
||||||
"}\n");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void foo()\n"
|
|
||||||
"{\n"
|
|
||||||
" if (0 != g->p)\n"
|
|
||||||
" {\n"
|
|
||||||
" delete g->p;\n"
|
|
||||||
" g->z = 0;\n"
|
|
||||||
" }\n"
|
|
||||||
"}\n");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void foo()\n"
|
|
||||||
"{\n"
|
|
||||||
" if (0 != this->g->a)\n"
|
|
||||||
" delete this->p->a;\n"
|
|
||||||
"}\n");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void delete2()
|
|
||||||
{
|
|
||||||
check("void foo()\n"
|
|
||||||
"{\n"
|
|
||||||
" if (p)\n"
|
|
||||||
" {\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());
|
|
||||||
|
|
||||||
check("void foo()\n"
|
|
||||||
"{\n"
|
|
||||||
" if (p)\n"
|
|
||||||
" {\n"
|
|
||||||
" delete p;\n"
|
|
||||||
" p = 0;\n"
|
|
||||||
" }\n"
|
|
||||||
"}\n");
|
|
||||||
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 (p)\n"
|
|
||||||
" delete 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()\n"
|
|
||||||
"{\n"
|
|
||||||
" if (p != NULL)\n"
|
|
||||||
" delete 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()\n"
|
|
||||||
"{\n"
|
|
||||||
" if (p != NULL)\n"
|
|
||||||
" {\n"
|
|
||||||
" delete p;\n"
|
|
||||||
" p = NULL;\n"
|
|
||||||
" }\n"
|
|
||||||
"}\n");
|
|
||||||
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 (p)\n"
|
|
||||||
" delete [] 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()\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()\n"
|
|
||||||
"{\n"
|
|
||||||
" if (0 != this->p->a)\n"
|
|
||||||
" delete this->p->a;\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());
|
|
||||||
|
|
||||||
check("void Foo::deleteInstance()\n"
|
|
||||||
"{\n"
|
|
||||||
" if (Foo::instance != NULL)\n"
|
|
||||||
" {\n"
|
|
||||||
" delete Foo::instance;\n"
|
|
||||||
" Foo::instance = NULL;\n"
|
|
||||||
" }\n"
|
|
||||||
"}\n");
|
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Redundant condition. It is safe to deallocate a NULL pointer\n", errout.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sprintfUsage(const char code[])
|
void sprintfUsage(const char code[])
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,87 +0,0 @@
|
||||||
/*
|
|
||||||
* Cppcheck - A tool for static C/C++ code analysis
|
|
||||||
* Copyright (C) 2007-2010 Daniel Marjamäki and Cppcheck team.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Check for dangerous division..
|
|
||||||
// such as "svar / uvar". Treating "svar" as unsigned data is not good
|
|
||||||
|
|
||||||
|
|
||||||
#include "tokenize.h"
|
|
||||||
#include "checkother.h"
|
|
||||||
#include "testsuite.h"
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
extern std::ostringstream errout;
|
|
||||||
|
|
||||||
class TestRedundantIf : public TestFixture
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TestRedundantIf() : TestFixture("TestRedundantIf")
|
|
||||||
{ }
|
|
||||||
|
|
||||||
private:
|
|
||||||
void check(const char code[])
|
|
||||||
{
|
|
||||||
// Tokenize..
|
|
||||||
Tokenizer tokenizer;
|
|
||||||
std::istringstream istr(code);
|
|
||||||
tokenizer.tokenize(istr, "test.cpp");
|
|
||||||
|
|
||||||
// Clear the error buffer..
|
|
||||||
errout.str("");
|
|
||||||
|
|
||||||
// Check for redundant condition..
|
|
||||||
Settings settings;
|
|
||||||
CheckOther checkOther(&tokenizer, &settings, this);
|
|
||||||
checkOther.redundantCondition2();
|
|
||||||
}
|
|
||||||
|
|
||||||
void run()
|
|
||||||
{
|
|
||||||
TEST_CASE(remove1);
|
|
||||||
TEST_CASE(remove2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove1()
|
|
||||||
{
|
|
||||||
check("void f()\n"
|
|
||||||
"{\n"
|
|
||||||
" if (haystack.find(needle) != haystack.end())\n"
|
|
||||||
" haystack.remove(needle);"
|
|
||||||
"}\n");
|
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Redundant condition. The remove function in the STL will not do anything if element doesn't exist\n", errout.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove2()
|
|
||||||
{
|
|
||||||
check("void f()\n"
|
|
||||||
"{\n"
|
|
||||||
" if (haystack.find(needle) != haystack.end())\n"
|
|
||||||
" {\n"
|
|
||||||
" haystack.remove(needle);\n"
|
|
||||||
" }\n"
|
|
||||||
"}\n");
|
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Redundant condition. The remove function in the STL will not do anything if element doesn't exist\n", errout.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
REGISTER_TEST(TestRedundantIf)
|
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,11 @@ private:
|
||||||
TEST_CASE(if_str_find);
|
TEST_CASE(if_str_find);
|
||||||
|
|
||||||
TEST_CASE(size1);
|
TEST_CASE(size1);
|
||||||
|
|
||||||
|
// Redundant conditions..
|
||||||
|
// if (ints.find(123) != ints.end()) ints.remove(123);
|
||||||
|
TEST_CASE(redundantCondition1);
|
||||||
|
TEST_CASE(redundantCondition2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check(const std::string &code)
|
void check(const std::string &code)
|
||||||
|
@ -946,6 +951,28 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void redundantCondition1()
|
||||||
|
{
|
||||||
|
check("void f()\n"
|
||||||
|
"{\n"
|
||||||
|
" if (haystack.find(needle) != haystack.end())\n"
|
||||||
|
" haystack.remove(needle);"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) Redundant condition. The remove function in the STL will not do anything if element doesn't exist\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void redundantCondition2()
|
||||||
|
{
|
||||||
|
check("void f()\n"
|
||||||
|
"{\n"
|
||||||
|
" if (haystack.find(needle) != haystack.end())\n"
|
||||||
|
" {\n"
|
||||||
|
" haystack.remove(needle);\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) Redundant condition. The remove function in the STL will not do anything if element doesn't exist\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST(TestStl)
|
REGISTER_TEST(TestStl)
|
||||||
|
|
Loading…
Reference in New Issue