diff --git a/lib/checkfunctions.cpp b/lib/checkfunctions.cpp index b7d2a6762..4e17c5787 100644 --- a/lib/checkfunctions.cpp +++ b/lib/checkfunctions.cpp @@ -269,6 +269,19 @@ void CheckFunctions::checkMissingReturn() } } +static bool isForwardJump(const Token *gotoToken) +{ + if (!Token::Match(gotoToken, "goto %name% ;")) + return false; + for (const Token *prev = gotoToken; gotoToken; gotoToken = gotoToken->previous()) { + if (Token::Match(prev, "%name% :") && prev->str() == gotoToken->next()->str()) + return true; + if (prev->str() == "{" && prev->scope()->type == Scope::eFunction) + return false; + } + return false; +} + static const Token *checkMissingReturnScope(const Token *tok, const Library &library) { const Token *lastStatement = nullptr; @@ -279,6 +292,8 @@ static const Token *checkMissingReturnScope(const Token *tok, const Library &lib for (const Token *prev = tok->link()->previous(); prev && prev->scope() == tok->scope() && !Token::Match(prev, "[;{}]"); prev = prev->previous()) { if (prev->isKeyword() && Token::Match(prev, "return|throw")) return nullptr; + if (prev->str() == "goto" && !isForwardJump(prev)) + return nullptr; } if (tok->scope()->type == Scope::ScopeType::eSwitch) { // find reachable break / !default @@ -316,6 +331,8 @@ static const Token *checkMissingReturnScope(const Token *tok, const Library &lib } if (tok->isKeyword() && Token::Match(tok, "return|throw")) return nullptr; + if (tok->str() == "goto" && !isForwardJump(tok)) + return nullptr; if (Token::Match(tok, "%name% (") && library.isnoreturn(tok)) return nullptr; if (Token::Match(tok, "[;{}] %name% :")) diff --git a/test/testfunctions.cpp b/test/testfunctions.cpp index 78217f383..7cd843bd5 100644 --- a/test/testfunctions.cpp +++ b/test/testfunctions.cpp @@ -1379,6 +1379,15 @@ private: check("auto foo4() -> void {}"); ASSERT_EQUALS("", errout.str()); + check("int f() {\n" + "back:\n" + " return 0;\n" + "ng:\n" + " x=y;\n" + " goto back;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + // unreachable code.. check("int foo(int x) {\n" " return 1;\n"