Fix #3457 (Statement following goto can be executed)

http://sourceforge.net/apps/trac/cppcheck/ticket/3457
This commit is contained in:
Erik Lax 2012-01-01 00:11:03 +02:00 committed by Reijo Tomperi
parent 38e0e25ce0
commit 3d0c1a3301
2 changed files with 47 additions and 2 deletions

View File

@ -1591,6 +1591,7 @@ void CheckOther::checkUnreachableCode()
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
const Token* secondBreak = 0; const Token* secondBreak = 0;
const Token* labelName = 0;
if (tok->str() == "(") if (tok->str() == "(")
tok = tok->link(); tok = tok->link();
else if (Token::Match(tok, "break|continue ;")) else if (Token::Match(tok, "break|continue ;"))
@ -1602,8 +1603,10 @@ void CheckOther::checkUnreachableCode()
secondBreak = tok2->next(); secondBreak = tok2->next();
break; break;
} }
} else if (Token::Match(tok, "goto %any% ;")) } else if (Token::Match(tok, "goto %any% ;")) {
secondBreak = tok->tokAt(3); secondBreak = tok->tokAt(3);
labelName = tok->tokAt(1);
}
if (secondBreak) { if (secondBreak) {
if (Token::Match(secondBreak, "continue|goto|throw") || if (Token::Match(secondBreak, "continue|goto|throw") ||
@ -1630,7 +1633,22 @@ void CheckOther::checkUnreachableCode()
} }
tok = Token::findmatch(secondBreak, "[}:]"); tok = Token::findmatch(secondBreak, "[}:]");
} else if (!Token::Match(secondBreak, "return|}|case|default") && secondBreak->strAt(1) != ":") { // TODO: No bailout for unconditional scopes } else if (!Token::Match(secondBreak, "return|}|case|default") && secondBreak->strAt(1) != ":") { // TODO: No bailout for unconditional scopes
unreachableCodeError(secondBreak); // If the goto label is followed by a loop construct in which the label is defined it's quite likely
// that the goto jump was intended to skip some code on the first loop iteration.
bool labelInFollowingLoop = false;
if (labelName && Token::Match(secondBreak, "while|do|for")) {
const Token *scope = Token::findmatch(secondBreak, "{");
if (scope) {
for (const Token *tokIter = scope; tokIter != scope->link() && tokIter; tokIter = tokIter->next()) {
if (Token::Match(tokIter, "[;{}] %any% :") && labelName->str() == tokIter->strAt(1)) {
labelInFollowingLoop = true;
break;
}
}
}
}
if (!labelInFollowingLoop)
unreachableCodeError(secondBreak);
tok = Token::findmatch(secondBreak, "[}:]"); tok = Token::findmatch(secondBreak, "[}:]");
} else } else
tok = secondBreak; tok = secondBreak;

View File

@ -1919,6 +1919,33 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("int foo() {\n"
" goto label;\n"
" while (true) {\n"
" bar();\n"
" label:\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str()); // #3457
check("int foo() {\n"
" goto label;\n"
" do {\n"
" bar();\n"
" label:\n"
" } while (true);\n"
"}");
ASSERT_EQUALS("", errout.str()); // #3457
check("int foo() {\n"
" goto label;\n"
" for (;;) {\n"
" bar();\n"
" label:\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str()); // #3457
check("%: return ; ()"); // Don't crash. #3441. check("%: return ; ()"); // Don't crash. #3441.
} }