Annex F (informative) Core undefined behavior [ub]

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

F.4.1[ub:stmt.return.flow.off]
Specified in: [stmt.return]

Flowing off the end of a function other than main or a coroutine results in undefined behavior if the return type is not cv void.
[Example 1: int f(int x) { if (x) return 1; // undefined behavior if x is 0 } void b() { int x = f(0); // undefined behavior, using 0 as an argument will cause f(...) to flow // off the end without a return statement } — end example]

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]

F.4.3[ub:stmt.dcl.local.static.init.recursive]
Specified in: [stmt.dcl]

If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined.
[Example 1: int foo(int i) { static int s = foo(2 * i); // undefined behavior, recursive call return i + 1; } — end example]