diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 3e243a138..b9796268b 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -829,6 +829,9 @@ void CheckOther::checkUnreachableCode() if (!labelInFollowingLoop && !silencedCompilerWarningOnly) unreachableCodeError(secondBreak, inconclusive); tok = Token::findmatch(secondBreak, "[}:]"); + } else if (secondBreak->scope() && secondBreak->scope()->isLoopScope() && secondBreak->str() == "}" && tok->str() == "continue") { + redundantContinueError(tok); + tok = secondBreak; } else tok = secondBreak; @@ -854,6 +857,12 @@ void CheckOther::unreachableCodeError(const Token *tok, bool inconclusive) "Statements following return, break, continue, goto or throw will never be executed.", CWE561, inconclusive ? Certainty::inconclusive : Certainty::normal); } +void CheckOther::redundantContinueError(const Token *tok) +{ + reportError(tok, Severity::style, "redundantContinue", + "'continue' is redundant since it is the last statement in a loop.", CWE561, Certainty::normal); +} + //--------------------------------------------------------------------------- // Check scope of variables.. //--------------------------------------------------------------------------- diff --git a/lib/checkother.h b/lib/checkother.h index 8ef99473a..584af1d30 100644 --- a/lib/checkother.h +++ b/lib/checkother.h @@ -260,6 +260,7 @@ private: void duplicateExpressionTernaryError(const Token *tok, ErrorPath errors); void duplicateBreakError(const Token *tok, bool inconclusive); void unreachableCodeError(const Token* tok, bool inconclusive); + void redundantContinueError(const Token* tok); void unsignedLessThanZeroError(const Token *tok, const ValueFlow::Value *v, const std::string &varname); void pointerLessThanZeroError(const Token *tok, const ValueFlow::Value *v); void unsignedPositiveError(const Token *tok, const ValueFlow::Value *v, const std::string &varname); diff --git a/test/testother.cpp b/test/testother.cpp index a2f734777..63fd58d32 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -117,6 +117,7 @@ private: TEST_CASE(switchRedundantOperationTest); TEST_CASE(switchRedundantBitwiseOperationTest); TEST_CASE(unreachableCode); + TEST_CASE(redundantContinue); TEST_CASE(suspiciousCase); TEST_CASE(suspiciousEqualityComparison); @@ -4449,6 +4450,26 @@ private: ASSERT_EQUALS("", errout.str()); } + void redundantContinue() { + check("void f() {\n" // #11195 + " for (int i = 0; i < 10; ++i) {\n" + " printf(\"i = %d\\n\", i);\n" + " continue;\n" + " }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4]: (style) 'continue' is redundant since it is the last statement in a loop.\n", errout.str()); + + check("void f() {\n" + " int i = 0;" + " do {\n" + " ++i;\n" + " printf(\"i = %d\\n\", i);\n" + " continue;\n" + " } while (i < 10);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:5]: (style) 'continue' is redundant since it is the last statement in a loop.\n", errout.str()); + } + void suspiciousCase() { check("void foo() {\n"