1 // RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts \ 2 // RUN: -fsyntax-only -Wignored-qualifiers -Wno-error=return-type -verify \ 3 // RUN: -fblocks 4 #include "Inputs/std-coroutine.h" 5 6 using namespace std::experimental; 7 8 9 template <class Begin> 10 struct Awaiter { 11 bool await_ready(); 12 void await_suspend(coroutine_handle<>); 13 Begin await_resume(); 14 }; 15 16 template <class Iter> struct BeginTag { BeginTag() = delete; }; 17 template <class Iter> struct IncTag { IncTag() = delete; }; 18 19 template <class Iter, bool Delete = false> 20 struct CoawaitTag { CoawaitTag() = delete; }; 21 22 template <class T> 23 struct Iter { 24 using value_type = T; 25 using reference = T &; 26 using pointer = T *; 27 28 IncTag<Iter> operator++(); 29 reference operator*(); 30 pointer operator->(); 31 }; 32 template <class T> bool operator==(Iter<T>, Iter<T>); 33 template <class T> bool operator!=(Iter<T>, Iter<T>); 34 35 template <class T> 36 struct Range { 37 BeginTag<Iter<T>> begin(); 38 Iter<T> end(); 39 }; 40 41 struct MyForLoopArrayAwaiter { 42 struct promise_type { get_return_objectMyForLoopArrayAwaiter::promise_type43 MyForLoopArrayAwaiter get_return_object() { return {}; } 44 void return_void(); 45 void unhandled_exception(); 46 suspend_never initial_suspend(); 47 suspend_never final_suspend(); 48 template <class T> 49 Awaiter<T *> await_transform(T *) = delete; // expected-note {{explicitly deleted}} 50 }; 51 }; g()52MyForLoopArrayAwaiter g() { 53 int arr[10] = {0}; 54 for co_await(auto i : arr) {} 55 // expected-error@-1 {{call to deleted member function 'await_transform'}} 56 // expected-note@-2 {{'await_transform' implicitly required by 'co_await' here}} 57 } 58 59 struct ForLoopAwaiterBadBeginTransform { 60 struct promise_type { 61 ForLoopAwaiterBadBeginTransform get_return_object(); 62 void return_void(); 63 void unhandled_exception(); 64 suspend_never initial_suspend(); 65 suspend_never final_suspend(); 66 67 template <class T> 68 Awaiter<T> await_transform(BeginTag<T>) = delete; // expected-note 1+ {{explicitly deleted}} 69 70 template <class T> 71 CoawaitTag<T> await_transform(IncTag<T>); // expected-note 1+ {{candidate}} 72 }; 73 }; bad_begin()74ForLoopAwaiterBadBeginTransform bad_begin() { 75 Range<int> R; 76 for co_await(auto i : R) {} 77 // expected-error@-1 {{call to deleted member function 'await_transform'}} 78 // expected-note@-2 {{'await_transform' implicitly required by 'co_await' here}} 79 } 80 template <class Dummy> bad_begin_template(Dummy)81ForLoopAwaiterBadBeginTransform bad_begin_template(Dummy) { 82 Range<Dummy> R; 83 for co_await(auto i : R) {} 84 // expected-error@-1 {{call to deleted member function 'await_transform'}} 85 // expected-note@-2 {{'await_transform' implicitly required by 'co_await' here}} 86 } 87 template ForLoopAwaiterBadBeginTransform bad_begin_template(int); // expected-note {{requested here}} 88 89 template <class Iter> 90 Awaiter<Iter> operator co_await(CoawaitTag<Iter, true>) = delete; 91 // expected-note@-1 1+ {{explicitly deleted}} 92 93 struct ForLoopAwaiterBadIncTransform { 94 struct promise_type { 95 ForLoopAwaiterBadIncTransform get_return_object(); 96 void return_void(); 97 void unhandled_exception(); 98 suspend_never initial_suspend(); 99 suspend_never final_suspend(); 100 101 template <class T> 102 Awaiter<T> await_transform(BeginTag<T> e); 103 104 template <class T> 105 CoawaitTag<T, true> await_transform(IncTag<T>); 106 }; 107 }; bad_inc_transform()108ForLoopAwaiterBadIncTransform bad_inc_transform() { 109 Range<float> R; 110 for co_await(auto i : R) {} 111 // expected-error@-1 {{overload resolution selected deleted operator 'co_await'}} 112 // expected-note@-2 {{in implicit call to 'operator++' for iterator of type 'Range<float>'}} 113 } 114 115 template <class Dummy> bad_inc_transform_template(Dummy)116ForLoopAwaiterBadIncTransform bad_inc_transform_template(Dummy) { 117 Range<Dummy> R; 118 for co_await(auto i : R) {} 119 // expected-error@-1 {{overload resolution selected deleted operator 'co_await'}} 120 // expected-note@-2 {{in implicit call to 'operator++' for iterator of type 'Range<long>'}} 121 } 122 template ForLoopAwaiterBadIncTransform bad_inc_transform_template(long); // expected-note {{requested here}} 123 124 // Ensure we mark and check the function as a coroutine even if it's 125 // never instantiated. 126 template <class T> never_instant(T)127constexpr void never_instant(T) { 128 static_assert(sizeof(T) != sizeof(T), "function should not be instantiated"); 129 for co_await(auto i : foo(T{})) {} 130 // expected-error@-1 {{'co_await' cannot be used in a constexpr function}} 131 } 132 133 namespace NS { 134 struct ForLoopAwaiterCoawaitLookup { 135 struct promise_type { 136 ForLoopAwaiterCoawaitLookup get_return_object(); 137 void return_void(); 138 void unhandled_exception(); 139 suspend_never initial_suspend(); 140 suspend_never final_suspend(); 141 template <class T> 142 CoawaitTag<T, false> await_transform(BeginTag<T> e); 143 template <class T> 144 Awaiter<T> await_transform(IncTag<T>); 145 }; 146 }; 147 } // namespace NS 148 using NS::ForLoopAwaiterCoawaitLookup; 149 150 template <class T> test_coawait_lookup(T)151ForLoopAwaiterCoawaitLookup test_coawait_lookup(T) { 152 Range<T> R; 153 for co_await(auto i : R) {} 154 // expected-error@-1 {{no member named 'await_ready' in 'CoawaitTag<Iter<int>, false>'}} 155 } 156 template ForLoopAwaiterCoawaitLookup test_coawait_lookup(int); // expected-note {{requested here}} 157 158 // FIXME: This test should fail as well since the newly declared operator co_await 159 // should not be found by lookup. 160 namespace NS2 { 161 template <class Iter> 162 Awaiter<Iter> operator co_await(CoawaitTag<Iter, false>); 163 } 164 using NS2::operator co_await; 165 template ForLoopAwaiterCoawaitLookup test_coawait_lookup(long); 166