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 { |
43 | 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 | }; |
52 | MyForLoopArrayAwaiter 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 | }; |
74 | ForLoopAwaiterBadBeginTransform 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> |
81 | ForLoopAwaiterBadBeginTransform 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 | }; |
108 | ForLoopAwaiterBadIncTransform 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> |
116 | ForLoopAwaiterBadIncTransform 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> |
127 | constexpr 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> |
151 | ForLoopAwaiterCoawaitLookup 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 | |