Skip to content

Commit a219774

Browse files
Fix #13491 FP unreachableCode for declaration in switch (danmar#7194)
1 parent ed38aee commit a219774

File tree

2 files changed

+72
-1
lines changed

2 files changed

+72
-1
lines changed

lib/checkother.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,30 @@ void CheckOther::suspiciousCaseInSwitchError(const Token* tok, const std::string
851851
"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);
852852
}
853853

854+
static bool isNestedInSwitch(const Scope* scope)
855+
{
856+
while (scope) {
857+
if (scope->type == Scope::ScopeType::eSwitch)
858+
return true;
859+
if (scope->type == Scope::ScopeType::eUnconditional) {
860+
scope = scope->nestedIn;
861+
continue;
862+
}
863+
break;
864+
}
865+
return false;
866+
}
867+
868+
static bool isVardeclInSwitch(const Token* tok)
869+
{
870+
if (!tok)
871+
return false;
872+
if (!isNestedInSwitch(tok->scope()))
873+
return false;
874+
const Token* end = Token::findsimplematch(tok, ";");
875+
return end && end->previous()->variable() && end->previous()->variable()->nameToken() == end->previous();
876+
}
877+
854878
//---------------------------------------------------------------------------
855879
// Find consecutive return, break, continue, goto or throw statements. e.g.:
856880
// break; break;
@@ -958,7 +982,7 @@ void CheckOther::checkUnreachableCode()
958982
if (silencedWarning)
959983
secondBreak = silencedWarning;
960984

961-
if (!labelInFollowingLoop && !silencedCompilerWarningOnly)
985+
if (!labelInFollowingLoop && !silencedCompilerWarningOnly && !isVardeclInSwitch(secondBreak))
962986
unreachableCodeError(secondBreak, tok, inconclusive);
963987
tok = Token::findmatch(secondBreak, "[}:]");
964988
} else if (secondBreak->scope() && secondBreak->scope()->isLoopScope() && secondBreak->str() == "}" && tok->str() == "continue") {

test/testother.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5677,6 +5677,53 @@ class TestOther : public TestFixture {
56775677
ASSERT_EQUALS("[test.cpp:6]: (style) Consecutive return, break, continue, goto or throw statements are unnecessary.\n"
56785678
"[test.cpp:1]: (style) Parameter 'argv' can be declared as const array\n",
56795679
errout_str());
5680+
5681+
check("int f(int i) {\n" // #13491
5682+
" switch (i) {\n"
5683+
" case 0:\n"
5684+
" return 0;\n"
5685+
" int j;\n"
5686+
" case 1:\n"
5687+
" case 2:\n"
5688+
" j = 5;\n"
5689+
" return j + i;\n"
5690+
" }\n"
5691+
" return 3;\n"
5692+
"}\n");
5693+
ASSERT_EQUALS("", errout_str());
5694+
5695+
check("int f(int i) {\n"
5696+
" switch (i) {\n"
5697+
" {\n"
5698+
" case 0:\n"
5699+
" return 0;\n"
5700+
" }\n"
5701+
" {\n"
5702+
" int j;\n"
5703+
" case 1:\n"
5704+
" case 2:\n"
5705+
" j = 5;\n"
5706+
" return j + i;\n"
5707+
" }\n"
5708+
" }\n"
5709+
" return 3;\n"
5710+
"}\n");
5711+
ASSERT_EQUALS("", errout_str());
5712+
5713+
check("int f(int i) {\n"
5714+
" switch (i) {\n"
5715+
" case 0:\n"
5716+
" return 0;\n"
5717+
" int j;\n"
5718+
" dostuff();\n"
5719+
" case 1:\n"
5720+
" case 2:\n"
5721+
" j = 5;\n"
5722+
" return j + i;\n"
5723+
" }\n"
5724+
" return 3;\n"
5725+
"}\n");
5726+
TODO_ASSERT_EQUALS("[test.cpp:6]: (style) Statements following 'return' will never be executed.\n", "", errout_str());
56805727
}
56815728

56825729
void redundantContinue() {

0 commit comments

Comments
 (0)