Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion lib/checkother.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,30 @@ void CheckOther::suspiciousCaseInSwitchError(const Token* tok, const std::string
"Using an operator like '" + operatorString + "' in a case label is suspicious. Did you intend to use a bitwise operator, multiple case labels or if/else instead?", CWE398, Certainty::inconclusive);
}

static bool isNestedInSwitch(const Scope* scope)
{
while (scope) {
if (scope->type == Scope::ScopeType::eSwitch)
return true;
if (scope->type == Scope::ScopeType::eUnconditional) {
scope = scope->nestedIn;
continue;
}
break;
}
return false;
}

static bool isVardeclInSwitch(const Token* tok)
{
if (!tok)
return false;
if (!isNestedInSwitch(tok->scope()))
return false;
const Token* end = Token::findsimplematch(tok, ";");
return end && end->previous()->variable() && end->previous()->variable()->nameToken() == end->previous();
}

//---------------------------------------------------------------------------
// Find consecutive return, break, continue, goto or throw statements. e.g.:
// break; break;
Expand Down Expand Up @@ -958,7 +982,7 @@ void CheckOther::checkUnreachableCode()
if (silencedWarning)
secondBreak = silencedWarning;

if (!labelInFollowingLoop && !silencedCompilerWarningOnly)
if (!labelInFollowingLoop && !silencedCompilerWarningOnly && !isVardeclInSwitch(secondBreak))
unreachableCodeError(secondBreak, tok, inconclusive);
tok = Token::findmatch(secondBreak, "[}:]");
} else if (secondBreak->scope() && secondBreak->scope()->isLoopScope() && secondBreak->str() == "}" && tok->str() == "continue") {
Expand Down
47 changes: 47 additions & 0 deletions test/testother.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5677,6 +5677,53 @@ class TestOther : public TestFixture {
ASSERT_EQUALS("[test.cpp:6]: (style) Consecutive return, break, continue, goto or throw statements are unnecessary.\n"
"[test.cpp:1]: (style) Parameter 'argv' can be declared as const array\n",
errout_str());

check("int f(int i) {\n" // #13491
" switch (i) {\n"
" case 0:\n"
" return 0;\n"
" int j;\n"
" case 1:\n"
" case 2:\n"
" j = 5;\n"
" return j + i;\n"
" }\n"
" return 3;\n"
"}\n");
ASSERT_EQUALS("", errout_str());

check("int f(int i) {\n"
" switch (i) {\n"
" {\n"
" case 0:\n"
" return 0;\n"
" }\n"
" {\n"
" int j;\n"
" case 1:\n"
" case 2:\n"
" j = 5;\n"
" return j + i;\n"
" }\n"
" }\n"
" return 3;\n"
"}\n");
ASSERT_EQUALS("", errout_str());

check("int f(int i) {\n"
" switch (i) {\n"
" case 0:\n"
" return 0;\n"
" int j;\n"
" dostuff();\n"
" case 1:\n"
" case 2:\n"
" j = 5;\n"
" return j + i;\n"
" }\n"
" return 3;\n"
"}\n");
TODO_ASSERT_EQUALS("[test.cpp:6]: (style) Statements following 'return' will never be executed.\n", "", errout_str());
}

void redundantContinue() {
Expand Down
Loading