diff --git a/testtokenize.cpp b/testtokenize.cpp index 1c1bc07dc..a486bc6fc 100644 --- a/testtokenize.cpp +++ b/testtokenize.cpp @@ -46,6 +46,8 @@ private: TEST_CASE( const_and_volatile_functions ); + TEST_CASE( ifAddBraces ); + TEST_CASE( numeric_true_condition ); TEST_CASE( simplify_known_variables ); @@ -220,6 +222,66 @@ private: ASSERT_EQUALS( std::string(" void f ( ) { ; }"), ostr.str() ); } + void ifAddBraces() + { + { + const char code[] = "void f()\n" + "{\n" + " if (a);\n" + "}\n"; + + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + ASSERT_EQUALS( true, tokenizer.simplifyIfAddBraces() ); + + std::ostringstream ostr; + for (const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next()) + ostr << " " << tok->str(); + ASSERT_EQUALS( std::string(" void f ( ) { if ( a ) { ; } }"), ostr.str() ); + } + + { + const char code[] = "void f()\n" + "{\n" + " if (a) if (b) { }\n" + "}\n"; + + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + ASSERT_EQUALS( true, tokenizer.simplifyIfAddBraces() ); + + std::ostringstream ostr; + for (const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next()) + ostr << " " << tok->str(); + ASSERT_EQUALS( std::string(" void f ( ) { if ( a ) { if ( b ) { } } }"), ostr.str() ); + } + + { + const char code[] = "void f()\n" + "{\n" + " if (a) for (;;) { }\n" + "}\n"; + + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + ASSERT_EQUALS( true, tokenizer.simplifyIfAddBraces() ); + + std::ostringstream ostr; + for (const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next()) + ostr << " " << tok->str(); + ASSERT_EQUALS( std::string(" void f ( ) { if ( a ) { for ( ; ; ) { } } }"), ostr.str() ); + } + } + void simplify_known_variables() { { diff --git a/tokenize.cpp b/tokenize.cpp index 689e42007..49e93fc16 100644 --- a/tokenize.cpp +++ b/tokenize.cpp @@ -1216,6 +1216,72 @@ bool Tokenizer::removeReduntantConditions() return ret; } +bool Tokenizer::simplifyIfAddBraces() +{ + bool ret = false; + + for ( TOKEN *tok = _tokens; tok; tok = tok->next() ) + { + if ( ! TOKEN::Match(tok, "if|for|while (") ) + continue; + + // Goto the ending ')' + int parlevel = 1; + tok = tok->next(); + while ( parlevel >= 1 && (tok = tok->next()) ) + { + if ( tok->str() == "(" ) + ++parlevel; + else if ( tok->str() == ")" ) + --parlevel; + } + + // ')' should be followed by '{' + if ( TOKEN::Match(tok, ") {") ) + continue; + + // insert open brace.. + tok->insertToken("{"); + + // insert close brace.. + // In most cases it would work to just search for the next ';' and insert a closing brace after it. + // But here are special cases.. + // * if (cond) for (;;) break; + // * if (cond1) if (cond2) { } + parlevel = 0; + int indentlevel = 0; + while ( (tok = tok->next()) != NULL ) + { + if ( tok->str() == "{" ) + ++indentlevel; + + else if ( tok->str() == "}" ) + { + --indentlevel; + if ( indentlevel == 0 ) + break; + } + + else if ( tok->str() == "(" ) + ++parlevel; + + else if ( tok->str() == ")" ) + --parlevel; + + else if ( indentlevel == 0 && parlevel == 0 && tok->str() == ";" ) + break; + } + + if ( tok ) + { + tok->insertToken("}"); + ret = true; + } + } + + return ret; +} + bool Tokenizer::simplifyConditions() { bool ret = false; diff --git a/tokenize.h b/tokenize.h index 48ba4ac35..8259c7ac2 100644 --- a/tokenize.h +++ b/tokenize.h @@ -102,6 +102,12 @@ private: void addtoken(const char str[], const unsigned int lineno, const unsigned int fileno); + /** Add braces to an if-block + * @return true if something is modified + * false if nothing is done. + */ + bool simplifyIfAddBraces(); + /** Simplify conditions * @return true if something is modified * false if nothing is done.