diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index e9463383f..95466dd00 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -4383,7 +4383,7 @@ void Tokenizer::simplifyDeadCode() } else if (Token::Match(tok2, "[{}]")) break; //bad code } - } else if (tok->str()=="return") { + } else if (Token::Match(tok,"return|goto|continue|break")) { if (!indentlevel) break; @@ -4391,6 +4391,14 @@ void Tokenizer::simplifyDeadCode() if (roundbraces) continue; + if (Token::Match(tok,"continue|break ;")) { + indentret = indentlevel; + if (Token::Match(tok->tokAt(2),"continue|break ;")) { + tok = tok->tokAt(3); + continue; + } + } + //catch the first ';' after the return unsigned int returnroundbraces = 0; for (Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) { diff --git a/lib/tokenize.h b/lib/tokenize.h index 45de86e94..f92e8a860 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -197,12 +197,6 @@ public: /** Remove redundant assignment */ void removeRedundantAssignment(); - /** - * Remove redudant code placed after 'return ;' code. - * @todo Extend the functionality to code after 'break;' and 'continue;' code - */ - void simplifyDeadCode(); - /** * Replace sizeof() to appropriate size. */ @@ -343,6 +337,11 @@ public: /** Replace a "goto" with the statements */ void simplifyGoto(); + /** Simplify redundant code placed after control flow statements : + * 'return', 'goto', 'break' and 'continue' + */ + void simplifyDeadCode(); + /** Expand nested strcat() calls. */ void simplifyNestedStrcat(); diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 1795c827c..3a765706f 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -155,13 +155,19 @@ private: TEST_CASE(goto1); TEST_CASE(goto2); - //remove redundant code after the 'return ;' statement + //remove redundant code after flow control statements TEST_CASE(return1); TEST_CASE(return2); TEST_CASE(return3); TEST_CASE(return4); TEST_CASE(return5); + TEST_CASE(break1); + TEST_CASE(break2); + + TEST_CASE(continue1); + TEST_CASE(continue2); + // Simplify nested strcat() calls TEST_CASE(strcat1); TEST_CASE(strcat2); @@ -2896,7 +2902,7 @@ private: ASSERT_EQUALS("int f ( int n ) { switch ( n ) { case 0 : ; return 0 ; default : ; return n ; } return -1 ; }", tok("int f(int n) { switch (n) {case 0: return 0; n*=2; default: return n; n*=6;} return -1; foo();}")); //ticket #3132 - ASSERT_EQUALS("void f ( int i ) { goto label ; switch ( i ) { label : ; return ; } }",tok("void f (int i) { goto label; switch(i) { label: return; } }")); + ASSERT_EQUALS("void f ( int i ) { goto label ; { label : ; return ; } }",tok("void f (int i) { goto label; switch(i) { label: return; } }")); //ticket #3148 ASSERT_EQUALS("void f ( ) { MACRO ( return 0 ) }",tok("void f() { MACRO(return NULL) }")); ASSERT_EQUALS("void f ( ) { MACRO ( return ; , 0 ) }",tok("void f() { MACRO(return;, NULL) }")); @@ -2956,6 +2962,72 @@ private: ASSERT_EQUALS(expected, tok(code)); } + void break1() { + ASSERT_EQUALS("void f ( ) { int i ; for ( i = 0 ; i < 10 ; i ++ ) { foo ( i ) ; break ; } }", tok("void f() { int i; for (i=0; i<10; i++) { foo(i); break; bar1(); } }")); + ASSERT_EQUALS("void f ( int n ) { int i ; for ( i = 0 ; i < 10 ; i ++ ) { if ( n ) { break ; } foo ( ) ; } }",tok("void f(int n) { int i; for(i=0; i<10; i++) { if (n) break; foo();}}")); + + ASSERT_EQUALS("int f ( int n ) { switch ( n ) { case 0 : ; break ; default : ; break ; } }", + tok("int f(int n) { switch (n) {case 0: break; n*=2; default: break; n*=6;}}")); + + ASSERT_EQUALS("void f ( ) { MACRO ( break ) }",tok("void f() { MACRO(break) }")); + ASSERT_EQUALS("void f ( ) { MACRO ( break ; , 0 ) }",tok("void f() { MACRO(break;, NULL) }")); + ASSERT_EQUALS("void f ( ) { MACRO ( bar1 , break ) }",tok("void f() { MACRO(bar1, break) }")); + ASSERT_EQUALS("void f ( ) { MACRO ( break ; bar2 , foo ) }",tok("void f() { MACRO(break; bar2, foo) }")); + } + + void break2() { + const char code[] = "void f()" + "{ " + " while(tnt) " + " { " + " --tnt; " + " if (k>0) goto label; " + " break; " + " if (tnt) " + " { " + " { " + " check(); " + " k=0; " + " } " + " label: " + " bar(); " + " } " + " } " + "}"; + ASSERT_EQUALS("void f ( ) { while ( tnt ) { -- tnt ; if ( 0 < k ) { goto label ; } break ; { label : ; bar ( ) ; } } }",tok(code)); + } + + void continue1() { + ASSERT_EQUALS("void f ( int n ) { int i ; for ( i = 0 ; i < 10 ; i ++ ) { if ( n ) { continue ; } foo ( ) ; } }",tok("void f(int n) { int i; for(i=0; i<10; i++) { if (n) continue; foo();}}")); + + ASSERT_EQUALS("void f ( ) { MACRO ( continue ) }",tok("void f() { MACRO(continue) }")); + ASSERT_EQUALS("void f ( ) { MACRO ( continue ; , 0 ) }",tok("void f() { MACRO(continue;, NULL) }")); + ASSERT_EQUALS("void f ( ) { MACRO ( bar1 , continue ) }",tok("void f() { MACRO(bar1, continue) }")); + ASSERT_EQUALS("void f ( ) { MACRO ( continue ; bar2 , foo ) }",tok("void f() { MACRO(continue; bar2, foo) }")); + } + + void continue2() { + const char code[] = "void f()" + "{ " + " while(tnt) " + " { " + " --tnt; " + " if (k>0) goto label; " + " continue; " + " if (tnt) " + " { " + " { " + " check(); " + " k=0; " + " } " + " label: " + " bar(); " + " } " + " } " + "}"; + ASSERT_EQUALS("void f ( ) { while ( tnt ) { -- tnt ; if ( 0 < k ) { goto label ; } continue ; { label : ; bar ( ) ; } } }",tok(code)); + } + void strcat1() { const char code[] = "; strcat(strcat(strcat(strcat(strcat(strcat(dst, \"this \"), \"\"), \"is \"), \"a \"), \"test\"), \".\");"; const char expect[] = "; "