blob: 4d999ea7db5e575baf1e657c4c9951d10978bd39 [file] [log] [blame]
Eric Fiselierb936a392017-06-14 03:24:55 +00001// 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
6using namespace std::experimental;
7
8
9template <class Begin>
10struct Awaiter {
11 bool await_ready();
12 void await_suspend(coroutine_handle<>);
13 Begin await_resume();
14};
15
16template <class Iter> struct BeginTag { BeginTag() = delete; };
17template <class Iter> struct IncTag { IncTag() = delete; };
18
19template <class Iter, bool Delete = false>
20struct CoawaitTag { CoawaitTag() = delete; };
21
22template <class T>
23struct 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};
32template <class T> bool operator==(Iter<T>, Iter<T>);
33template <class T> bool operator!=(Iter<T>, Iter<T>);
34
35template <class T>
36struct Range {
37 BeginTag<Iter<T>> begin();
38 Iter<T> end();
39};
40
41struct 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};
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
59struct 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};
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}
80template <class 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}
87template ForLoopAwaiterBadBeginTransform bad_begin_template(int); // expected-note {{requested here}}
88
89template <class Iter>
90Awaiter<Iter> operator co_await(CoawaitTag<Iter, true>) = delete;
91// expected-note@-1 1+ {{explicitly deleted}}
92
93struct 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};
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
115template <class 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}
122template 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.
126template <class 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
133namespace NS {
134struct 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
148using NS::ForLoopAwaiterCoawaitLookup;
149
150template <class 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}
156template 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.
160namespace NS2 {
161template <class Iter>
162Awaiter<Iter> operator co_await(CoawaitTag<Iter, false>);
163}
164using NS2::operator co_await;
165template ForLoopAwaiterCoawaitLookup test_coawait_lookup(long);