Fix #3457 (Statement following goto can be executed)
http://sourceforge.net/apps/trac/cppcheck/ticket/3457
This commit is contained in:
parent
38e0e25ce0
commit
3d0c1a3301
|
@ -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;
|
||||||
|
|
|
@ -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.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue