1 // RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s
2 
3 void no_coroutine_traits_bad_arg_await() {
4   co_await a; // expected-error {{include <experimental/coroutine>}}
5   // expected-error@-1 {{use of undeclared identifier 'a'}}
6 }
7 
8 void no_coroutine_traits_bad_arg_yield() {
9   co_yield a; // expected-error {{include <experimental/coroutine>}}
10   // expected-error@-1 {{use of undeclared identifier 'a'}}
11 }
12 
13 
14 void no_coroutine_traits_bad_arg_return() {
15   co_return a; // expected-error {{include <experimental/coroutine>}}
16   // expected-error@-1 {{use of undeclared identifier 'a'}}
17 }
18 
19 
20 struct awaitable {
21   bool await_ready();
22   void await_suspend(); // FIXME: coroutine_handle
23   void await_resume();
24 } a;
25 
26 struct suspend_always {
27   bool await_ready() { return false; }
28   void await_suspend() {}
29   void await_resume() {}
30 };
31 
32 struct suspend_never {
33   bool await_ready() { return true; }
34   void await_suspend() {}
35   void await_resume() {}
36 };
37 
38 void no_coroutine_traits() {
39   co_await a; // expected-error {{need to include <experimental/coroutine>}}
40 }
41 
42 namespace std {
43 namespace experimental {
44 template <typename... T>
45 struct coroutine_traits; // expected-note {{declared here}}
46 }
47 }
48 
49 template<typename Promise> struct coro {};
50 template <typename Promise, typename... Ps>
51 struct std::experimental::coroutine_traits<coro<Promise>, Ps...> {
52   using promise_type = Promise;
53 };
54 
55 void no_specialization() {
56   co_await a; // expected-error {{implicit instantiation of undefined template 'std::experimental::coroutine_traits<void>'}}
57 }
58 
59 template <typename... T>
60 struct std::experimental::coroutine_traits<int, T...> {};
61 
62 int no_promise_type() {
63   co_await a; // expected-error {{this function cannot be a coroutine: 'std::experimental::coroutine_traits<int>' has no member named 'promise_type'}}
64 }
65 
66 template <>
67 struct std::experimental::coroutine_traits<double, double> { typedef int promise_type; };
68 double bad_promise_type(double) {
69   co_await a; // expected-error {{this function cannot be a coroutine: 'experimental::coroutine_traits<double, double>::promise_type' (aka 'int') is not a class}}
70 }
71 
72 template <>
73 struct std::experimental::coroutine_traits<double, int> {
74   struct promise_type {};
75 };
76 double bad_promise_type_2(int) {
77   co_yield 0; // expected-error {{no member named 'yield_value' in 'std::experimental::coroutine_traits<double, int>::promise_type'}}
78 }
79 
80 struct promise; // expected-note 2{{forward declaration}}
81 struct promise_void;
82 struct void_tag {};
83 template <typename... T>
84 struct std::experimental::coroutine_traits<void, T...> { using promise_type = promise; };
85 template <typename... T>
86 struct std::experimental::coroutine_traits<void, void_tag, T...>
87 { using promise_type = promise_void; };
88 
89 namespace std {
90 namespace experimental {
91 template <typename Promise = void>
92 struct coroutine_handle;
93 }
94 }
95 
96 // FIXME: This diagnostic is terrible.
97 void undefined_promise() { // expected-error {{variable has incomplete type 'promise_type'}}
98   // FIXME: This diagnostic doesn't make any sense.
99   // expected-error@-2 {{incomplete definition of type 'promise'}}
100   co_await a;
101 }
102 
103 struct yielded_thing { const char *p; short a, b; };
104 
105 struct not_awaitable {};
106 
107 struct promise {
108   void get_return_object();
109   suspend_always initial_suspend();
110   suspend_always final_suspend();
111   awaitable yield_value(int); // expected-note 2{{candidate}}
112   awaitable yield_value(yielded_thing); // expected-note 2{{candidate}}
113   not_awaitable yield_value(void()); // expected-note 2{{candidate}}
114   void return_value(int); // expected-note 2{{here}}
115 };
116 
117 struct promise_void {
118   void get_return_object();
119   suspend_always initial_suspend();
120   suspend_always final_suspend();
121   void return_void();
122 };
123 
124 void yield() {
125   co_yield 0;
126   co_yield {"foo", 1, 2};
127   co_yield {1e100}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}} expected-warning {{braces around scalar}}
128   co_yield {"foo", __LONG_LONG_MAX__}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}}
129   co_yield {"foo"};
130   co_yield "foo"; // expected-error {{no matching}}
131   co_yield 1.0;
132   co_yield yield; // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
133 }
134 
135 void coreturn(int n) {
136   co_await a;
137   if (n == 0)
138     co_return 3;
139   if (n == 1)
140     co_return {4}; // expected-warning {{braces around scalar initializer}}
141   if (n == 2)
142     co_return "foo"; // expected-error {{cannot initialize a parameter of type 'int' with an lvalue of type 'const char [4]'}}
143   co_return 42;
144 }
145 
146 void mixed_yield() {
147   co_yield 0; // expected-note {{use of 'co_yield'}}
148   return; // expected-error {{not allowed in coroutine}}
149 }
150 
151 void mixed_await() {
152   co_await a; // expected-note {{use of 'co_await'}}
153   return; // expected-error {{not allowed in coroutine}}
154 }
155 
156 void only_coreturn(void_tag) {
157   co_return; // expected-warning {{'co_return' used in a function that uses neither 'co_await' nor 'co_yield'}}
158 }
159 
160 void mixed_coreturn(void_tag, bool b) {
161   if (b)
162     // expected-warning@+1 {{'co_return' used in a function that uses neither}}
163     co_return; // expected-note {{use of 'co_return'}}
164   else
165     return; // expected-error {{not allowed in coroutine}}
166 }
167 
168 struct CtorDtor {
169   CtorDtor() {
170     co_yield 0; // expected-error {{'co_yield' cannot be used in a constructor}}
171   }
172   CtorDtor(awaitable a) {
173     // The spec doesn't say this is ill-formed, but it must be.
174     co_await a; // expected-error {{'co_await' cannot be used in a constructor}}
175   }
176   ~CtorDtor() {
177     co_return 0; // expected-error {{'co_return' cannot be used in a destructor}}
178   }
179   // FIXME: The spec says this is ill-formed.
180   void operator=(CtorDtor&) {
181     co_yield 0; // expected-error {{'co_yield' cannot be used in a copy assignment operator}}
182   }
183   void operator=(CtorDtor const &) {
184     co_yield 0; // expected-error {{'co_yield' cannot be used in a copy assignment operator}}
185   }
186   void operator=(CtorDtor &&) {
187     co_await a; // expected-error {{'co_await' cannot be used in a move assignment operator}}
188   }
189   void operator=(CtorDtor const &&) {
190     co_await a; // expected-error {{'co_await' cannot be used in a move assignment operator}}
191   }
192   void operator=(int) {
193     co_await a; // OK. Not a special member
194   }
195 };
196 
197 void unevaluated() {
198   decltype(co_await a); // expected-error {{cannot be used in an unevaluated context}}
199   sizeof(co_await a); // expected-error {{cannot be used in an unevaluated context}}
200   typeid(co_await a); // expected-error {{cannot be used in an unevaluated context}}
201   decltype(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
202   sizeof(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
203   typeid(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
204 }
205 
206 constexpr auto constexpr_deduced_return_coroutine() {
207   co_yield 0; // expected-error {{'co_yield' cannot be used in a constexpr function}}
208   // expected-error@-1 {{'co_yield' cannot be used in a function with a deduced return type}}
209 }
210 
211 void varargs_coroutine(const char *, ...) {
212   co_await a; // expected-error {{'co_await' cannot be used in a varargs function}}
213 }
214 
215 auto deduced_return_coroutine() {
216   co_await a; // expected-error {{'co_await' cannot be used in a function with a deduced return type}}
217 }
218 
219 struct outer {};
220 
221 namespace dependent_operator_co_await_lookup {
222   template<typename T> void await_template(T t) {
223     // no unqualified lookup results
224     co_await t; // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::not_awaitable'}}
225     // expected-error@-1 {{call to function 'operator co_await' that is neither visible in the template definition nor found by argument-dependent lookup}}
226   };
227   template void await_template(awaitable);
228 
229   struct indirectly_awaitable { indirectly_awaitable(outer); };
230   awaitable operator co_await(indirectly_awaitable); // expected-note {{should be declared prior to}}
231   template void await_template(indirectly_awaitable);
232 
233   struct not_awaitable {};
234   template void await_template(not_awaitable); // expected-note {{instantiation}}
235 
236   template<typename T> void await_template_2(T t) {
237     // one unqualified lookup result
238     co_await t;
239   };
240   template void await_template(outer); // expected-note {{instantiation}}
241   template void await_template_2(outer);
242 }
243 
244 struct yield_fn_tag {};
245 template <>
246 struct std::experimental::coroutine_traits<void, yield_fn_tag> {
247   struct promise_type {
248     // FIXME: add an await_transform overload for functions
249     awaitable yield_value(int());
250     void return_value(int());
251 
252     suspend_never initial_suspend();
253     suspend_never final_suspend();
254     void get_return_object();
255   };
256 };
257 
258 namespace placeholder {
259   awaitable f(), f(int); // expected-note 4{{possible target}}
260   int g(), g(int); // expected-note 2{{candidate}}
261   void x() {
262     co_await f; // expected-error {{reference to overloaded function}}
263   }
264   void y() {
265     co_yield g; // expected-error {{no matching member function for call to 'yield_value'}}
266   }
267   void z() {
268     co_await a;
269     co_return g; // expected-error {{address of overloaded function 'g' does not match required type 'int'}}
270   }
271 
272   void x(yield_fn_tag) {
273     co_await f; // expected-error {{reference to overloaded function}}
274   }
275   void y(yield_fn_tag) {
276     co_yield g;
277   }
278   void z(yield_fn_tag) {
279     co_await a;
280     co_return g;
281   }
282 }
283 
284 struct bad_promise_1 {
285   suspend_always initial_suspend();
286   suspend_always final_suspend();
287 };
288 coro<bad_promise_1> missing_get_return_object() { // expected-error {{no member named 'get_return_object' in 'bad_promise_1'}}
289   co_await a;
290 }
291 
292 struct bad_promise_2 {
293   coro<bad_promise_2> get_return_object();
294   // FIXME: We shouldn't offer a typo-correction here!
295   suspend_always final_suspend(); // expected-note {{here}}
296 };
297 coro<bad_promise_2> missing_initial_suspend() { // expected-error {{no member named 'initial_suspend' in 'bad_promise_2'}}
298   co_await a;
299 }
300 
301 struct bad_promise_3 {
302   coro<bad_promise_3> get_return_object();
303   // FIXME: We shouldn't offer a typo-correction here!
304   suspend_always initial_suspend(); // expected-note {{here}}
305 };
306 coro<bad_promise_3> missing_final_suspend() { // expected-error {{no member named 'final_suspend' in 'bad_promise_3'}}
307   co_await a;
308 }
309 
310 struct bad_promise_4 {
311   coro<bad_promise_4> get_return_object();
312   not_awaitable initial_suspend();
313   suspend_always final_suspend();
314 };
315 // FIXME: This diagnostic is terrible.
316 coro<bad_promise_4> bad_initial_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
317   co_await a;
318 }
319 
320 struct bad_promise_5 {
321   coro<bad_promise_5> get_return_object();
322   suspend_always initial_suspend();
323   not_awaitable final_suspend();
324 };
325 // FIXME: This diagnostic is terrible.
326 coro<bad_promise_5> bad_final_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
327   co_await a;
328 }
329 
330 struct bad_promise_6 {
331   coro<bad_promise_6> get_return_object();
332   suspend_always initial_suspend();
333   suspend_always final_suspend();
334   void return_void();
335   void return_value(int) const;
336   void return_value(int);
337 };
338 coro<bad_promise_6> bad_implicit_return() { // expected-error {{'bad_promise_6' declares both 'return_value' and 'return_void'}}
339   co_await a;
340 }
341 
342 struct bad_promise_7 {
343   coro<bad_promise_7> get_return_object();
344   suspend_always initial_suspend();
345   suspend_always final_suspend();
346   void return_void();
347   void set_exception(int *);
348 };
349 coro<bad_promise_7> no_std_current_exc() {
350   // expected-error@-1 {{you need to include <exception> before defining a coroutine that implicitly uses 'set_exception'}}
351   co_await a;
352 }
353 
354 namespace std {
355 int *current_exception();
356 }
357 
358 struct bad_promise_8 {
359   coro<bad_promise_8> get_return_object();
360   suspend_always initial_suspend();
361   suspend_always final_suspend();
362   void return_void();
363   void set_exception();                                   // expected-note {{function not viable}}
364   void set_exception(int *) __attribute__((unavailable)); // expected-note {{explicitly made unavailable}}
365   void set_exception(void *);                             // expected-note {{candidate function}}
366 };
367 coro<bad_promise_8> calls_set_exception() {
368   // expected-error@-1 {{call to unavailable member function 'set_exception'}}
369   co_await a;
370 }
371 
372 template<> struct std::experimental::coroutine_traits<int, int, const char**>
373 { using promise_type = promise; };
374 
375 int main(int, const char**) {
376   co_await a; // expected-error {{'co_await' cannot be used in the 'main' function}}
377 }
378