blob: dc3980cef028b3e9c083d966912ea935976145ee [file] [log] [blame]
Gor Nishanov4ffb4342016-10-02 03:31:58 +00001// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s
Richard Smithcfd53b42015-10-22 06:13:50 +00002
Eric Fiseliera5465282016-09-29 21:47:39 +00003void no_coroutine_traits_bad_arg_await() {
Gor Nishanov3e048bb2016-10-04 00:31:16 +00004 co_await a; // expected-error {{include <experimental/coroutine>}}
Eric Fiseliera5465282016-09-29 21:47:39 +00005 // expected-error@-1 {{use of undeclared identifier 'a'}}
6}
7
8void no_coroutine_traits_bad_arg_yield() {
Gor Nishanov3e048bb2016-10-04 00:31:16 +00009 co_yield a; // expected-error {{include <experimental/coroutine>}}
Eric Fiseliera5465282016-09-29 21:47:39 +000010 // expected-error@-1 {{use of undeclared identifier 'a'}}
11}
12
13
14void no_coroutine_traits_bad_arg_return() {
Gor Nishanov3e048bb2016-10-04 00:31:16 +000015 co_return a; // expected-error {{include <experimental/coroutine>}}
Eric Fiseliera5465282016-09-29 21:47:39 +000016 // expected-error@-1 {{use of undeclared identifier 'a'}}
17}
18
19
Richard Smith9f690bd2015-10-27 06:02:45 +000020struct awaitable {
21 bool await_ready();
22 void await_suspend(); // FIXME: coroutine_handle
23 void await_resume();
24} a;
25
Richard Smith2af65c42015-11-24 02:34:39 +000026struct suspend_always {
27 bool await_ready() { return false; }
28 void await_suspend() {}
29 void await_resume() {}
30};
31
32struct suspend_never {
33 bool await_ready() { return true; }
34 void await_suspend() {}
35 void await_resume() {}
36};
37
Richard Smith9f690bd2015-10-27 06:02:45 +000038void no_coroutine_traits() {
Gor Nishanov3e048bb2016-10-04 00:31:16 +000039 co_await a; // expected-error {{need to include <experimental/coroutine>}}
Richard Smith9f690bd2015-10-27 06:02:45 +000040}
41
42namespace std {
Gor Nishanov3e048bb2016-10-04 00:31:16 +000043namespace experimental {
44template <typename... T>
45struct coroutine_traits; // expected-note {{declared here}}
46}
47}
Richard Smith9f690bd2015-10-27 06:02:45 +000048
Richard Smith2af65c42015-11-24 02:34:39 +000049template<typename Promise> struct coro {};
Gor Nishanov3e048bb2016-10-04 00:31:16 +000050template <typename Promise, typename... Ps>
51struct std::experimental::coroutine_traits<coro<Promise>, Ps...> {
Richard Smith2af65c42015-11-24 02:34:39 +000052 using promise_type = Promise;
53};
54
Richard Smith9f690bd2015-10-27 06:02:45 +000055void no_specialization() {
Gor Nishanov3e048bb2016-10-04 00:31:16 +000056 co_await a; // expected-error {{implicit instantiation of undefined template 'std::experimental::coroutine_traits<void>'}}
Richard Smith9f690bd2015-10-27 06:02:45 +000057}
58
Gor Nishanov3e048bb2016-10-04 00:31:16 +000059template <typename... T>
60struct std::experimental::coroutine_traits<int, T...> {};
Richard Smith9f690bd2015-10-27 06:02:45 +000061
62int no_promise_type() {
Gor Nishanov3e048bb2016-10-04 00:31:16 +000063 co_await a; // expected-error {{this function cannot be a coroutine: 'std::experimental::coroutine_traits<int>' has no member named 'promise_type'}}
Richard Smith9b2f53e2015-11-19 02:36:35 +000064}
65
Gor Nishanov3e048bb2016-10-04 00:31:16 +000066template <>
67struct std::experimental::coroutine_traits<double, double> { typedef int promise_type; };
Richard Smith9b2f53e2015-11-19 02:36:35 +000068double bad_promise_type(double) {
Gor Nishanov3e048bb2016-10-04 00:31:16 +000069 co_await a; // expected-error {{this function cannot be a coroutine: 'experimental::coroutine_traits<double, double>::promise_type' (aka 'int') is not a class}}
Richard Smith9f690bd2015-10-27 06:02:45 +000070}
71
Gor Nishanov3e048bb2016-10-04 00:31:16 +000072template <>
73struct std::experimental::coroutine_traits<double, int> {
Richard Smith23da82c2015-11-20 22:40:06 +000074 struct promise_type {};
75};
76double bad_promise_type_2(int) {
Gor Nishanov3e048bb2016-10-04 00:31:16 +000077 co_yield 0; // expected-error {{no member named 'yield_value' in 'std::experimental::coroutine_traits<double, int>::promise_type'}}
Richard Smith23da82c2015-11-20 22:40:06 +000078}
79
Richard Smith2af65c42015-11-24 02:34:39 +000080struct promise; // expected-note 2{{forward declaration}}
Eric Fiselier98131312016-10-06 21:23:38 +000081struct promise_void;
82struct void_tag {};
Gor Nishanov3e048bb2016-10-04 00:31:16 +000083template <typename... T>
84struct std::experimental::coroutine_traits<void, T...> { using promise_type = promise; };
Eric Fiselier98131312016-10-06 21:23:38 +000085template <typename... T>
86struct std::experimental::coroutine_traits<void, void_tag, T...>
87{ using promise_type = promise_void; };
Richard Smith9f690bd2015-10-27 06:02:45 +000088
Gor Nishanov3e048bb2016-10-04 00:31:16 +000089namespace std {
90namespace experimental {
91template <typename Promise = void>
92struct coroutine_handle;
93}
94}
95
96// FIXME: This diagnostic is terrible.
Richard Smith9f690bd2015-10-27 06:02:45 +000097void undefined_promise() { // expected-error {{variable has incomplete type 'promise_type'}}
Richard Smith2af65c42015-11-24 02:34:39 +000098 // FIXME: This diagnostic doesn't make any sense.
99 // expected-error@-2 {{incomplete definition of type 'promise'}}
Richard Smith9f690bd2015-10-27 06:02:45 +0000100 co_await a;
101}
102
Richard Smithae3d1472015-11-20 22:47:10 +0000103struct yielded_thing { const char *p; short a, b; };
Richard Smith23da82c2015-11-20 22:40:06 +0000104
Richard Smithd7bed4d2015-11-22 02:57:17 +0000105struct not_awaitable {};
106
Richard Smith23da82c2015-11-20 22:40:06 +0000107struct promise {
Richard Smith2af65c42015-11-24 02:34:39 +0000108 void get_return_object();
109 suspend_always initial_suspend();
110 suspend_always final_suspend();
Richard Smith71d403e2015-11-22 07:33:28 +0000111 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}}
Richard Smith71d403e2015-11-22 07:33:28 +0000114 void return_value(int); // expected-note 2{{here}}
Richard Smith23da82c2015-11-20 22:40:06 +0000115};
116
Eric Fiselier98131312016-10-06 21:23:38 +0000117struct promise_void {
118 void get_return_object();
119 suspend_always initial_suspend();
120 suspend_always final_suspend();
121 awaitable yield_value(int);
122 awaitable yield_value(yielded_thing);
123 not_awaitable yield_value(void());
124 void return_void();
125};
126
Richard Smith23da82c2015-11-20 22:40:06 +0000127void yield() {
128 co_yield 0;
Richard Smithae3d1472015-11-20 22:47:10 +0000129 co_yield {"foo", 1, 2};
130 co_yield {1e100}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}} expected-warning {{braces around scalar}}
131 co_yield {"foo", __LONG_LONG_MAX__}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}}
132 co_yield {"foo"};
Richard Smith23da82c2015-11-20 22:40:06 +0000133 co_yield "foo"; // expected-error {{no matching}}
Richard Smithd7bed4d2015-11-22 02:57:17 +0000134 co_yield 1.0;
135 co_yield yield; // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
Richard Smith23da82c2015-11-20 22:40:06 +0000136}
Richard Smith9f690bd2015-10-27 06:02:45 +0000137
Richard Smith4ba66602015-11-22 07:05:16 +0000138void coreturn(int n) {
139 co_await a;
140 if (n == 0)
141 co_return 3;
142 if (n == 1)
Eric Fiselier98131312016-10-06 21:23:38 +0000143 co_return {4}; // expected-warning {{braces around scalar initializer}}
Richard Smith4ba66602015-11-22 07:05:16 +0000144 if (n == 2)
145 co_return "foo"; // expected-error {{cannot initialize a parameter of type 'int' with an lvalue of type 'const char [4]'}}
Eric Fiselier98131312016-10-06 21:23:38 +0000146 co_return 42;
Richard Smith4ba66602015-11-22 07:05:16 +0000147}
148
Richard Smithcfd53b42015-10-22 06:13:50 +0000149void mixed_yield() {
Richard Smith9f690bd2015-10-27 06:02:45 +0000150 co_yield 0; // expected-note {{use of 'co_yield'}}
151 return; // expected-error {{not allowed in coroutine}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000152}
153
154void mixed_await() {
Richard Smith9f690bd2015-10-27 06:02:45 +0000155 co_await a; // expected-note {{use of 'co_await'}}
156 return; // expected-error {{not allowed in coroutine}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000157}
158
Eric Fiselier98131312016-10-06 21:23:38 +0000159void only_coreturn(void_tag) {
Richard Smith9f690bd2015-10-27 06:02:45 +0000160 co_return; // expected-warning {{'co_return' used in a function that uses neither 'co_await' nor 'co_yield'}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000161}
162
Eric Fiselier98131312016-10-06 21:23:38 +0000163void mixed_coreturn(void_tag, bool b) {
Richard Smithcfd53b42015-10-22 06:13:50 +0000164 if (b)
Richard Smith9f690bd2015-10-27 06:02:45 +0000165 // expected-warning@+1 {{'co_return' used in a function that uses neither}}
166 co_return; // expected-note {{use of 'co_return'}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000167 else
Richard Smith9f690bd2015-10-27 06:02:45 +0000168 return; // expected-error {{not allowed in coroutine}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000169}
170
171struct CtorDtor {
172 CtorDtor() {
173 co_yield 0; // expected-error {{'co_yield' cannot be used in a constructor}}
174 }
Richard Smith9f690bd2015-10-27 06:02:45 +0000175 CtorDtor(awaitable a) {
Richard Smithcfd53b42015-10-22 06:13:50 +0000176 // The spec doesn't say this is ill-formed, but it must be.
Richard Smith9f690bd2015-10-27 06:02:45 +0000177 co_await a; // expected-error {{'co_await' cannot be used in a constructor}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000178 }
179 ~CtorDtor() {
180 co_return 0; // expected-error {{'co_return' cannot be used in a destructor}}
181 }
182 // FIXME: The spec says this is ill-formed.
183 void operator=(CtorDtor&) {
184 co_yield 0;
185 }
186};
187
Richard Smith744b2242015-11-20 02:54:01 +0000188void unevaluated() {
189 decltype(co_await a); // expected-error {{cannot be used in an unevaluated context}}
190 sizeof(co_await a); // expected-error {{cannot be used in an unevaluated context}}
191 typeid(co_await a); // expected-error {{cannot be used in an unevaluated context}}
192 decltype(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
193 sizeof(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
194 typeid(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
195}
196
197constexpr void constexpr_coroutine() {
198 co_yield 0; // expected-error {{'co_yield' cannot be used in a constexpr function}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000199}
200
201void varargs_coroutine(const char *, ...) {
Richard Smith9f690bd2015-10-27 06:02:45 +0000202 co_await a; // expected-error {{'co_await' cannot be used in a varargs function}}
203}
204
205struct outer {};
206
207namespace dependent_operator_co_await_lookup {
208 template<typename T> void await_template(T t) {
209 // no unqualified lookup results
210 co_await t; // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::not_awaitable'}}
211 // expected-error@-1 {{call to function 'operator co_await' that is neither visible in the template definition nor found by argument-dependent lookup}}
212 };
213 template void await_template(awaitable);
214
215 struct indirectly_awaitable { indirectly_awaitable(outer); };
216 awaitable operator co_await(indirectly_awaitable); // expected-note {{should be declared prior to}}
217 template void await_template(indirectly_awaitable);
218
219 struct not_awaitable {};
220 template void await_template(not_awaitable); // expected-note {{instantiation}}
221
222 template<typename T> void await_template_2(T t) {
223 // one unqualified lookup result
224 co_await t;
225 };
226 template void await_template(outer); // expected-note {{instantiation}}
227 template void await_template_2(outer);
Richard Smithcfd53b42015-10-22 06:13:50 +0000228}
Richard Smith10610f72015-11-20 22:57:24 +0000229
Richard Smith71d403e2015-11-22 07:33:28 +0000230struct yield_fn_tag {};
Gor Nishanov3e048bb2016-10-04 00:31:16 +0000231template <>
232struct std::experimental::coroutine_traits<void, yield_fn_tag> {
Richard Smith71d403e2015-11-22 07:33:28 +0000233 struct promise_type {
234 // FIXME: add an await_transform overload for functions
235 awaitable yield_value(int());
236 void return_value(int());
Richard Smith2af65c42015-11-24 02:34:39 +0000237
238 suspend_never initial_suspend();
239 suspend_never final_suspend();
240 void get_return_object();
Richard Smith71d403e2015-11-22 07:33:28 +0000241 };
242};
243
Richard Smith10610f72015-11-20 22:57:24 +0000244namespace placeholder {
Richard Smith71d403e2015-11-22 07:33:28 +0000245 awaitable f(), f(int); // expected-note 4{{possible target}}
246 int g(), g(int); // expected-note 2{{candidate}}
Richard Smith10610f72015-11-20 22:57:24 +0000247 void x() {
248 co_await f; // expected-error {{reference to overloaded function}}
249 }
250 void y() {
Richard Smith71d403e2015-11-22 07:33:28 +0000251 co_yield g; // expected-error {{no matching member function for call to 'yield_value'}}
Richard Smith10610f72015-11-20 22:57:24 +0000252 }
253 void z() {
254 co_await a;
Richard Smith71d403e2015-11-22 07:33:28 +0000255 co_return g; // expected-error {{address of overloaded function 'g' does not match required type 'int'}}
256 }
257
258 void x(yield_fn_tag) {
259 co_await f; // expected-error {{reference to overloaded function}}
260 }
261 void y(yield_fn_tag) {
262 co_yield g;
263 }
264 void z(yield_fn_tag) {
265 co_await a;
266 co_return g;
Richard Smith10610f72015-11-20 22:57:24 +0000267 }
268}
Richard Smith2af65c42015-11-24 02:34:39 +0000269
270struct bad_promise_1 {
271 suspend_always initial_suspend();
272 suspend_always final_suspend();
273};
274coro<bad_promise_1> missing_get_return_object() { // expected-error {{no member named 'get_return_object' in 'bad_promise_1'}}
275 co_await a;
276}
277
278struct bad_promise_2 {
279 coro<bad_promise_2> get_return_object();
280 // FIXME: We shouldn't offer a typo-correction here!
281 suspend_always final_suspend(); // expected-note {{here}}
282};
283coro<bad_promise_2> missing_initial_suspend() { // expected-error {{no member named 'initial_suspend' in 'bad_promise_2'}}
284 co_await a;
285}
286
287struct bad_promise_3 {
288 coro<bad_promise_3> get_return_object();
289 // FIXME: We shouldn't offer a typo-correction here!
290 suspend_always initial_suspend(); // expected-note {{here}}
291};
292coro<bad_promise_3> missing_final_suspend() { // expected-error {{no member named 'final_suspend' in 'bad_promise_3'}}
293 co_await a;
294}
295
296struct bad_promise_4 {
297 coro<bad_promise_4> get_return_object();
298 not_awaitable initial_suspend();
299 suspend_always final_suspend();
300};
301// FIXME: This diagnostic is terrible.
302coro<bad_promise_4> bad_initial_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
303 co_await a;
304}
305
306struct bad_promise_5 {
307 coro<bad_promise_5> get_return_object();
308 suspend_always initial_suspend();
309 not_awaitable final_suspend();
310};
311// FIXME: This diagnostic is terrible.
312coro<bad_promise_5> bad_final_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
313 co_await a;
314}
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000315
316
Gor Nishanov3e048bb2016-10-04 00:31:16 +0000317template<> struct std::experimental::coroutine_traits<int, int, const char**>
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000318{ using promise_type = promise; };
319
320int main(int, const char**) { // expected-error {{'main' cannot be a coroutine}}
321 co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}}
322}