Home | History | Annotate | Download | only in SemaCXX
      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 {
     10   bool await_ready() { return false; }
     11   void await_suspend() {}
     12   void await_resume() {}
     13 };
     14 
     15 struct suspend_never {
     16   bool await_ready() { return true; }
     17   void await_suspend() {}
     18   void await_resume() {}
     19 };
     20 
     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 
     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 
     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; };
     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 };
     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.
     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 
     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 
     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 
    104 void mixed_yield() {
    105   co_yield 0; // expected-note {{use of 'co_yield'}}
    106   return; // expected-error {{not allowed in coroutine}}
    107 }
    108 
    109 void mixed_await() {
    110   co_await a; // expected-note {{use of 'co_await'}}
    111   return; // expected-error {{not allowed in coroutine}}
    112 }
    113 
    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 
    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 {
    127   CtorDtor() {
    128     co_yield 0; // expected-error {{'co_yield' cannot be used in a constructor}}
    129   }
    130   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   }
    134   ~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.
    138   void operator=(CtorDtor&) {
    139     co_yield 0;
    140   }
    141 };
    142 
    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 
    152 constexpr void constexpr_coroutine() {
    153   co_yield 0; // expected-error {{'co_yield' cannot be used in a constexpr function}}
    154 }
    155 
    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 {
    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 
    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}}
    201   void x() {
    202     co_await f; // expected-error {{reference to overloaded function}}
    203   }
    204   void y() {
    205     co_yield g; // expected-error {{no matching member function for call to 'yield_value'}}
    206   }
    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 
    212   void x(yield_fn_tag) {
    213     co_await f; // expected-error {{reference to overloaded function}}
    214   }
    215   void y(yield_fn_tag) {
    216     co_yield g;
    217   }
    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 };
    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 };
    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 };
    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.
    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.
    266 coro<bad_promise_5> bad_final_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
    267   co_await a;
    268 }
    269