diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index e429758f0..fc74698ea 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -763,6 +763,11 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const variables.clear(); break; } + if (Token::Match(tok, "goto")) { // https://sourceforge.net/apps/trac/cppcheck/ticket/4447 + variables.clear(); + break; + } + // bailout when for_each is used if (Token::Match(tok,"%var% (") && Token::simpleMatch(tok->linkAt(1),") {")) { diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 59d0d01b1..71d3bbbc0 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -150,6 +150,7 @@ private: TEST_CASE(localvarAnd); // #3672 TEST_CASE(localvarSwitch); // #3744 - false positive when localvar is used in switch TEST_CASE(localvarNULL); // #4203 - Setting NULL value is not redundant - it is safe + TEST_CASE(localvarUnusedGoto); // #4447, #4558 goto TEST_CASE(crash1); TEST_CASE(usingNamespace); // #4585 @@ -3614,6 +3615,37 @@ private: ASSERT_EQUALS("", errout.str()); } + void localvarUnusedGoto() { + // #4447 + functionVariableUsage("bool f(const int &i) {\n" + " int X = i;\n" + "label:\n" + " if ( X == 0 ) {\n" + " X -= 101;\n" + " return true;\n" + " }\n" + " if ( X < 1001 ) {\n" + " X += 1;\n" + " goto label;\n" + " }\n" + " return false;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + // #4558 + functionVariableUsage("int f() {\n" + " int i,j=0;\n" + " start:\n" + " i=j;\n" + " i++;\n" + " j=i;\n" + " if (i<3)\n" + " goto start;\n" + " return i;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + } + void crash1() { functionVariableUsage("SAL_WNODEPRECATED_DECLARATIONS_PUSH\n" "void convertToTokenArray() {\n"