Annex F (informative) Core undefined behavior [ub]

F.4 [stmt]: Statements [ub.stmt]

F.4.2[ub:stmt.return.coroutine.flow.off]

Flowing off the end of a coroutine function body that does not return void has undefined behavior.
[Example 1: #include <cassert> #include <coroutine> #include <iostream> #include <vector> class resumable { public: struct promise_type; using coro_handle = std::coroutine_handle<promise_type>; resumable(coro_handle handle) : handle_(handle) { assert(handle); } resumable(resumable&) = delete; resumable(resumable&&) = delete; bool resume() { if (not handle_.done()) handle_.resume(); return not handle_.done(); } ~resumable() { handle_.destroy(); } const char* return_val(); private: coro_handle handle_; }; struct resumable::promise_type { using coro_handle = std::coroutine_handle<promise_type>; const char* string_; auto get_return_object() { return coro_handle::from_promise(*this); } auto initial_suspend() { return std::suspend_always(); } auto final_suspend() noexcept { return std::suspend_always(); } void unhandled_exception() { std::terminate(); } void return_value(const char* string) { string_ = string; } }; const char* resumable::return_val() { return handle_.promise().string_; } resumable foo() { std::cout << "Hello" << std::endl; co_await std::suspend_always(); // undefined behavior, falling off the end of coroutine that does not return void } int main() { resumable res = foo(); while (res.resume()) ; std::cout << res.return_val() << std::endl; } — end example]