1 // RUN: %clang_cc1 --std=c++20 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
3 #include "Inputs/coroutine.h"
6 Printy(const char *name
) : name(name
) {}
13 std::coroutine_handle
<promise_type
> handle
;
15 if (handle
) handle
.destroy();
19 struct coroutine::promise_type
{
20 coroutine
get_return_object() {
21 return {std::coroutine_handle
<promise_type
>::from_promise(*this)};
23 std::suspend_never
initial_suspend() noexcept
{ return {}; }
24 std::suspend_always
final_suspend() noexcept
{ return {}; }
26 void unhandled_exception() {}
29 struct Awaiter
: std::suspend_always
{
30 Printy
await_resume() { return {"awaited"}; }
33 int foo() { return 2; }
35 coroutine
ArrayInitCoro() {
37 // - We do the necessary stores for array cleanups.
38 // - Array cleanups are called by await.cleanup.
39 // - We activate the cleanup after the first element and deactivate it in await.ready (see cleanup.isactive).
41 // CHECK-LABEL: define dso_local void @_Z13ArrayInitCorov
42 // CHECK: %arrayinit.endOfInit = alloca ptr, align 8
43 // CHECK: %cleanup.isactive = alloca i1, align 1
46 // CHECK: store i1 true, ptr %cleanup.isactive.reload.addr, align 1
47 // CHECK-NEXT: store ptr %arr.reload.addr, ptr %arrayinit.endOfInit.reload.addr, align 8
48 // CHECK-NEXT: call void @_ZN6PrintyC1EPKc(ptr noundef nonnull align 8 dereferenceable(8) %arr.reload.addr, ptr noundef @.str)
49 // CHECK-NEXT: %arrayinit.element = getelementptr inbounds %struct.Printy, ptr %arr.reload.addr, i64 1
50 // CHECK-NEXT: %arrayinit.element.spill.addr = getelementptr inbounds %_Z13ArrayInitCorov.Frame, ptr %0, i32 0, i32 10
51 // CHECK-NEXT: store ptr %arrayinit.element, ptr %arrayinit.element.spill.addr, align 8
52 // CHECK-NEXT: store ptr %arrayinit.element, ptr %arrayinit.endOfInit.reload.addr, align 8
54 // CHECK-NEXT: @_ZNSt14suspend_always11await_readyEv
55 // CHECK-NEXT: br i1 %{{.+}}, label %await.ready, label %CoroSave30
57 // CHECK: await.cleanup: ; preds = %AfterCoroSuspend{{.*}}
58 // CHECK-NEXT: br label %cleanup{{.*}}.from.await.cleanup
60 // CHECK: cleanup{{.*}}.from.await.cleanup: ; preds = %await.cleanup
61 // CHECK: br label %cleanup{{.*}}
63 // CHECK: await.ready:
64 // CHECK-NEXT: %arrayinit.element.reload.addr = getelementptr inbounds %_Z13ArrayInitCorov.Frame, ptr %0, i32 0, i32 10
65 // CHECK-NEXT: %arrayinit.element.reload = load ptr, ptr %arrayinit.element.reload.addr, align 8
66 // CHECK-NEXT: call void @_ZN7Awaiter12await_resumeEv
67 // CHECK-NEXT: store i1 false, ptr %cleanup.isactive.reload.addr, align 1
68 // CHECK-NEXT: br label %cleanup{{.*}}.from.await.ready
70 // CHECK: cleanup{{.*}}: ; preds = %cleanup{{.*}}.from.await.ready, %cleanup{{.*}}.from.await.cleanup
71 // CHECK: %cleanup.is_active = load i1, ptr %cleanup.isactive.reload.addr, align 1
72 // CHECK-NEXT: br i1 %cleanup.is_active, label %cleanup.action, label %cleanup.done
74 // CHECK: cleanup.action:
75 // CHECK: %arraydestroy.isempty = icmp eq ptr %arr.reload.addr, %{{.*}}
76 // CHECK-NEXT: br i1 %arraydestroy.isempty, label %arraydestroy.done{{.*}}, label %arraydestroy.body.from.cleanup.action
77 // Ignore rest of the array cleanup.
80 coroutine
ArrayInitWithCoReturn() {
81 // CHECK-LABEL: define dso_local void @_Z21ArrayInitWithCoReturnv
82 // Verify that we start to emit the array destructor.
83 // CHECK: %arrayinit.endOfInit = alloca ptr, align 8
84 Printy arr
[2] = {"a", ({