diff --git a/CheckMemoryLeak.cpp b/CheckMemoryLeak.cpp index b58253270..a1c002c73 100644 --- a/CheckMemoryLeak.cpp +++ b/CheckMemoryLeak.cpp @@ -189,26 +189,26 @@ CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetDeallocationType( const //-------------------------------------------------------------------------- const char * CheckMemoryLeakClass::call_func( const TOKEN *tok, std::list callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype ) -{ +{ // Keywords that are not function calls.. if (TOKEN::Match(tok,"if|for|while")) - return 0; - - // String functions that are not allocating nor deallocating memory.. - if (TOKEN::Match(tok, "strcpy|strncpy|strcat|strncat|strcmp|strncmp|strcasecmp|stricmp|sprintf|strchr|strrchr|strstr")) - return 0; - - // Memory functions that are not allocating nor deallocating memory.. - if (TOKEN::Match(tok, "memset|memcpy|memmove|memchr")) - return 0; - - // I/O functions that are not allocating nor deallocating memory.. - if (TOKEN::Match(tok, "fgets|fgetc|fputs|fputc|printf")) return 0; - - // Convert functions that are not allocating nor deallocating memory.. - if (TOKEN::Match(tok, "atoi|atof|atol|strtol|strtoul|strtod")) - return 0; + + // String functions that are not allocating nor deallocating memory.. + if (TOKEN::Match(tok, "strcpy|strncpy|strcat|strncat|strcmp|strncmp|strcasecmp|stricmp|sprintf|strchr|strrchr|strstr")) + return 0; + + // Memory functions that are not allocating nor deallocating memory.. + if (TOKEN::Match(tok, "memset|memcpy|memmove|memchr")) + return 0; + + // I/O functions that are not allocating nor deallocating memory.. + if (TOKEN::Match(tok, "fgets|fgetc|fputs|fputc|printf")) + return 0; + + // Convert functions that are not allocating nor deallocating memory.. + if (TOKEN::Match(tok, "atoi|atof|atol|strtol|strtoul|strtod")) + return 0; if (GetAllocationType(tok)!=No || GetReallocationType(tok)!=No || GetDeallocationType(tok,varnames)!=No) return 0; diff --git a/testtoken.cpp b/testtoken.cpp index d92b39f75..ffca19318 100644 --- a/testtoken.cpp +++ b/testtoken.cpp @@ -1,61 +1,61 @@ -/* - * c++check - c/c++ syntax checking - * Copyright (C) 2008 Daniel Marjamäki and Reijo Tomperi - * - * 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 -#include "testsuite.h" -#include "token.h" - -extern std::ostringstream errout; -class TestTOKEN : public TestFixture -{ -public: - TestTOKEN() : TestFixture("TestTOKEN") - { } - -private: - - void run() - { - TEST_CASE( nextprevious ); - - } - - void nextprevious() - { - TOKEN *token = new TOKEN; - token->setstr( "1" ); - token->insertToken( "2" ); - token->next()->insertToken( "3" ); - TOKEN *last = token->next()->next(); - ASSERT_EQUALS( token->str(), "1" ); - ASSERT_EQUALS( token->next()->str(), "2" ); - ASSERT_EQUALS( token->next()->next()->str(), "3" ); - if( last->next() ) - ASSERT_EQUALS( "Null was expected", "" ); - - ASSERT_EQUALS( last->str(), "3" ); - ASSERT_EQUALS( last->previous()->str(), "2" ); - ASSERT_EQUALS( last->previous()->previous()->str(), "1" ); - if( token->previous() ) - ASSERT_EQUALS( "Null was expected", "" ); - } - - -}; - -REGISTER_TEST( TestTOKEN ) +/* + * c++check - c/c++ syntax checking + * Copyright (C) 2008 Daniel Marjamäki and Reijo Tomperi + * + * 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 +#include "testsuite.h" +#include "token.h" + +extern std::ostringstream errout; +class TestTOKEN : public TestFixture +{ +public: + TestTOKEN() : TestFixture("TestTOKEN") + { } + +private: + + void run() + { + TEST_CASE( nextprevious ); + + } + + void nextprevious() + { + TOKEN *token = new TOKEN; + token->setstr( "1" ); + token->insertToken( "2" ); + token->next()->insertToken( "3" ); + TOKEN *last = token->next()->next(); + ASSERT_EQUALS( token->str(), "1" ); + ASSERT_EQUALS( token->next()->str(), "2" ); + ASSERT_EQUALS( token->next()->next()->str(), "3" ); + if( last->next() ) + ASSERT_EQUALS( "Null was expected", "" ); + + ASSERT_EQUALS( last->str(), "3" ); + ASSERT_EQUALS( last->previous()->str(), "2" ); + ASSERT_EQUALS( last->previous()->previous()->str(), "1" ); + if( token->previous() ) + ASSERT_EQUALS( "Null was expected", "" ); + } + + +}; + +REGISTER_TEST( TestTOKEN ) diff --git a/testtokenize.cpp b/testtokenize.cpp index 571f34663..c10c6add3 100644 --- a/testtokenize.cpp +++ b/testtokenize.cpp @@ -46,8 +46,8 @@ private: TEST_CASE( const_and_volatile_functions ); - TEST_CASE( numeric_true_condition ); - + TEST_CASE( numeric_true_condition ); + TEST_CASE( simplify_known_variables ); TEST_CASE( multi_compare ); @@ -218,119 +218,119 @@ private: ostr << " " << tok->str(); ASSERT_EQUALS( std::string(" void f ( ) { if ( true ) ; }"), ostr.str() ); } - - void simplify_known_variables() - { - { - const char code[] = "void f()\n" - "{\n" - " int a = 10;\n" - " if (a);\n" - "}\n"; - - // tokenize.. - Tokenizer tokenizer; - std::istringstream istr(code); - tokenizer.tokenize(istr, "test.cpp"); - - tokenizer.setVarId(); - tokenizer.simplifyKnownVariables(); - - std::ostringstream ostr; - for (const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next()) - ostr << " " << tok->str(); - ASSERT_EQUALS( std::string(" void f ( ) { int a = 10 ; if ( 10 ) ; }"), ostr.str() ); - } - - { - const char code[] = "void f()\n" - "{\n" - " int a = 10;\n" - " a = g();\n" - " if (a);\n" - "}\n"; - - // tokenize.. - Tokenizer tokenizer; - std::istringstream istr(code); - tokenizer.tokenize(istr, "test.cpp"); - - tokenizer.setVarId(); - tokenizer.simplifyKnownVariables(); - - std::ostringstream ostr; - for (const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next()) - ostr << " " << tok->str(); - ASSERT_EQUALS( std::string(" void f ( ) { int a = 10 ; a = g ( ) ; if ( a ) ; }"), ostr.str() ); - } - - { - const char code[] = "void f()\n" - "{\n" - " int a = 4;\n" - " while(true){\n" - " break;\n" - " a = 10;\n" - " }\n" - " if (a);\n" - "}\n"; - - // tokenize.. - Tokenizer tokenizer; - std::istringstream istr(code); - tokenizer.tokenize(istr, "test.cpp"); - - tokenizer.setVarId(); - tokenizer.simplifyKnownVariables(); - - std::ostringstream ostr; - for (const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next()) - ostr << " " << tok->str(); - ASSERT_EQUALS( std::string(" void f ( ) { int a = 4 ; while ( true ) { break ; a = 10 ; } if ( a ) ; }"), ostr.str() ); - } - - { - const char code[] = "void f()\n" - "{\n" - " int a = 4;\n" - " if ( g(a));\n" - "}\n"; - - // tokenize.. - Tokenizer tokenizer; - std::istringstream istr(code); - tokenizer.tokenize(istr, "test.cpp"); - - tokenizer.setVarId(); - tokenizer.simplifyKnownVariables(); - - std::ostringstream ostr; - for (const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next()) - ostr << " " << tok->str(); - ASSERT_EQUALS( std::string(" void f ( ) { int a = 4 ; if ( g ( a ) ) ; }"), ostr.str() ); - } - - { - const char code[] = "void f()\n" - "{\n" - " int a = 4;\n" - " if ( a = 5 );\n" - "}\n"; - - // tokenize.. - Tokenizer tokenizer; - std::istringstream istr(code); - tokenizer.tokenize(istr, "test.cpp"); - - tokenizer.setVarId(); - tokenizer.simplifyKnownVariables(); - - std::ostringstream ostr; - for (const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next()) - ostr << " " << tok->str(); - ASSERT_EQUALS( std::string(" void f ( ) { int a = 4 ; if ( a = 5 ) ; }"), ostr.str() ); - } - } + + void simplify_known_variables() + { + { + const char code[] = "void f()\n" + "{\n" + " int a = 10;\n" + " if (a);\n" + "}\n"; + + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + tokenizer.setVarId(); + tokenizer.simplifyKnownVariables(); + + std::ostringstream ostr; + for (const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next()) + ostr << " " << tok->str(); + ASSERT_EQUALS( std::string(" void f ( ) { int a = 10 ; if ( 10 ) ; }"), ostr.str() ); + } + + { + const char code[] = "void f()\n" + "{\n" + " int a = 10;\n" + " a = g();\n" + " if (a);\n" + "}\n"; + + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + tokenizer.setVarId(); + tokenizer.simplifyKnownVariables(); + + std::ostringstream ostr; + for (const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next()) + ostr << " " << tok->str(); + ASSERT_EQUALS( std::string(" void f ( ) { int a = 10 ; a = g ( ) ; if ( a ) ; }"), ostr.str() ); + } + + { + const char code[] = "void f()\n" + "{\n" + " int a = 4;\n" + " while(true){\n" + " break;\n" + " a = 10;\n" + " }\n" + " if (a);\n" + "}\n"; + + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + tokenizer.setVarId(); + tokenizer.simplifyKnownVariables(); + + std::ostringstream ostr; + for (const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next()) + ostr << " " << tok->str(); + ASSERT_EQUALS( std::string(" void f ( ) { int a = 4 ; while ( true ) { break ; a = 10 ; } if ( a ) ; }"), ostr.str() ); + } + + { + const char code[] = "void f()\n" + "{\n" + " int a = 4;\n" + " if ( g(a));\n" + "}\n"; + + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + tokenizer.setVarId(); + tokenizer.simplifyKnownVariables(); + + std::ostringstream ostr; + for (const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next()) + ostr << " " << tok->str(); + ASSERT_EQUALS( std::string(" void f ( ) { int a = 4 ; if ( g ( a ) ) ; }"), ostr.str() ); + } + + { + const char code[] = "void f()\n" + "{\n" + " int a = 4;\n" + " if ( a = 5 );\n" + "}\n"; + + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + tokenizer.setVarId(); + tokenizer.simplifyKnownVariables(); + + std::ostringstream ostr; + for (const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next()) + ostr << " " << tok->str(); + ASSERT_EQUALS( std::string(" void f ( ) { int a = 4 ; if ( a = 5 ) ; }"), ostr.str() ); + } + } void multi_compare() { diff --git a/tokenize.cpp b/tokenize.cpp index d86090b07..f092340c5 100644 --- a/tokenize.cpp +++ b/tokenize.cpp @@ -1011,19 +1011,19 @@ void Tokenizer::simplifyTokenList() } } - + bool done = false; while ( ! done ) - { + { done = true; - if( simplifyConditions() ) - done = false; - - if( simplifyCasts() ) - done = false; - - if( simplifyFunctionReturn() ) - done = false; + if( simplifyConditions() ) + done = false; + + if( simplifyCasts() ) + done = false; + + if( simplifyFunctionReturn() ) + done = false; } } //--------------------------------------------------------------------------- @@ -1099,139 +1099,139 @@ bool Tokenizer::simplifyConditions() return ret; } - -bool Tokenizer::simplifyCasts() -{ - bool ret = false; - for ( TOKEN *tok = _tokens; tok; tok = tok->next() ) - { - if ( TOKEN::Match(tok->next(), "( %type% * )") ) - { - tok->deleteNext(); - tok->deleteNext(); - tok->deleteNext(); - tok->deleteNext(); - ret = true; - } - - else if ( TOKEN::Match(tok->next(), "dynamic_cast|reinterpret_cast|const_cast|static_cast <" ) ) - { - while ( tok->next() && tok->next()->str() != ">" ) - tok->deleteNext(); - tok->deleteNext(); - tok->deleteNext(); - TOKEN *tok2 = tok; - int parlevel = 0; - while ( tok2->next() && parlevel >= 0 ) - { - tok2 = tok2->next(); - if ( TOKEN::Match(tok2->next(), "(") ) - ++parlevel; - else if ( TOKEN::Match(tok2->next(), ")") ) - --parlevel; - } - if (tok2->next()) - tok2->deleteNext(); - - ret = true; - } - } - - return ret; -} - - - -bool Tokenizer::simplifyFunctionReturn() -{ - bool ret = false; - int indentlevel = 0; - for ( const TOKEN *tok = tokens(); tok; tok = tok->next() ) - { - if ( tok->str() == "{" ) - ++indentlevel; - - else if ( tok->str() == "}" ) - --indentlevel; - - else if ( indentlevel == 0 && TOKEN::Match(tok, "%var% ( ) { return %num% ; }") ) - { - std::ostringstream pattern; - pattern << "[(=+-*/] " << tok->str() << " ( ) [;)+-*/]"; - for ( TOKEN *tok2 = _tokens; tok2; tok2 = tok2->next() ) - { - if ( TOKEN::Match(tok2, pattern.str().c_str()) ) - { - tok2 = tok2->next(); - tok2->setstr( tok->strAt(5) ); - tok2->deleteNext(); - tok2->deleteNext(); - ret = true; - } - } - } - } - - return ret; -} - -bool Tokenizer::simplifyKnownVariables() -{ - // TODO, this function should be called from simplifyTokenList() - // after the implementation is done. - // TODO, this functions needs to be implemented. - // TODO, test - bool ret = false; - for ( TOKEN *tok = _tokens; tok; tok = tok->next() ) - { - // Search for a block of code - if ( ! TOKEN::Match(tok, ") const| {") ) - continue; - - // parse the block of code.. - int indentlevel = 0; - for ( TOKEN *tok2 = tok; tok2; tok2 = tok2->next() ) - { - if ( tok2->str() == "{" ) - ++indentlevel; - - else if ( tok2->str() == "}" ) - { - --indentlevel; - if ( indentlevel <= 0 ) - continue; - } - - else if ( TOKEN::Match(tok2, "%var% = %num% ;") ) - { - unsigned int varid = tok2->varId(); - TOKEN *tok3 = tok2; - while ( tok3 ) - { - tok3 = tok3->next(); - - // Perhaps it's a loop => bail out - if ( TOKEN::Match(tok3, "[{}]") ) - break; - - // Variable is used somehow in a non-defined pattern => bail out - if ( tok3->varId() == varid ) - break; - - // Replace variable with numeric constant.. - if ( TOKEN::Match(tok3, "if ( %varid% )", 0, 0, varid) ) - { - tok3 = tok3->next()->next(); - tok3->setstr( tok2->strAt(2) ); - ret = true; - } - } - } - } - } - - return ret; -} + +bool Tokenizer::simplifyCasts() +{ + bool ret = false; + for ( TOKEN *tok = _tokens; tok; tok = tok->next() ) + { + if ( TOKEN::Match(tok->next(), "( %type% * )") ) + { + tok->deleteNext(); + tok->deleteNext(); + tok->deleteNext(); + tok->deleteNext(); + ret = true; + } + + else if ( TOKEN::Match(tok->next(), "dynamic_cast|reinterpret_cast|const_cast|static_cast <" ) ) + { + while ( tok->next() && tok->next()->str() != ">" ) + tok->deleteNext(); + tok->deleteNext(); + tok->deleteNext(); + TOKEN *tok2 = tok; + int parlevel = 0; + while ( tok2->next() && parlevel >= 0 ) + { + tok2 = tok2->next(); + if ( TOKEN::Match(tok2->next(), "(") ) + ++parlevel; + else if ( TOKEN::Match(tok2->next(), ")") ) + --parlevel; + } + if (tok2->next()) + tok2->deleteNext(); + + ret = true; + } + } + + return ret; +} + + + +bool Tokenizer::simplifyFunctionReturn() +{ + bool ret = false; + int indentlevel = 0; + for ( const TOKEN *tok = tokens(); tok; tok = tok->next() ) + { + if ( tok->str() == "{" ) + ++indentlevel; + + else if ( tok->str() == "}" ) + --indentlevel; + + else if ( indentlevel == 0 && TOKEN::Match(tok, "%var% ( ) { return %num% ; }") ) + { + std::ostringstream pattern; + pattern << "[(=+-*/] " << tok->str() << " ( ) [;)+-*/]"; + for ( TOKEN *tok2 = _tokens; tok2; tok2 = tok2->next() ) + { + if ( TOKEN::Match(tok2, pattern.str().c_str()) ) + { + tok2 = tok2->next(); + tok2->setstr( tok->strAt(5) ); + tok2->deleteNext(); + tok2->deleteNext(); + ret = true; + } + } + } + } + + return ret; +} + +bool Tokenizer::simplifyKnownVariables() +{ + // TODO, this function should be called from simplifyTokenList() + // after the implementation is done. + // TODO, this functions needs to be implemented. + // TODO, test + bool ret = false; + for ( TOKEN *tok = _tokens; tok; tok = tok->next() ) + { + // Search for a block of code + if ( ! TOKEN::Match(tok, ") const| {") ) + continue; + + // parse the block of code.. + int indentlevel = 0; + for ( TOKEN *tok2 = tok; tok2; tok2 = tok2->next() ) + { + if ( tok2->str() == "{" ) + ++indentlevel; + + else if ( tok2->str() == "}" ) + { + --indentlevel; + if ( indentlevel <= 0 ) + continue; + } + + else if ( TOKEN::Match(tok2, "%var% = %num% ;") ) + { + unsigned int varid = tok2->varId(); + TOKEN *tok3 = tok2; + while ( tok3 ) + { + tok3 = tok3->next(); + + // Perhaps it's a loop => bail out + if ( TOKEN::Match(tok3, "[{}]") ) + break; + + // Variable is used somehow in a non-defined pattern => bail out + if ( tok3->varId() == varid ) + break; + + // Replace variable with numeric constant.. + if ( TOKEN::Match(tok3, "if ( %varid% )", 0, 0, varid) ) + { + tok3 = tok3->next()->next(); + tok3->setstr( tok2->strAt(2) ); + ret = true; + } + } + } + } + } + + return ret; +} //--------------------------------------------------------------------------- // Helper functions for handling the tokens list diff --git a/tokenize.h b/tokenize.h index cc212733f..4e826d88c 100644 --- a/tokenize.h +++ b/tokenize.h @@ -78,7 +78,7 @@ public: void fillFunctionList(); const TOKEN *GetFunctionTokenByName( const char funcname[] ) const; const TOKEN *tokens() const; - + #ifndef UNIT_TESTING private: @@ -94,34 +94,34 @@ private: void Define(const char Name[], const char Value[]); void addtoken(const char str[], const unsigned int lineno, const unsigned int fileno); - - /** Simplify conditions - * @return true if something is modified - * false if nothing is done. + + /** Simplify conditions + * @return true if something is modified + * false if nothing is done. + */ + bool simplifyConditions(); + + /** Simplify casts + * @return true if something is modified + * false if nothing is done. */ - bool simplifyConditions(); - - /** Simplify casts - * @return true if something is modified - * false if nothing is done. - */ bool simplifyCasts(); - - /** Simplify function calls - constant return value - * @return true if something is modified - * false if nothing is done. - */ - bool simplifyFunctionReturn(); - - /** - * A simplify function that replaces a variable with its value in cases - * when the value is known. e.g. "x=10; if(x)" => "x=10;if(10)" - * - * @param token The token list to check and modify. - * @return true if modifications to token-list are done. - * false if no modifications are done. - */ - bool simplifyKnownVariables(); + + /** Simplify function calls - constant return value + * @return true if something is modified + * false if nothing is done. + */ + bool simplifyFunctionReturn(); + + /** + * A simplify function that replaces a variable with its value in cases + * when the value is known. e.g. "x=10; if(x)" => "x=10;if(10)" + * + * @param token The token list to check and modify. + * @return true if modifications to token-list are done. + * false if no modifications are done. + */ + bool simplifyKnownVariables(); TOKEN *_gettok(TOKEN *tok, int index);