From 8025a29171cd1c650bcc11fa2c2806a2724bce73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Mon, 13 Jul 2026 14:38:47 +0200 Subject: [PATCH 1/3] add test --- test/testfunctions.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/testfunctions.cpp b/test/testfunctions.cpp index 788ff7a0d14..b5ed2871a73 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,13 @@ 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() { + check("boost::asio::awaitable test() {\n" + " co_return;\n" + "}\n"); + 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()); From 07e0b49dbaf2620381c1cb25c89b2d57a57602b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Mon, 13 Jul 2026 14:35:34 +0200 Subject: [PATCH 2/3] fix --- lib/checkfunctions.cpp | 2 ++ lib/symboldatabase.cpp | 12 ++++++++++++ lib/symboldatabase.h | 1 + 3 files changed, 15 insertions(+) diff --git a/lib/checkfunctions.cpp b/lib/checkfunctions.cpp index 23db248816d..2490dbd02b7 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)) + 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..5a9f68988a4 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -3407,6 +3407,18 @@ bool Function::returnsVoid(const Function* function, bool unknown) }); } +bool Function::isCoroutine(const Function* function) +{ + 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..f1fe3464452 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); static std::vector findReturns(const Function* f); From b496ae896b45edc51c3ce8c7ea62960523a3147c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Mon, 13 Jul 2026 15:33:40 +0200 Subject: [PATCH 3/3] add language/standard check --- lib/checkfunctions.cpp | 2 +- lib/symboldatabase.cpp | 4 +++- lib/symboldatabase.h | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/checkfunctions.cpp b/lib/checkfunctions.cpp index 2490dbd02b7..1edfdfab6ac 100644 --- a/lib/checkfunctions.cpp +++ b/lib/checkfunctions.cpp @@ -329,7 +329,7 @@ void CheckFunctionsImpl::checkMissingReturn() continue; if (Function::returnsVoid(function, true)) continue; - if (Function::isCoroutine(function)) + if (Function::isCoroutine(function, mSettings.standards, *mTokenizer)) continue; const Token *errorToken = checkMissingReturnScope(scope->bodyEnd, mSettings.library); if (errorToken) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 5a9f68988a4..89f70191e92 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -3407,8 +3407,10 @@ bool Function::returnsVoid(const Function* function, bool unknown) }); } -bool Function::isCoroutine(const Function* function) +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; diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index f1fe3464452..7d52d0bfb32 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -945,7 +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); + static bool isCoroutine(const Function* function, const Standards &standards, const Tokenizer &tokens); static std::vector findReturns(const Function* f);