1 | // RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts -fsyntax-only -Wignored-qualifiers -Wno-error=return-type -verify -fblocks -Wall -Wextra -Wno-error=unreachable-code |
2 | #include "Inputs/std-coroutine.h" |
3 | |
4 | using std::experimental::suspend_always; |
5 | using std::experimental::suspend_never; |
6 | |
7 | struct awaitable { |
8 | bool await_ready(); |
9 | void await_suspend(std::experimental::coroutine_handle<>); // FIXME: coroutine_handle |
10 | void await_resume(); |
11 | } a; |
12 | |
13 | struct promise_void { |
14 | void get_return_object(); |
15 | suspend_always initial_suspend(); |
16 | suspend_always final_suspend(); |
17 | void return_void(); |
18 | void unhandled_exception(); |
19 | }; |
20 | |
21 | struct promise_void_return_value { |
22 | void get_return_object(); |
23 | suspend_always initial_suspend(); |
24 | suspend_always final_suspend(); |
25 | void unhandled_exception(); |
26 | void return_value(int); |
27 | }; |
28 | |
29 | struct VoidTagNoReturn { |
30 | struct promise_type { |
31 | VoidTagNoReturn get_return_object(); |
32 | suspend_always initial_suspend(); |
33 | suspend_always final_suspend(); |
34 | void unhandled_exception(); |
35 | }; |
36 | }; |
37 | |
38 | struct VoidTagReturnValue { |
39 | struct promise_type { |
40 | VoidTagReturnValue get_return_object(); |
41 | suspend_always initial_suspend(); |
42 | suspend_always final_suspend(); |
43 | void unhandled_exception(); |
44 | void return_value(int); |
45 | }; |
46 | }; |
47 | |
48 | struct VoidTagReturnVoid { |
49 | struct promise_type { |
50 | VoidTagReturnVoid get_return_object(); |
51 | suspend_always initial_suspend(); |
52 | suspend_always final_suspend(); |
53 | void unhandled_exception(); |
54 | void return_void(); |
55 | }; |
56 | }; |
57 | |
58 | struct promise_float { |
59 | float get_return_object(); |
60 | suspend_always initial_suspend(); |
61 | suspend_always final_suspend(); |
62 | void return_void(); |
63 | void unhandled_exception(); |
64 | }; |
65 | |
66 | struct promise_int { |
67 | int get_return_object(); |
68 | suspend_always initial_suspend(); |
69 | suspend_always final_suspend(); |
70 | void return_value(int); |
71 | void unhandled_exception(); |
72 | }; |
73 | |
74 | template <> |
75 | struct std::experimental::coroutine_traits<void> { using promise_type = promise_void; }; |
76 | |
77 | template <typename T1> |
78 | struct std::experimental::coroutine_traits<void, T1> { using promise_type = promise_void_return_value; }; |
79 | |
80 | template <typename... T> |
81 | struct std::experimental::coroutine_traits<float, T...> { using promise_type = promise_float; }; |
82 | |
83 | template <typename... T> |
84 | struct std::experimental::coroutine_traits<int, T...> { using promise_type = promise_int; }; |
85 | |
86 | void test0() { co_await a; } |
87 | float test1() { co_await a; } |
88 | |
89 | int test2() { |
90 | co_await a; |
91 | } // expected-warning {{control reaches end of coroutine; which is undefined behavior because the promise type 'std::experimental::coroutine_traits<int>::promise_type' (aka 'promise_int') does not declare 'return_void()'}} |
92 | |
93 | int test2a(bool b) { |
94 | if (b) |
95 | co_return 42; |
96 | } // expected-warning {{control may reach end of coroutine; which is undefined behavior because the promise type 'std::experimental::coroutine_traits<int, bool>::promise_type' (aka 'promise_int') does not declare 'return_void()'}} |
97 | |
98 | int test3() { |
99 | co_await a; |
100 | b: |
101 | goto b; |
102 | } |
103 | |
104 | int test4() { |
105 | co_return 42; |
106 | } |
107 | |
108 | void test5(int) { |
109 | co_await a; |
110 | } // expected-warning {{control reaches end of coroutine; which is undefined behavior because}} |
111 | |
112 | void test6(int x) { |
113 | if (x) |
114 | co_return 42; |
115 | } // expected-warning {{control may reach end of coroutine; which is undefined behavior because}} |
116 | |
117 | void test7(int y) { |
118 | if (y) |
119 | co_return 42; |
120 | else |
121 | co_return 101; |
122 | } |
123 | |
124 | VoidTagReturnVoid test8() { |
125 | co_await a; |
126 | } |
127 | |
128 | VoidTagReturnVoid test9(bool b) { |
129 | if (b) |
130 | co_return; |
131 | } |
132 | |
133 | VoidTagReturnValue test10() { |
134 | co_await a; |
135 | } // expected-warning {{control reaches end of coroutine}} |
136 | |
137 | VoidTagReturnValue test11(bool b) { |
138 | if (b) |
139 | co_return 42; |
140 | } // expected-warning {{control may reach end of coroutine}} |
141 | |