xref: /llvm-project/clang/test/SemaCXX/coroutine-final-suspend-noexcept.cpp (revision 4f4340ee2af36909db77aeedb1d22c2ba52d2dfa)
1 // This file contains references to sections of the Coroutines TS, which can be
2 // found at http://wg21.link/coroutines.
3 
4 // RUN: %clang_cc1 -std=c++20 -verify %s -fcxx-exceptions -fexceptions -Wunused-result
5 
6 namespace std {
7 
8 template <class Ret, typename... T>
9 struct coroutine_traits { using promise_type = typename Ret::promise_type; };
10 
11 template <class Promise = void>
12 struct coroutine_handle {
13   static coroutine_handle from_address(void *);
14   void *address() const noexcept;
15 };
16 template <>
17 struct coroutine_handle<void> {
18   template <class PromiseType>
19   coroutine_handle(coroutine_handle<PromiseType>);
20   void *address() const noexcept;
21 };
22 
23 struct suspend_always {
await_readystd::suspend_always24   bool await_ready() { return false; }      // expected-note 2 {{must be declared with 'noexcept'}}
await_suspendstd::suspend_always25   void await_suspend(coroutine_handle<>) {} // expected-note 2 {{must be declared with 'noexcept'}}
await_resumestd::suspend_always26   void await_resume() {}                    // expected-note 2 {{must be declared with 'noexcept'}}
27   ~suspend_always() noexcept(false);        // expected-note 2 {{must be declared with 'noexcept'}}
28 };
29 
30 } // namespace std
31 
32 using namespace std;
33 
34 struct A {
35   bool await_ready();
36   void await_resume();
37   template <typename F>
38   void await_suspend(F);
39 };
40 
41 struct coro_t {
42   struct promise_type {
43     coro_t get_return_object();
44     suspend_always initial_suspend();
45     suspend_always final_suspend(); // expected-note 2 {{must be declared with 'noexcept'}}
46     void return_void();
47     static void unhandled_exception();
48   };
49 };
50 
f(int n)51 coro_t f(int n) { // expected-error {{the expression 'co_await __promise.final_suspend()' is required to be non-throwing}}
52   A a{};
53   co_await a;
54 }
55 
56 template <typename T>
f_dep(T n)57 coro_t f_dep(T n) { // expected-error {{the expression 'co_await __promise.final_suspend()' is required to be non-throwing}}
58   A a{};
59   co_await a;
60 }
61 
foo()62 void foo() {
63   f_dep<int>(5); // expected-note {{in instantiation of function template specialization 'f_dep<int>' requested here}}
64 }
65 
66 struct PositiveFinalSuspend {
67   bool await_ready() noexcept;
68   coroutine_handle<> await_suspend(coroutine_handle<>) noexcept;
69   void await_resume() noexcept;
70 };
71 
72 struct correct_coro {
73   struct promise_type {
74     correct_coro get_return_object();
75     suspend_always initial_suspend();
76     PositiveFinalSuspend final_suspend() noexcept;
77     void return_void();
78     static void unhandled_exception();
79   };
80 };
81 
f2(int n)82 correct_coro f2(int n) {
83   co_return;
84 }
85 
86 struct NegativeFinalSuspend {
87   bool await_ready() noexcept;
88   coroutine_handle<> await_suspend(coroutine_handle<>) noexcept;
89   void await_resume() noexcept;
90   ~NegativeFinalSuspend() noexcept(false); // expected-note {{must be declared with 'noexcept'}}
91 };
92 
93 struct incorrect_coro {
94   struct promise_type {
95     incorrect_coro get_return_object();
96     suspend_always initial_suspend();
97     NegativeFinalSuspend final_suspend() noexcept;
98     void return_void();
99     static void unhandled_exception();
100   };
101 };
102 
f3(int n)103 incorrect_coro f3(int n) { // expected-error {{the expression 'co_await __promise.final_suspend()' is required to be non-throwing}}
104   co_return;
105 }
106