diff --git a/Makefile b/Makefile index 0456c11d2..34b16b85c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ SRCS=checkbufferoverrun.cpp checkclass.cpp checkheaders.cpp checkmemoryleak.cpp checkfunctionusage.cpp checkother.cpp filelister.cpp preprocessor.cpp tokenize.cpp cppcheck.cpp settings.cpp token.cpp cppcheckexecutor.cpp OBJS=$(SRCS:%.cpp=%.o) -TESTS=testbufferoverrun.o testcharvar.o testclass.o testconstructors.o testdivision.o testfunctionusage.o testincompletestatement.o testmemleak.o testpreprocessor.o testsimplifytokens.o testtokenize.o testtoken.o testunusedprivfunc.o testunusedvar.o testfilelister.o +TESTS=testbufferoverrun.o testcharvar.o testclass.o testconstructors.o testdivision.o testfunctionusage.o testincompletestatement.o testmemleak.o testpreprocessor.o testredundantif.o testsimplifytokens.o testtokenize.o testtoken.o testunusedprivfunc.o testunusedvar.o testfilelister.o BIN = ${DESTDIR}/usr/bin all: ${OBJS} main.o @@ -49,6 +49,8 @@ testmemleak.o: testmemleak.cpp tokenize.h settings.h errorlogger.h token.h check g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp testpreprocessor.o: testpreprocessor.cpp testsuite.h errorlogger.h preprocessor.h g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp +testredundantif.o: testredundantif.cpp testsuite.h errorlogger.h checkother.h + g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp testrunner.o: testrunner.cpp testsuite.h errorlogger.h g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp testsimplifytokens.o: testsimplifytokens.cpp testsuite.h errorlogger.h tokenize.h settings.h token.h diff --git a/checkother.cpp b/checkother.cpp index 376c5dc88..1b4e93c37 100644 --- a/checkother.cpp +++ b/checkother.cpp @@ -203,14 +203,49 @@ void CheckOther::WarningRedundantCode() } } - - // TODO: Redundant condition + + + // Redundant condition // if (haystack.find(needle) != haystack.end()) - // haystack.remove(needle); - + // 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 = TOKEN::Match( tok->tokAt(15), "{" ); + + // 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() ) + { + std::ostringstream errmsg; + errmsg << _tokenizer->fileLine(tok) + << ": Redundant condition found. The remove function in the STL will not do anything if element doesn't exist"; + _errorLogger->reportErr(errmsg.str()); + } + + tok = TOKEN::findmatch( tok->next(), pattern ); + } +} +//--------------------------------------------------------------------------- + diff --git a/checkother.h b/checkother.h index 78fadbcf8..a84cd424c 100644 --- a/checkother.h +++ b/checkother.h @@ -75,10 +75,18 @@ public: void unreachableCode(); /** Unused function variables */ - void functionVariableUsage(); -private: + void functionVariableUsage(); + +#ifndef UNIT_TESTING +private: +#endif void CheckVariableScope_LookupVar( const TOKEN *tok1, const char varname[] ); - + + // Redundant condition + // if (haystack.find(needle) != haystack.end()) + // haystack.remove(needle); + void redundantCondition2(); + const Tokenizer *_tokenizer; ErrorLogger *_errorLogger; }; diff --git a/testredundantif.cpp b/testredundantif.cpp new file mode 100644 index 000000000..cfe7809bc --- /dev/null +++ b/testredundantif.cpp @@ -0,0 +1,87 @@ +/* + * c++check - c/c++ syntax checking + * Copyright (C) 2007 Daniel Marjamäki + * + * 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 + +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.. + CheckOther checkOther( &tokenizer, this ); + checkOther.redundantCondition2(); + } + + void run() + { + // TODO TEST_CASE( remove1 ); + // TODO TEST_CASE( remove2 ); + } + + void remove1() + { + check( "void f()\n" + "{\n" + " if (haystack.find(needle) != haystack.end())\n" + " haystack.remove(needle);" + "}\n" ); + ASSERT_EQUALS( std::string("[test.cpp:3]: Redundant condition.\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( std::string("[test.cpp:3]: Redundant condition.\n"), errout.str() ); + } + +}; + +REGISTER_TEST( TestRedundantIf ) + +