[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / CodeGenCoroutines / coro-await.cpp
blob8dd53a712b16f6d40f35a3765bcdaaa918b21509
1 // RUN: %clang_cc1 -no-enable-noundef-analysis -triple x86_64-unknown-linux-gnu -std=c++20 \
2 // RUN: -emit-llvm %s -o - -disable-llvm-passes -Wno-coroutine -Wno-unused | FileCheck %s
4 namespace std {
5 template <typename... T>
6 struct coroutine_traits;
8 template <typename Promise = void> struct coroutine_handle;
10 template <>
11 struct coroutine_handle<void> {
12 void *ptr;
13 static coroutine_handle from_address(void *);
14 void *address();
17 template <typename Promise>
18 struct coroutine_handle : coroutine_handle<> {
19 static coroutine_handle from_address(void *) noexcept;
22 } // namespace std
24 struct init_susp {
25 bool await_ready();
26 void await_suspend(std::coroutine_handle<>);
27 void await_resume();
29 struct final_susp {
30 bool await_ready() noexcept;
31 void await_suspend(std::coroutine_handle<>) noexcept;
32 void await_resume() noexcept;
35 struct suspend_always {
36 int stuff;
37 bool await_ready();
38 void await_suspend(std::coroutine_handle<>);
39 void await_resume();
42 template <>
43 struct std::coroutine_traits<void> {
44 struct promise_type {
45 void get_return_object();
46 init_susp initial_suspend();
47 final_susp final_suspend() noexcept;
48 void return_void();
52 // CHECK-LABEL: f0(
53 extern "C" void f0() {
54 // CHECK: %[[FRAME:.+]] = call ptr @llvm.coro.begin(
56 // See if initial_suspend was issued:
57 // ----------------------------------
58 // CHECK: call void @_ZNSt16coroutine_traitsIJvEE12promise_type15initial_suspendEv(
59 // CHECK-NEXT: call zeroext i1 @_ZN9init_susp11await_readyEv(ptr
60 // CHECK: %[[INITSP_ID:.+]] = call token @llvm.coro.save(
61 // CHECK: call i8 @llvm.coro.suspend(token %[[INITSP_ID]], i1 false)
63 co_await suspend_always{};
64 // See if we need to suspend:
65 // --------------------------
66 // CHECK: %[[READY:.+]] = call zeroext i1 @_ZN14suspend_always11await_readyEv(ptr {{[^,]*}} %[[AWAITABLE:.+]])
67 // CHECK: br i1 %[[READY]], label %[[READY_BB:.+]], label %[[SUSPEND_BB:.+]]
69 // If we are suspending:
70 // ---------------------
71 // CHECK: [[SUSPEND_BB]]:
72 // CHECK: %[[SUSPEND_ID:.+]] = call token @llvm.coro.save(
73 // ---------------------------
74 // Call coro.await.suspend
75 // ---------------------------
76 // CHECK-NEXT: call void @llvm.coro.await.suspend.void(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @f0.__await_suspend_wrapper__await)
77 // -------------------------
78 // Generate a suspend point:
79 // -------------------------
80 // CHECK-NEXT: %[[OUTCOME:.+]] = call i8 @llvm.coro.suspend(token %[[SUSPEND_ID]], i1 false)
81 // CHECK: switch i8 %[[OUTCOME]], label %[[RET_BB:.+]] [
82 // CHECK: i8 0, label %[[READY_BB]]
83 // CHECK: i8 1, label %[[CLEANUP_BB:.+]]
84 // CHECK: ]
86 // Cleanup code goes here:
87 // -----------------------
88 // CHECK: [[CLEANUP_BB]]:
90 // When coroutine is resumed, call await_resume
91 // --------------------------
92 // CHECK: [[READY_BB]]:
93 // CHECK: call void @_ZN14suspend_always12await_resumeEv(ptr {{[^,]*}} %[[AWAITABLE]])
95 // See if final_suspend was issued:
96 // ----------------------------------
97 // CHECK: call void @_ZNSt16coroutine_traitsIJvEE12promise_type13final_suspendEv(
98 // CHECK-NEXT: call zeroext i1 @_ZN10final_susp11await_readyEv(ptr
99 // CHECK: %[[FINALSP_ID:.+]] = call token @llvm.coro.save(
100 // CHECK: call i8 @llvm.coro.suspend(token %[[FINALSP_ID]], i1 true)
102 // Await suspend wrapper
103 // CHECK: define{{.*}} @f0.__await_suspend_wrapper__await(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]])
104 // CHECK: store ptr %[[AWAITABLE_ARG]], ptr %[[AWAITABLE_TMP:.+]],
105 // CHECK: store ptr %[[FRAME_ARG]], ptr %[[FRAME_TMP:.+]],
106 // CHECK: %[[AWAITABLE:.+]] = load ptr, ptr %[[AWAITABLE_TMP]]
107 // CHECK: %[[FRAME:.+]] = load ptr, ptr %[[FRAME_TMP]]
108 // CHECK: call ptr @_ZNSt16coroutine_handleINSt16coroutine_traitsIJvEE12promise_typeEE12from_addressEPv(ptr %[[FRAME]])
109 // ... many lines of code to coerce coroutine_handle into an ptr scalar
110 // CHECK: %[[CH:.+]] = load ptr, ptr %{{.+}}
111 // CHECK: call void @_ZN14suspend_always13await_suspendESt16coroutine_handleIvE(ptr {{[^,]*}} %[[AWAITABLE]], ptr %[[CH]])
114 struct suspend_maybe {
115 float stuff;
116 ~suspend_maybe();
117 bool await_ready();
118 bool await_suspend(std::coroutine_handle<>);
119 void await_resume();
122 template <>
123 struct std::coroutine_traits<void, int> {
124 struct promise_type {
125 void get_return_object();
126 init_susp initial_suspend();
127 final_susp final_suspend() noexcept;
128 void return_void();
129 suspend_maybe yield_value(int);
133 // CHECK-LABEL: f1(
134 extern "C" void f1(int) {
135 // CHECK: %[[PROMISE:.+]] = alloca %"struct.std::coroutine_traits<void, int>::promise_type"
136 // CHECK: %[[FRAME:.+]] = call ptr @llvm.coro.begin(
137 co_yield 42;
138 // CHECK: call void @_ZNSt16coroutine_traitsIJviEE12promise_type11yield_valueEi(ptr dead_on_unwind writable sret(%struct.suspend_maybe) align 4 %[[AWAITER:.+]], ptr {{[^,]*}} %[[PROMISE]], i32 42)
140 // See if we need to suspend:
141 // --------------------------
142 // CHECK: %[[READY:.+]] = call zeroext i1 @_ZN13suspend_maybe11await_readyEv(ptr {{[^,]*}} %[[AWAITABLE:.+]])
143 // CHECK: br i1 %[[READY]], label %[[READY_BB:.+]], label %[[SUSPEND_BB:.+]]
145 // If we are suspending:
146 // ---------------------
147 // CHECK: [[SUSPEND_BB]]:
148 // CHECK: %[[SUSPEND_ID:.+]] = call token @llvm.coro.save(
149 // ---------------------------
150 // Call coro.await.suspend
151 // ---------------------------
152 // CHECK-NEXT: %[[YES:.+]] = call i1 @llvm.coro.await.suspend.bool(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @f1.__await_suspend_wrapper__yield)
153 // -------------------------------------------
154 // See if await_suspend decided not to suspend
155 // -------------------------------------------
156 // CHECK: br i1 %[[YES]], label %[[SUSPEND_PLEASE:.+]], label %[[READY_BB]]
158 // CHECK: [[SUSPEND_PLEASE]]:
159 // CHECK: call i8 @llvm.coro.suspend(token %[[SUSPEND_ID]], i1 false)
161 // CHECK: [[READY_BB]]:
162 // CHECK: call void @_ZN13suspend_maybe12await_resumeEv(ptr {{[^,]*}} %[[AWAITABLE]])
164 // Await suspend wrapper
165 // CHECK: define {{.*}} i1 @f1.__await_suspend_wrapper__yield(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]])
166 // CHECK: store ptr %[[AWAITABLE_ARG]], ptr %[[AWAITABLE_TMP:.+]],
167 // CHECK: store ptr %[[FRAME_ARG]], ptr %[[FRAME_TMP:.+]],
168 // CHECK: %[[AWAITABLE:.+]] = load ptr, ptr %[[AWAITABLE_TMP]]
169 // CHECK: %[[FRAME:.+]] = load ptr, ptr %[[FRAME_TMP]]
170 // CHECK: call ptr @_ZNSt16coroutine_handleINSt16coroutine_traitsIJviEE12promise_typeEE12from_addressEPv(ptr %[[FRAME]])
171 // ... many lines of code to coerce coroutine_handle into an ptr scalar
172 // CHECK: %[[CH:.+]] = load ptr, ptr %{{.+}}
173 // CHECK: %[[YES:.+]] = call zeroext i1 @_ZN13suspend_maybe13await_suspendESt16coroutine_handleIvE(ptr {{[^,]*}} %[[AWAITABLE]], ptr %[[CH]])
174 // CHECK-NEXT: ret i1 %[[YES]]
177 struct ComplexAwaiter {
178 template <typename F> void await_suspend(F);
179 bool await_ready();
180 _Complex float await_resume();
182 extern "C" void UseComplex(_Complex float);
184 // CHECK-LABEL: @TestComplex(
185 extern "C" void TestComplex() {
186 UseComplex(co_await ComplexAwaiter{});
187 // CHECK: call <2 x float> @_ZN14ComplexAwaiter12await_resumeEv(ptr
188 // CHECK: call void @UseComplex(<2 x float> %{{.+}})
190 co_await ComplexAwaiter{};
191 // CHECK: call <2 x float> @_ZN14ComplexAwaiter12await_resumeEv(ptr
193 _Complex float Val = co_await ComplexAwaiter{};
194 // CHECK: call <2 x float> @_ZN14ComplexAwaiter12await_resumeEv(ptr
197 struct Aggr { int X, Y, Z; ~Aggr(); };
198 struct AggrAwaiter {
199 template <typename F> void await_suspend(F);
200 bool await_ready();
201 Aggr await_resume();
204 extern "C" void Whatever();
205 extern "C" void UseAggr(Aggr&&);
207 // FIXME: Once the cleanup code is in, add testing that destructors for Aggr
208 // are invoked properly on the cleanup branches.
210 // CHECK-LABEL: @TestAggr(
211 extern "C" void TestAggr() {
212 UseAggr(co_await AggrAwaiter{});
213 Whatever();
214 // CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(ptr dead_on_unwind writable sret(%struct.Aggr) align 4 %[[AwaitResume:.+]],
215 // CHECK: call void @UseAggr(ptr nonnull align 4 dereferenceable(12) %[[AwaitResume]])
216 // CHECK: call void @_ZN4AggrD1Ev(ptr {{[^,]*}} %[[AwaitResume]])
217 // CHECK: call void @Whatever()
219 co_await AggrAwaiter{};
220 Whatever();
221 // CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(ptr dead_on_unwind writable sret(%struct.Aggr) align 4 %[[AwaitResume2:.+]],
222 // CHECK: call void @_ZN4AggrD1Ev(ptr {{[^,]*}} %[[AwaitResume2]])
223 // CHECK: call void @Whatever()
225 Aggr Val = co_await AggrAwaiter{};
226 Whatever();
227 // CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(ptr dead_on_unwind writable sret(%struct.Aggr) align 4 %[[AwaitResume3:.+]],
228 // CHECK: call void @Whatever()
229 // CHECK: call void @_ZN4AggrD1Ev(ptr {{[^,]*}} %[[AwaitResume3]])
232 struct ScalarAwaiter {
233 template <typename F> void await_suspend(F);
234 bool await_ready();
235 int await_resume();
238 extern "C" void UseScalar(int);
240 // CHECK-LABEL: @TestScalar(
241 extern "C" void TestScalar() {
242 UseScalar(co_await ScalarAwaiter{});
243 // CHECK: %[[Result:.+]] = call i32 @_ZN13ScalarAwaiter12await_resumeEv(ptr
244 // CHECK: call void @UseScalar(i32 %[[Result]])
246 int Val = co_await ScalarAwaiter{};
247 // CHECK: %[[Result2:.+]] = call i32 @_ZN13ScalarAwaiter12await_resumeEv(ptr
248 // CHECK: store i32 %[[Result2]], ptr %[[TMP_EXPRCLEANUP:.+]],
249 // CHECK: %[[TMP:.+]] = load i32, ptr %[[TMP_EXPRCLEANUP]],
250 // CHECK: store i32 %[[TMP]], ptr %Val,
252 co_await ScalarAwaiter{};
253 // CHECK: call i32 @_ZN13ScalarAwaiter12await_resumeEv(ptr
256 // Test operator co_await codegen.
257 enum class MyInt: int {};
258 ScalarAwaiter operator co_await(MyInt);
260 struct MyAgg {
261 AggrAwaiter operator co_await();
264 // CHECK-LABEL: @TestOpAwait(
265 extern "C" void TestOpAwait() {
266 co_await MyInt(42);
267 // CHECK: call void @_Zaw5MyInt(i32 42)
268 // CHECK: call i32 @_ZN13ScalarAwaiter12await_resumeEv(ptr {{[^,]*}} %
270 co_await MyAgg{};
271 // CHECK: call void @_ZN5MyAggawEv(ptr {{[^,]*}} %
272 // CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(ptr dead_on_unwind writable sret(%struct.Aggr) align 4 %
275 // CHECK-LABEL: EndlessLoop(
276 extern "C" void EndlessLoop() {
277 // CHECK: %[[FRAME:.+]] = call ptr @llvm.coro.begin(
279 // See if initial_suspend was issued:
280 // ----------------------------------
281 // CHECK: call void @_ZNSt16coroutine_traitsIJvEE12promise_type15initial_suspendEv(
282 // CHECK-NEXT: call zeroext i1 @_ZN9init_susp11await_readyEv(ptr
284 for (;;)
285 co_await suspend_always{};
287 // Verify that final_suspend was NOT issued:
288 // ----------------------------------
289 // CHECK-NOT: call void @_ZNSt16coroutine_traitsIJvEE12promise_type13final_suspendEv(
290 // CHECK-NOT: call zeroext i1 @_ZN10final_susp11await_readyEv(ptr
293 // Verifies that we don't crash when awaiting on an lvalue.
294 // CHECK-LABEL: @_Z11AwaitLValuev(
295 void AwaitLValue() {
296 suspend_always lval;
297 co_await lval;
300 struct RefTag { };
302 struct AwaitResumeReturnsLValue {
303 bool await_ready();
304 void await_suspend(std::coroutine_handle<>);
305 RefTag& await_resume();
308 template <>
309 struct std::coroutine_traits<void, double> {
310 struct promise_type {
311 void get_return_object();
312 init_susp initial_suspend();
313 final_susp final_suspend() noexcept;
314 void return_void();
315 AwaitResumeReturnsLValue yield_value(int);
319 // Verifies that we don't crash when returning an lvalue from an await_resume()
320 // expression.
321 // CHECK-LABEL: define{{.*}} void @_Z18AwaitReturnsLValued(double %0)
322 void AwaitReturnsLValue(double) {
323 AwaitResumeReturnsLValue a;
324 // CHECK: %[[AVAR:.+]] = alloca %struct.AwaitResumeReturnsLValue,
325 // CHECK: %[[XVAR:.+]] = alloca ptr,
327 // CHECK: %[[YVAR:.+]] = alloca ptr,
328 // CHECK-NEXT: %[[TMP1:.+]] = alloca %struct.AwaitResumeReturnsLValue,
330 // CHECK: %[[TMP_EXPRCLEANUP1:.+]] = alloca ptr,
331 // CHECK: %[[ZVAR:.+]] = alloca ptr,
332 // CHECK-NEXT: %[[TMP2:.+]] = alloca %struct.AwaitResumeReturnsLValue,
333 // CHECK: %[[TMP_EXPRCLEANUP2:.+]] = alloca ptr,
335 // CHECK: %[[RES1:.+]] = call nonnull align 1 dereferenceable({{.*}}) ptr @_ZN24AwaitResumeReturnsLValue12await_resumeEv(ptr {{[^,]*}} %[[AVAR]])
336 // CHECK-NEXT: store ptr %[[RES1]], ptr %[[XVAR]],
337 RefTag& x = co_await a;
339 // CHECK: %[[RES2:.+]] = call nonnull align 1 dereferenceable({{.*}}) ptr @_ZN24AwaitResumeReturnsLValue12await_resumeEv(ptr {{[^,]*}} %[[TMP1]])
340 // CHECK-NEXT: store ptr %[[RES2]], ptr %[[TMP_EXPRCLEANUP1]],
341 // CHECK: %[[LOAD_TMP1:.+]] = load ptr, ptr %[[TMP_EXPRCLEANUP1]],
342 // CHECK: store ptr %[[LOAD_TMP1]], ptr %[[YVAR]],
344 RefTag& y = co_await AwaitResumeReturnsLValue{};
345 // CHECK: %[[RES3:.+]] = call nonnull align 1 dereferenceable({{.*}}) ptr @_ZN24AwaitResumeReturnsLValue12await_resumeEv(ptr {{[^,]*}} %[[TMP2]])
346 // CHECK-NEXT: store ptr %[[RES3]], ptr %[[TMP_EXPRCLEANUP2]],
347 // CHECK: %[[LOAD_TMP2:.+]] = load ptr, ptr %[[TMP_EXPRCLEANUP2]],
348 // CHECK: store ptr %[[LOAD_TMP2]], ptr %[[ZVAR]],
349 RefTag& z = co_yield 42;
352 struct TailCallAwait {
353 bool await_ready();
354 std::coroutine_handle<> await_suspend(std::coroutine_handle<>);
355 void await_resume();
358 // CHECK-LABEL: @TestTailcall(
359 extern "C" void TestTailcall() {
360 // CHECK: %[[PROMISE:.+]] = alloca %"struct.std::coroutine_traits<void>::promise_type"
361 // CHECK: %[[FRAME:.+]] = call ptr @llvm.coro.begin(
362 co_await TailCallAwait{};
363 // CHECK: %[[READY:.+]] = call zeroext i1 @_ZN13TailCallAwait11await_readyEv(ptr {{[^,]*}} %[[AWAITABLE:.+]])
364 // CHECK: br i1 %[[READY]], label %[[READY_BB:.+]], label %[[SUSPEND_BB:.+]]
366 // If we are suspending:
367 // ---------------------
368 // CHECK: [[SUSPEND_BB]]:
369 // CHECK: %[[SUSPEND_ID:.+]] = call token @llvm.coro.save(
370 // ---------------------------
371 // Call coro.await.suspend
372 // ---------------------------
373 // Note: The call must not be nounwind since the resumed function could throw.
374 // CHECK-NEXT: call void @llvm.coro.await.suspend.handle(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @TestTailcall.__await_suspend_wrapper__await){{$}}
375 // CHECK-NEXT: %[[OUTCOME:.+]] = call i8 @llvm.coro.suspend(token %[[SUSPEND_ID]], i1 false)
376 // CHECK-NEXT: switch i8 %[[OUTCOME]], label %[[RET_BB:.+]] [
377 // CHECK-NEXT: i8 0, label %[[READY_BB]]
378 // CHECK-NEXT: i8 1, label %{{.+}}
379 // CHECK-NEXT: ]
381 // Await suspend wrapper
382 // CHECK: define {{.*}} ptr @TestTailcall.__await_suspend_wrapper__await(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]])
383 // CHECK: store ptr %[[AWAITABLE_ARG]], ptr %[[AWAITABLE_TMP:.+]],
384 // CHECK: store ptr %[[FRAME_ARG]], ptr %[[FRAME_TMP:.+]],
385 // CHECK: %[[AWAITABLE:.+]] = load ptr, ptr %[[AWAITABLE_TMP]]
386 // CHECK: %[[FRAME:.+]] = load ptr, ptr %[[FRAME_TMP]]
387 // CHECK: call ptr @_ZNSt16coroutine_handleINSt16coroutine_traitsIJvEE12promise_typeEE12from_addressEPv(ptr %[[FRAME]])
388 // ... many lines of code to coerce coroutine_handle into an ptr scalar
389 // CHECK: %[[CH:.+]] = load ptr, ptr %{{.+}}
390 // CHECK-NEXT: %[[RESULT:.+]] = call ptr @_ZN13TailCallAwait13await_suspendESt16coroutine_handleIvE(ptr {{[^,]*}} %[[AWAITABLE]], ptr %[[CH]])
391 // CHECK-NEXT: %[[COERCE:.+]] = getelementptr inbounds nuw %"struct.std::coroutine_handle", ptr %[[TMP:.+]], i32 0, i32 0
392 // CHECK-NEXT: store ptr %[[RESULT]], ptr %[[COERCE]]
393 // CHECK-NEXT: %[[ADDR:.+]] = call ptr @_ZNSt16coroutine_handleIvE7addressEv(ptr {{[^,]*}} %[[TMP]])
394 // CHECK-NEXT: ret ptr %[[ADDR]]