1 // RUN: %clang_cc1 -std=c++14 -fcoroutines -verify %s
2
3 struct awaitable {
4 bool await_ready();
5 void await_suspend(); // FIXME: coroutine_handle
6 void await_resume();
7 } a;
8
9 struct suspend_always {
await_readysuspend_always10 bool await_ready() { return false; }
await_suspendsuspend_always11 void await_suspend() {}
await_resumesuspend_always12 void await_resume() {}
13 };
14
15 struct suspend_never {
await_readysuspend_never16 bool await_ready() { return true; }
await_suspendsuspend_never17 void await_suspend() {}
await_resumesuspend_never18 void await_resume() {}
19 };
20
no_coroutine_traits()21 void no_coroutine_traits() {
22 co_await a; // expected-error {{need to include <coroutine>}}
23 }
24
25 namespace std {
26 template<typename ...T> struct coroutine_traits; // expected-note {{declared here}}
27 };
28
29 template<typename Promise> struct coro {};
30 template<typename Promise, typename... Ps>
31 struct std::coroutine_traits<coro<Promise>, Ps...> {
32 using promise_type = Promise;
33 };
34
no_specialization()35 void no_specialization() {
36 co_await a; // expected-error {{implicit instantiation of undefined template 'std::coroutine_traits<void>'}}
37 }
38
39 template<typename ...T> struct std::coroutine_traits<int, T...> {};
40
no_promise_type()41 int no_promise_type() {
42 co_await a; // expected-error {{this function cannot be a coroutine: 'std::coroutine_traits<int>' has no member named 'promise_type'}}
43 }
44
45 template<> struct std::coroutine_traits<double, double> { typedef int promise_type; };
bad_promise_type(double)46 double bad_promise_type(double) {
47 co_await a; // expected-error {{this function cannot be a coroutine: 'std::coroutine_traits<double, double>::promise_type' (aka 'int') is not a class}}
48 }
49
50 template<> struct std::coroutine_traits<double, int> {
51 struct promise_type {};
52 };
bad_promise_type_2(int)53 double bad_promise_type_2(int) {
54 co_yield 0; // expected-error {{no member named 'yield_value' in 'std::coroutine_traits<double, int>::promise_type'}}
55 }
56
57 struct promise; // expected-note 2{{forward declaration}}
58 template<typename ...T> struct std::coroutine_traits<void, T...> { using promise_type = promise; };
59
60 // FIXME: This diagnostic is terrible.
undefined_promise()61 void undefined_promise() { // expected-error {{variable has incomplete type 'promise_type'}}
62 // FIXME: This diagnostic doesn't make any sense.
63 // expected-error@-2 {{incomplete definition of type 'promise'}}
64 co_await a;
65 }
66
67 struct yielded_thing { const char *p; short a, b; };
68
69 struct not_awaitable {};
70
71 struct promise {
72 void get_return_object();
73 suspend_always initial_suspend();
74 suspend_always final_suspend();
75 awaitable yield_value(int); // expected-note 2{{candidate}}
76 awaitable yield_value(yielded_thing); // expected-note 2{{candidate}}
77 not_awaitable yield_value(void()); // expected-note 2{{candidate}}
78 void return_void();
79 void return_value(int); // expected-note 2{{here}}
80 };
81
yield()82 void yield() {
83 co_yield 0;
84 co_yield {"foo", 1, 2};
85 co_yield {1e100}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}} expected-warning {{braces around scalar}}
86 co_yield {"foo", __LONG_LONG_MAX__}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}}
87 co_yield {"foo"};
88 co_yield "foo"; // expected-error {{no matching}}
89 co_yield 1.0;
90 co_yield yield; // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
91 }
92
coreturn(int n)93 void coreturn(int n) {
94 co_await a;
95 if (n == 0)
96 co_return 3;
97 if (n == 1)
98 co_return {4};
99 if (n == 2)
100 co_return "foo"; // expected-error {{cannot initialize a parameter of type 'int' with an lvalue of type 'const char [4]'}}
101 co_return;
102 }
103
mixed_yield()104 void mixed_yield() {
105 co_yield 0; // expected-note {{use of 'co_yield'}}
106 return; // expected-error {{not allowed in coroutine}}
107 }
108
mixed_await()109 void mixed_await() {
110 co_await a; // expected-note {{use of 'co_await'}}
111 return; // expected-error {{not allowed in coroutine}}
112 }
113
only_coreturn()114 void only_coreturn() {
115 co_return; // expected-warning {{'co_return' used in a function that uses neither 'co_await' nor 'co_yield'}}
116 }
117
mixed_coreturn(bool b)118 void mixed_coreturn(bool b) {
119 if (b)
120 // expected-warning@+1 {{'co_return' used in a function that uses neither}}
121 co_return; // expected-note {{use of 'co_return'}}
122 else
123 return; // expected-error {{not allowed in coroutine}}
124 }
125
126 struct CtorDtor {
CtorDtorCtorDtor127 CtorDtor() {
128 co_yield 0; // expected-error {{'co_yield' cannot be used in a constructor}}
129 }
CtorDtorCtorDtor130 CtorDtor(awaitable a) {
131 // The spec doesn't say this is ill-formed, but it must be.
132 co_await a; // expected-error {{'co_await' cannot be used in a constructor}}
133 }
~CtorDtorCtorDtor134 ~CtorDtor() {
135 co_return 0; // expected-error {{'co_return' cannot be used in a destructor}}
136 }
137 // FIXME: The spec says this is ill-formed.
operator =CtorDtor138 void operator=(CtorDtor&) {
139 co_yield 0;
140 }
141 };
142
unevaluated()143 void unevaluated() {
144 decltype(co_await a); // expected-error {{cannot be used in an unevaluated context}}
145 sizeof(co_await a); // expected-error {{cannot be used in an unevaluated context}}
146 typeid(co_await a); // expected-error {{cannot be used in an unevaluated context}}
147 decltype(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
148 sizeof(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
149 typeid(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
150 }
151
constexpr_coroutine()152 constexpr void constexpr_coroutine() {
153 co_yield 0; // expected-error {{'co_yield' cannot be used in a constexpr function}}
154 }
155
varargs_coroutine(const char *,...)156 void varargs_coroutine(const char *, ...) {
157 co_await a; // expected-error {{'co_await' cannot be used in a varargs function}}
158 }
159
160 struct outer {};
161
162 namespace dependent_operator_co_await_lookup {
await_template(T t)163 template<typename T> void await_template(T t) {
164 // no unqualified lookup results
165 co_await t; // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::not_awaitable'}}
166 // expected-error@-1 {{call to function 'operator co_await' that is neither visible in the template definition nor found by argument-dependent lookup}}
167 };
168 template void await_template(awaitable);
169
170 struct indirectly_awaitable { indirectly_awaitable(outer); };
171 awaitable operator co_await(indirectly_awaitable); // expected-note {{should be declared prior to}}
172 template void await_template(indirectly_awaitable);
173
174 struct not_awaitable {};
175 template void await_template(not_awaitable); // expected-note {{instantiation}}
176
await_template_2(T t)177 template<typename T> void await_template_2(T t) {
178 // one unqualified lookup result
179 co_await t;
180 };
181 template void await_template(outer); // expected-note {{instantiation}}
182 template void await_template_2(outer);
183 }
184
185 struct yield_fn_tag {};
186 template<> struct std::coroutine_traits<void, yield_fn_tag> {
187 struct promise_type {
188 // FIXME: add an await_transform overload for functions
189 awaitable yield_value(int());
190 void return_value(int());
191
192 suspend_never initial_suspend();
193 suspend_never final_suspend();
194 void get_return_object();
195 };
196 };
197
198 namespace placeholder {
199 awaitable f(), f(int); // expected-note 4{{possible target}}
200 int g(), g(int); // expected-note 2{{candidate}}
x()201 void x() {
202 co_await f; // expected-error {{reference to overloaded function}}
203 }
y()204 void y() {
205 co_yield g; // expected-error {{no matching member function for call to 'yield_value'}}
206 }
z()207 void z() {
208 co_await a;
209 co_return g; // expected-error {{address of overloaded function 'g' does not match required type 'int'}}
210 }
211
x(yield_fn_tag)212 void x(yield_fn_tag) {
213 co_await f; // expected-error {{reference to overloaded function}}
214 }
y(yield_fn_tag)215 void y(yield_fn_tag) {
216 co_yield g;
217 }
z(yield_fn_tag)218 void z(yield_fn_tag) {
219 co_await a;
220 co_return g;
221 }
222 }
223
224 struct bad_promise_1 {
225 suspend_always initial_suspend();
226 suspend_always final_suspend();
227 };
missing_get_return_object()228 coro<bad_promise_1> missing_get_return_object() { // expected-error {{no member named 'get_return_object' in 'bad_promise_1'}}
229 co_await a;
230 }
231
232 struct bad_promise_2 {
233 coro<bad_promise_2> get_return_object();
234 // FIXME: We shouldn't offer a typo-correction here!
235 suspend_always final_suspend(); // expected-note {{here}}
236 };
missing_initial_suspend()237 coro<bad_promise_2> missing_initial_suspend() { // expected-error {{no member named 'initial_suspend' in 'bad_promise_2'}}
238 co_await a;
239 }
240
241 struct bad_promise_3 {
242 coro<bad_promise_3> get_return_object();
243 // FIXME: We shouldn't offer a typo-correction here!
244 suspend_always initial_suspend(); // expected-note {{here}}
245 };
missing_final_suspend()246 coro<bad_promise_3> missing_final_suspend() { // expected-error {{no member named 'final_suspend' in 'bad_promise_3'}}
247 co_await a;
248 }
249
250 struct bad_promise_4 {
251 coro<bad_promise_4> get_return_object();
252 not_awaitable initial_suspend();
253 suspend_always final_suspend();
254 };
255 // FIXME: This diagnostic is terrible.
bad_initial_suspend()256 coro<bad_promise_4> bad_initial_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
257 co_await a;
258 }
259
260 struct bad_promise_5 {
261 coro<bad_promise_5> get_return_object();
262 suspend_always initial_suspend();
263 not_awaitable final_suspend();
264 };
265 // FIXME: This diagnostic is terrible.
bad_final_suspend()266 coro<bad_promise_5> bad_final_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
267 co_await a;
268 }
269