Fixed #2822 (New check: Duplicate break statements in switch)

This commit is contained in:
Zachary Blair 2011-07-14 17:12:56 -07:00
parent 270b2b1772
commit 997a3652d2
3 changed files with 111 additions and 0 deletions

View File

@ -867,6 +867,35 @@ void CheckOther::checkComparisonOfBoolWithInt()
}
}
//---------------------------------------------------------------------------
// switch (x)
// {
// case 2:
// y = a;
// break;
// break; // <- Redundant break
// case 3:
// y = b;
// }
//---------------------------------------------------------------------------
void CheckOther::checkDuplicateBreak()
{
if (!_settings->_checkCodingStyle)
return;
const char breakPattern[] = "break|continue ; break|continue ;";
// Find consecutive break or continue statements. e.g.:
// break; break;
const Token *tok = Token::findmatch(_tokenizer->tokens(), breakPattern);
while (tok)
{
duplicateBreakError(tok);
tok = Token::findmatch(tok->next(), breakPattern);
}
}
void CheckOther::sizeofForNumericParameterError(const Token *tok)
{
reportError(tok, Severity::error,
@ -3694,3 +3723,10 @@ void CheckOther::comparisonOfBoolWithIntError(const Token *tok, const std::strin
"Comparison of a boolean with a non-zero integer\n"
"The expression \"!" + varname + "\" is of type 'bool' but is compared against a non-zero 'int'.");
}
void CheckOther::duplicateBreakError(const Token *tok)
{
reportError(tok, Severity::style, "duplicateBreak",
"Consecutive break or continue statements are unnecessary\n"
"The second of the two statements can never be executed, and so should be removed\n");
}

View File

@ -67,6 +67,7 @@ public:
checkOther.checkDuplicateIf();
checkOther.checkDuplicateBranch();
checkOther.checkDuplicateExpression();
checkOther.checkDuplicateBreak();
// information checks
checkOther.checkVariableScope();
@ -224,9 +225,13 @@ public:
/** @brief %Check for suspicious code that compares string literals for equality */
void checkAlwaysTrueOrFalseStringCompare();
/** @brief %Check for duplicate break statements in a switch or loop */
void checkDuplicateBreak();
/** @brief check if token is a record type without side effects */
bool isRecordTypeWithoutSideEffects(const Token *tok);
// Error messages..
void cstyleCastError(const Token *tok);
void dangerousUsageStrtolError(const Token *tok);
@ -260,6 +265,7 @@ public:
void duplicateBranchError(const Token *tok1, const Token *tok2);
void duplicateExpressionError(const Token *tok1, const Token *tok2, const std::string &op);
void alwaysTrueFalseStringCompare(const Token *tok, const std::string& str1, const std::string& str2);
void duplicateBreakError(const Token *tok);
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings)
{
@ -309,6 +315,7 @@ public:
c.duplicateBranchError(0, 0);
c.duplicateExpressionError(0, 0, "&&");
c.alwaysTrueFalseStringCompare(0, "str1", "str2");
c.duplicateBreakError(0);
}
std::string myName() const
@ -354,6 +361,7 @@ public:
"* comparison of a boolean with a non-zero integer\n"
"* suspicious condition (assignment+comparison)\n"
"* suspicious condition (runtime comparison of string literals)\n"
"* duplicate break statement\n"
// optimisations
"* optimisation: detect post increment/decrement\n";

View File

@ -77,6 +77,7 @@ private:
TEST_CASE(switchRedundantAssignmentTest);
TEST_CASE(switchFallThroughCase);
TEST_CASE(duplicateBreak);
TEST_CASE(selfAssignment);
TEST_CASE(testScanf1);
@ -166,6 +167,7 @@ private:
checkOther.checkIncorrectStringCompare();
checkOther.checkIncrementBoolean();
checkOther.checkComparisonOfBoolWithInt();
checkOther.checkDuplicateBreak();
}
class SimpleSuppressor: public ErrorLogger
@ -1558,6 +1560,71 @@ private:
ASSERT_EQUALS("", errout.str());
}
void duplicateBreak()
{
check("void foo(int a)\n"
"{\n"
" switch(a) {\n"
" case 0:\n"
" printf(\"case 0\");\n"
" break;\n"
" break;\n"
" case 1:\n"
" c++;\n"
" break;\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:6]: (style) Consecutive break or continue statements are unnecessary\n", errout.str());
check("void foo(int a)\n"
"{\n"
" switch(a) {\n"
" case 0:\n"
" printf(\"case 0\");\n"
" break;\n"
" case 1:\n"
" c++;\n"
" break;\n"
" }\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("void foo(int a)\n"
"{\n"
" while(1) {\n"
" if (a++ >= 100) {\n"
" break;\n"
" break;\n"
" }\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:5]: (style) Consecutive break or continue statements are unnecessary\n", errout.str());
check("void foo(int a)\n"
"{\n"
" while(1) {\n"
" if (a++ >= 100) {\n"
" continue;\n"
" continue;\n"
" }\n"
" a+=2;\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:5]: (style) Consecutive break or continue statements are unnecessary\n", errout.str());
check("void foo(int a)\n"
"{\n"
" while(1) {\n"
" if (a++ >= 100) {\n"
" continue;\n"
" }\n"
" a+=2;\n"
" }\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void selfAssignment()
{
check("void foo()\n"