Refactorized dead code elimination:

- Use library to get noreturn functions
- Fixed do-while simplification (#4940)
This commit is contained in:
PKEuS 2014-03-23 10:59:41 +01:00
parent 77c17100ec
commit 5f2067e401
3 changed files with 257 additions and 249 deletions

View File

@ -3955,7 +3955,6 @@ void Tokenizer::simplifyFlowControl()
eraseDeadCode(tok, 0);
} else if (Token::Match(tok,"return|goto") ||
Token::Match(tok->previous(), "[;{}] exit (") ||
(Token::Match(tok->previous(), "[;{}] %var% (") &&
_settings->library.isnoreturn(tok->str())) ||
(tok->str() == "throw" && !isC())) {
@ -8146,6 +8145,10 @@ void Tokenizer::eraseDeadCode(Token *begin, const Token *end)
}
tok->deleteNext();
} else { //no need to keep the other strings, remove them.
if (tok->strAt(1) == "while") {
if (tok->str() == "}" && tok->link()->strAt(-1) == "do")
tok->link()->tokAt(-1)->deleteThis();
}
tok->deleteNext();
}
}

View File

@ -183,6 +183,7 @@ private:
TEST_CASE(comparisons);
//remove dead code after flow control statements
TEST_CASE(simplifyFlowControl);
TEST_CASE(flowControl);
// Simplify nested strcat() calls
@ -452,8 +453,6 @@ private:
TEST_CASE(simplifyArrayAddress); // Replace "&str[num]" => "(str + num)"
TEST_CASE(simplifyCharAt);
TEST_CASE(simplifyOverride); // ticket #5069
TEST_CASE(simplifyFlowControl);
}
std::string tok(const char code[], bool simplify = true, Settings::PlatformType type = Settings::Unspecified) {
@ -472,9 +471,7 @@ private:
return tokenizer.tokens()->stringifyList(0, !simplify);
}
std::string tok(const std::string& code, bool simplify = true, Settings::PlatformType type = Settings::Unspecified) {
return tok(code.c_str(), simplify, type);
}
std::string tok(const char code[], const char filename[]) {
errout.str("");
@ -488,6 +485,23 @@ private:
return tokenizer.tokens()->stringifyList(0, false);
}
std::string tokWithStdLib(const char code[]) {
errout.str("");
Settings settings;
if (!settings.library.load("./testrunner", "../cfg/std.cfg") && !settings.library.load("./testrunner", "cfg/std.cfg")) {
complainMissingLib("std.cfg");
return "";
}
Tokenizer tokenizer(&settings, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
tokenizer.simplifyTokenList2();
return tokenizer.tokens()->stringifyList(0, false);
}
std::string tokenizeDebugListing(const std::string &code, bool simplify = false, const char filename[] = "test.cpp") {
errout.str("");
@ -3143,38 +3157,49 @@ private:
ASSERT_EQUALS("( 6 )", tok("( 1 > 2 && 3 > 4 ? 5 : 6 )"));
}
void simplifyFlowControl() {
const char code1[] = "void f() {\n"
" return;\n"
" y();\n"
"}";
ASSERT_EQUALS("void f ( ) { return ; }", tokWithStdLib(code1));
const char code2[] = "void f() {\n"
" exit();\n"
" y();\n"
"}";
ASSERT_EQUALS("void f ( ) { exit ( ) ; }", tokWithStdLib(code2));
const char code3[] = "void f() {\n"
" x.abort();\n"
" y();\n"
"}";
ASSERT_EQUALS("void f ( ) { x . abort ( ) ; y ( ) ; }", tokWithStdLib(code3));
}
void flowControl() {
std::list<std::string> beforedead;
//beforedead.push_back("return");
//beforedead.push_back("throw ( 10 )");
beforedead.push_back("exit ( 0 )");
//beforedead.push_back("abort ( )");
//beforedead.push_back("goto labels");
//beforedead.push_back("break");
//beforedead.push_back("continue");
for (std::list<std::string>::iterator it = beforedead.begin(); it != beforedead.end(); ++it) {
{
ASSERT_EQUALS("void f ( ) { " + *it + " ; }", tok("void f() { " + *it + "; foo(); }"));
ASSERT_EQUALS("void f ( ) { " + *it + " ; }", tok("void f() { " + *it + "; if (m) foo(); }"));
ASSERT_EQUALS("void f ( int n ) { if ( n ) { " + *it + " ; } foo ( ) ; }",tok("void f(int n) { if (n) { " + *it + "; } foo(); }"));
ASSERT_EQUALS("void f ( ) { " + *it + " ; }", tok("void f() { " + *it + "; dead(); switch (n) { case 1: deadcode () ; default: deadcode (); } }"));
ASSERT_EQUALS("void f ( ) { exit ( 0 ) ; }", tokWithStdLib("void f() { exit(0); foo(); }"));
ASSERT_EQUALS("void f ( ) { exit ( 0 ) ; }", tokWithStdLib("void f() { exit(0); if (m) foo(); }"));
ASSERT_EQUALS("void f ( int n ) { if ( n ) { exit ( 0 ) ; } foo ( ) ; }", tokWithStdLib("void f(int n) { if (n) { exit(0); } foo(); }"));
ASSERT_EQUALS("void f ( ) { exit ( 0 ) ; }", tokWithStdLib("void f() { exit(0); dead(); switch (n) { case 1: deadcode () ; default: deadcode (); } }"));
ASSERT_EQUALS("int f ( int n ) { switch ( n ) { case 0 : ; " + *it + " ; default : ; " + *it + " ; } " + *it + " ; }",
tok("int f(int n) { switch (n) {case 0: " + *it + "; n*=2; default: " + *it + "; n*=6;} " + *it + "; foo();}"));
ASSERT_EQUALS("int f ( int n ) { switch ( n ) { case 0 : ; exit ( 0 ) ; default : ; exit ( 0 ) ; } exit ( 0 ) ; }",
tokWithStdLib("int f(int n) { switch (n) {case 0: exit(0); n*=2; default: exit(0); n*=6;} exit(0); foo();}"));
//ticket #3132
ASSERT_EQUALS("void f ( int i ) { goto label ; { label : ; " + *it + " ; } }",tok("void f (int i) { goto label; switch(i) { label: " + *it + "; } }"));
ASSERT_EQUALS("void f ( int i ) { goto label ; { label : ; exit ( 0 ) ; } }", tokWithStdLib("void f (int i) { goto label; switch(i) { label: exit(0); } }"));
//ticket #3148
ASSERT_EQUALS("void f ( ) { MACRO ( " + *it + " ) }",tok("void f() { MACRO(" + *it + ") }"));
ASSERT_EQUALS("void f ( ) { MACRO ( " + *it + " ; , NULL ) }",tok("void f() { MACRO(" + *it + ";, NULL) }"));
ASSERT_EQUALS("void f ( ) { MACRO ( bar1 , " + *it + " ) }",tok("void f() { MACRO(bar1, " + *it + ") }"));
ASSERT_EQUALS("void f ( ) { MACRO ( " + *it + " ; bar2 , foo ) }",tok("void f() { MACRO(" + *it + "; bar2, foo) }"));
ASSERT_EQUALS("void f ( ) { MACRO ( exit ( 0 ) ) }", tokWithStdLib("void f() { MACRO(exit(0)) }"));
ASSERT_EQUALS("void f ( ) { MACRO ( exit ( 0 ) ; , NULL ) }", tokWithStdLib("void f() { MACRO(exit(0);, NULL) }"));
ASSERT_EQUALS("void f ( ) { MACRO ( bar1 , exit ( 0 ) ) }", tokWithStdLib("void f() { MACRO(bar1, exit(0)) }"));
ASSERT_EQUALS("void f ( ) { MACRO ( exit ( 0 ) ; bar2 , foo ) }", tokWithStdLib("void f() { MACRO(exit(0); bar2, foo) }"));
}
{
std::string code = "void f(){ "
const char* code = "void f(){ "
" if (k>0) goto label; "
" " + *it + "; "
" exit(0); "
" if (tnt) "
" { "
" { "
@ -3185,12 +3210,12 @@ private:
" bar(); "
" } "
"}";
ASSERT_EQUALS("void f ( ) { if ( k > 0 ) { goto label ; } " + *it + " ; { label : ; bar ( ) ; } }",tok(code));
ASSERT_EQUALS("void f ( ) { if ( k > 0 ) { goto label ; } exit ( 0 ) ; { label : ; bar ( ) ; } }", tokWithStdLib(code));
}
{
std::string code = "void foo () {"
" " + *it + ";"
const char* code = "void foo () {"
" exit(0);"
" {"
" boo();"
" while (n) { --n; }"
@ -3200,12 +3225,12 @@ private:
" }"
" }"
"}";
ASSERT_EQUALS("void foo ( ) { " + *it + " ; { label : ; ok ( ) ; } }", tok(code));
ASSERT_EQUALS("void foo ( ) { exit ( 0 ) ; { label : ; ok ( ) ; } }", tokWithStdLib(code));
}
{
std::string code = "void foo () {"
" " + *it + ";"
const char* code = "void foo () {"
" exit(0);"
" switch (n) {"
" case 1:"
" label:"
@ -3214,13 +3239,13 @@ private:
" break;"
" }"
"}";
std::string expected = "void foo ( ) { " + *it + " ; { label : ; foo ( ) ; break ; } }";
ASSERT_EQUALS(expected, tok(code));
const char* expected = "void foo ( ) { exit ( 0 ) ; { label : ; foo ( ) ; break ; } }";
ASSERT_EQUALS(expected, tokWithStdLib(code));
}
{
std::string code = "void foo () {"
" " + *it + ";"
const char* code = "void foo () {"
" exit(0);"
" switch (n) {"
" case 1:"
" {"
@ -3230,13 +3255,13 @@ private:
" bar();"
" }"
"}";
std::string expected = "void foo ( ) { " + *it + " ; { label : ; bar ( ) ; } }";
ASSERT_EQUALS(expected, tok(code));
const char* expected = "void foo ( ) { exit ( 0 ) ; { label : ; bar ( ) ; } }";
ASSERT_EQUALS(expected, tokWithStdLib(code));
}
{
std::string code = "void foo () {"
" " + *it + ";"
const char* code = "void foo () {"
" exit(0);"
" switch (n) {"
" case a:"
" {"
@ -3246,13 +3271,13 @@ private:
" bar();"
" }"
"}";
std::string expected = "void foo ( ) { " + *it + " ; }";
ASSERT_EQUALS(expected, tok(code));
const char* expected = "void foo ( ) { exit ( 0 ) ; }";
ASSERT_EQUALS(expected, tokWithStdLib(code));
}
{
std::string code = "void foo () {"
" " + *it + ";"
const char* code = "void foo () {"
" exit(0);"
" switch (n) {"
" case 1:"
" label:"
@ -3261,13 +3286,13 @@ private:
" break; break;"
" }"
"}";
std::string expected = "void foo ( ) { " + *it + " ; { label : ; foo ( ) ; break ; } }";
ASSERT_EQUALS(expected, tok(code));
const char* expected = "void foo ( ) { exit ( 0 ) ; { label : ; foo ( ) ; break ; } }";
ASSERT_EQUALS(expected, tokWithStdLib(code));
}
{
std::string code = "void foo () {"
" " + *it + ";"
const char* code = "void foo () {"
" exit(0);"
" switch (n) {"
" case 1:"
" label:"
@ -3276,13 +3301,13 @@ private:
" break;"
" }"
"}";
std::string expected = "void foo ( ) { " + *it + " ; { label : ; foo ( ) ; break ; } }";
ASSERT_EQUALS(expected, tok(code));
const char* expected = "void foo ( ) { exit ( 0 ) ; { label : ; foo ( ) ; break ; } }";
ASSERT_EQUALS(expected, tokWithStdLib(code));
}
{
std::string code = "void foo () {"
" " + *it + ";"
const char* code = "void foo () {"
" exit(0);"
" switch (n) {"
" case 1:"
" label:"
@ -3291,79 +3316,78 @@ private:
" break; break;"
" }"
"}";
std::string expected = "void foo ( ) { " + *it + " ; { label : ; foo ( ) ; break ; } }";
ASSERT_EQUALS(expected, tok(code));
const char* expected = "void foo ( ) { exit ( 0 ) ; { label : ; foo ( ) ; break ; } }";
ASSERT_EQUALS(expected, tokWithStdLib(code));
}
{
std::string code = "int f() { "
"switch (x) { case 1: " + *it + "; bar(); tack; { ticak(); " + *it + " } " + *it + ";"
"case 2: " + *it + "; { random(); } tack(); "
"switch(y) { case 1: " + *it + "; case 2: " + *it + "; } "
"" + *it + "; } " + *it + "; }";
ASSERT_EQUALS("int f ( ) { switch ( x ) { case 1 : ; " + *it + " ; case 2 : ; " + *it + " ; } " + *it + " ; }",tok(code));
const char* code = "int f() { "
"switch (x) { case 1: exit(0); bar(); tack; { ticak(); exit(0) } exit(0);"
"case 2: exit(0); { random(); } tack(); "
"switch(y) { case 1: exit(0); case 2: exit(0); } "
"exit(0); } exit(0); }";
ASSERT_EQUALS("int f ( ) { switch ( x ) { case 1 : ; exit ( 0 ) ; case 2 : ; exit ( 0 ) ; } exit ( 0 ) ; }",tokWithStdLib(code));
}
{
std::string code = "int f() {"
"switch (x) { case 1: " + *it + "; bar(); tack; { ticak(); " + *it + "; } " + *it + ";"
"case 2: switch(y) { case 1: " + *it + "; bar2(); foo(); case 2: " + *it + "; }"
"" + *it + "; } " + *it + "; }";
std::string expected = "int f ( ) {"
" switch ( x ) { case 1 : ; " + *it + " ;"
" case 2 : ; switch ( y ) { case 1 : ; " + *it + " ; case 2 : ; " + *it + " ; }"
" " + *it + " ; } " + *it + " ; }";
ASSERT_EQUALS(expected,tok(code));
const char* code = "int f() {"
"switch (x) { case 1: exit(0); bar(); tack; { ticak(); exit(0); } exit(0);"
"case 2: switch(y) { case 1: exit(0); bar2(); foo(); case 2: exit(0); }"
"exit(0); } exit(0); }";
const char* expected = "int f ( ) {"
" switch ( x ) { case 1 : ; exit ( 0 ) ;"
" case 2 : ; switch ( y ) { case 1 : ; exit ( 0 ) ; case 2 : ; exit ( 0 ) ; }"
" exit ( 0 ) ; } exit ( 0 ) ; }";
ASSERT_EQUALS(expected,tokWithStdLib(code));
}
{
std::string code = "void foo () {"
" switch (i) { case 0: switch (j) { case 0: " + *it + "; }"
" case 1: switch (j) { case -1: " + *it + "; }"
" case 2: switch (j) { case -2: " + *it + "; }"
" case 3: if (blah6) {" + *it + ";} break; } }";
std::string expected = "void foo ( ) {"
" switch ( i ) { case 0 : ; switch ( j ) { case 0 : ; " + *it + " ; }"
" case 1 : ; switch ( j ) { case -1 : ; " + *it + " ; }"
" case 2 : ; switch ( j ) { case -2 : ; " + *it + " ; }"
" case 3 : ; if ( blah6 ) { " + *it + " ; } break ; } }";
ASSERT_EQUALS(expected, tok(code));
const char* code = "void foo () {"
" switch (i) { case 0: switch (j) { case 0: exit(0); }"
" case 1: switch (j) { case -1: exit(0); }"
" case 2: switch (j) { case -2: exit(0); }"
" case 3: if (blah6) {exit(0);} break; } }";
const char* expected = "void foo ( ) {"
" switch ( i ) { case 0 : ; switch ( j ) { case 0 : ; exit ( 0 ) ; }"
" case 1 : ; switch ( j ) { case -1 : ; exit ( 0 ) ; }"
" case 2 : ; switch ( j ) { case -2 : ; exit ( 0 ) ; }"
" case 3 : ; if ( blah6 ) { exit ( 0 ) ; } break ; } }";
ASSERT_EQUALS(expected, tokWithStdLib(code));
}
{
std::string code = "void foo () {"
" " + *it + ";"
const char* code = "void foo () {"
" exit(0);"
" switch (i) { case 0: switch (j) { case 0: foo(); }"
" case 1: switch (j) { case -1: bar(); label:; ok(); }"
" case 3: if (blah6) { boo(); break; } } }";
std::string expected = "void foo ( ) { " + *it + " ; { { label : ; ok ( ) ; } case 3 : ; if ( blah6 ) { boo ( ) ; break ; } } }";
ASSERT_EQUALS(expected, tok(code));
const char* expected = "void foo ( ) { exit ( 0 ) ; { { label : ; ok ( ) ; } case 3 : ; if ( blah6 ) { boo ( ) ; break ; } } }";
ASSERT_EQUALS(expected, tokWithStdLib(code));
}
{
std::string code = "void foo() {"
const char* code = "void foo() {"
" switch ( t ) {"
" case 0:"
" if ( t ) switch ( b ) {}"
" break;"
" case 1:"
" " + *it + ";"
" exit(0);"
" return 0;"
" }"
" return 0;"
"}";
std::string expected = "void foo ( ) {"
const char* expected = "void foo ( ) {"
" switch ( t ) {"
" case 0 : ;"
" if ( t ) { switch ( b ) { } }"
" break ;"
" case 1 : ;"
" " + *it + " ;"
" exit ( 0 ) ;"
" }"
" return 0 ; "
"}";
ASSERT_EQUALS(expected, tok(code));
}
ASSERT_EQUALS(expected, tokWithStdLib(code));
}
{
@ -3385,7 +3409,7 @@ private:
" return ;"
" } "
"}";
ASSERT_EQUALS(expected, tok(code));
ASSERT_EQUALS(expected, tokWithStdLib(code));
}
{
@ -3407,7 +3431,7 @@ private:
" private:"
" bool f ; "
"} ;";
ASSERT_EQUALS(expected, tok(code));
ASSERT_EQUALS(expected, tokWithStdLib(code));
}
{
@ -3432,8 +3456,11 @@ private:
" private:"
" bool f ; "
"} ;";
ASSERT_EQUALS(expected, tok(code));
ASSERT_EQUALS(expected, tokWithStdLib(code));
}
ASSERT_EQUALS("void foo ( ) { exit ( 0 ) ; }",
tokWithStdLib("void foo() { do { exit(0); } while (true); }"));
}
void strcat1() {
@ -7951,26 +7978,6 @@ private:
ASSERT_EQUALS("void fun ( ) { char override [ 2 ] = { 1 , 2 } ; doSomething ( override , 2 ) ; }",
tok(code, true));
}
void simplifyFlowControl() {
const char code1[] = "void f() {\n"
" return;\n"
" y();\n"
"}";
ASSERT_EQUALS("void f ( ) { return ; }", tok(code1,true));
const char code2[] = "void f() {\n"
" exit();\n"
" y();\n"
"}";
ASSERT_EQUALS("void f ( ) { exit ( ) ; }", tok(code2,true));
const char code3[] = "void f() {\n"
" x.abort();\n"
" y();\n"
"}";
ASSERT_EQUALS("void f ( ) { x . abort ( ) ; y ( ) ; }", tok(code3,true));
}
};
REGISTER_TEST(TestSimplifyTokens)

View File

@ -3133,11 +3133,9 @@ private:
checkUninitVar2("void f() {\n" // #4911 - bad simplification => don't crash
" int a;\n"
" do { } a=do_something(); while (a);\n"
" do { a=do_something() } while (a);\n"
"}\n", "test.cpp", /*verify=*/true, /*debugwarnings=*/true);
ASSERT_EQUALS("[test.cpp:3]: (debug) ValueFlow bailout: assignment of a\n"
"[test.cpp:3]: (error) Uninitialized variable: a\n"
"[test.cpp:3]: (debug) assertion failed '} while ('\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (debug) ValueFlow bailout: variable a stopping on }\n", errout.str());
checkUninitVar2("void f() {\n"
" int x;\n"