diff --git a/lib/checkfunctions.cpp b/lib/checkfunctions.cpp index 23db248816d..1edfdfab6ac 100644 --- a/lib/checkfunctions.cpp +++ b/lib/checkfunctions.cpp @@ -329,6 +329,8 @@ void CheckFunctionsImpl::checkMissingReturn() continue; if (Function::returnsVoid(function, true)) continue; + if (Function::isCoroutine(function, mSettings.standards, *mTokenizer)) + continue; const Token *errorToken = checkMissingReturnScope(scope->bodyEnd, mSettings.library); if (errorToken) missingReturnError(errorToken); diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index b82a3f790b0..89f70191e92 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -3407,6 +3407,20 @@ bool Function::returnsVoid(const Function* function, bool unknown) }); } +bool Function::isCoroutine(const Function* function, const Standards &standards, const Tokenizer &tokens) +{ + if (!tokens.isCPP() || standards.cpp < Standards::CPP20) + return false; + if (!function->functionScope) + return false; + const Scope *scope = function->functionScope; + for (const Token *tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { + if (Token::Match(tok, "co_return|co_await|co_yield")) + return true; + } + return false; +} + std::vector Function::findReturns(const Function* f) { std::vector result; diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 166f228ad99..7d52d0bfb32 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -945,6 +945,7 @@ class CPPCHECKLIB Function { static bool returnsStandardType(const Function* function, bool unknown = false); static bool returnsVoid(const Function* function, bool unknown = false); + static bool isCoroutine(const Function* function, const Standards &standards, const Tokenizer &tokens); static std::vector findReturns(const Function* f); diff --git a/test/testfunctions.cpp b/test/testfunctions.cpp index 788ff7a0d14..f5067bc31dc 100644 --- a/test/testfunctions.cpp +++ b/test/testfunctions.cpp @@ -86,6 +86,7 @@ class TestFunctions : public TestFixture { TEST_CASE(checkMissingReturn5); TEST_CASE(checkMissingReturn6); // #13180 TEST_CASE(checkMissingReturn7); // #14370 - FN try/catch + TEST_CASE(checkMissingReturn8); TEST_CASE(checkMissingReturnStdInt); // #14482 - FN std::int32_t // std::move for locar variable @@ -1927,6 +1928,14 @@ class TestFunctions : public TestFixture { ASSERT_EQUALS("[test.cpp:3:19]: (error) Found an exit path from function with non-void return type that has missing return statement [missingReturn]\n", errout_str()); } + void checkMissingReturn8() { + const Settings s = settingsBuilder(settings).cpp(Standards::CPP20).build(); + check("boost::asio::awaitable test() {\n" + " co_return;\n" + "}\n",s); + ASSERT_EQUALS("", errout_str()); + } + void checkMissingReturnStdInt() {// #14482 - FN check("std::int32_t f() {}\n"); ASSERT_EQUALS("[test.cpp:1:19]: (error) Found an exit path from function with non-void return type that has missing return statement [missingReturn]\n", errout_str());