1 // RUN: %clang_cc1 -no-opaque-pointers -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++14 -O1 -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s
3 #include "Inputs/coroutine-exp-namespace.h"
5 namespace coro
= std::experimental::coroutines_v1
;
9 Task
get_return_object() noexcept
{
10 return Task
{coro::coroutine_handle
<promise_type
>::from_promise(*this)};
13 void return_void() noexcept
{}
15 struct final_awaiter
{
16 bool await_ready() noexcept
{ return false; }
17 coro::coroutine_handle
<> await_suspend(coro::coroutine_handle
<promise_type
> h
) noexcept
{
21 void await_resume() noexcept
{}
24 void unhandled_exception() noexcept
{}
26 final_awaiter
final_suspend() noexcept
{ return {}; }
28 coro::suspend_always
initial_suspend() noexcept
{ return {}; }
30 template <typename Awaitable
>
31 auto await_transform(Awaitable
&&awaitable
) {
32 return awaitable
.co_viaIfAsync();
36 using handle_t
= coro::coroutine_handle
<promise_type
>;
40 explicit Awaiter(handle_t coro
) noexcept
;
41 Awaiter(Awaiter
&&other
) noexcept
;
42 Awaiter(const Awaiter
&) = delete;
45 bool await_ready() noexcept
{ return false; }
46 handle_t
await_suspend(coro::coroutine_handle
<> continuation
) noexcept
;
53 Task(handle_t coro
) noexcept
: coro_(coro
) {}
57 Task(const Task
&t
) = delete;
58 Task(Task
&&t
) noexcept
;
60 Task
&operator=(Task t
) noexcept
;
62 Awaiter
co_viaIfAsync();
83 // CHECK-LABEL: define{{.*}} void @_Z3barv
84 // CHECK: %[[MODE:.+]] = load i32, i32* %mode
85 // CHECK-NEXT: switch i32 %[[MODE]], label %{{.+}} [
86 // CHECK-NEXT: i32 1, label %[[CASE1:.+]]
87 // CHECK-NEXT: i32 2, label %[[CASE2:.+]]
91 // CHECK: br i1 %{{.+}}, label %[[CASE1_AWAIT_READY:.+]], label %[[CASE1_AWAIT_SUSPEND:.+]]
92 // CHECK: [[CASE1_AWAIT_SUSPEND]]:
93 // CHECK-NEXT: %{{.+}} = call token @llvm.coro.save(i8* null)
94 // CHECK-NEXT: %[[HANDLE11:.+]] = bitcast %"struct.std::experimental::coroutines_v1::coroutine_handle"* %[[TMP1:.+]] to i8*
95 // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* %[[HANDLE11]])
97 // CHECK: %[[HANDLE12:.+]] = bitcast %"struct.std::experimental::coroutines_v1::coroutine_handle"* %[[TMP1]] to i8*
98 // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* %[[HANDLE12]])
99 // CHECK-NEXT: call void @llvm.coro.resume
100 // CHECK-NEXT: %{{.+}} = call i8 @llvm.coro.suspend
101 // CHECK-NEXT: switch i8 %{{.+}}, label %coro.ret [
102 // CHECK-NEXT: i8 0, label %[[CASE1_AWAIT_READY]]
103 // CHECK-NEXT: i8 1, label %[[CASE1_AWAIT_CLEANUP:.+]]
105 // CHECK: [[CASE1_AWAIT_CLEANUP]]:
106 // make sure that the awaiter eventually gets cleaned up.
107 // CHECK: call void @{{.+Awaiter.+}}
110 // CHECK: br i1 %{{.+}}, label %[[CASE2_AWAIT_READY:.+]], label %[[CASE2_AWAIT_SUSPEND:.+]]
111 // CHECK: [[CASE2_AWAIT_SUSPEND]]:
112 // CHECK-NEXT: %{{.+}} = call token @llvm.coro.save(i8* null)
113 // CHECK-NEXT: %[[HANDLE21:.+]] = bitcast %"struct.std::experimental::coroutines_v1::coroutine_handle"* %[[TMP2:.+]] to i8*
114 // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* %[[HANDLE21]])
116 // CHECK: %[[HANDLE22:.+]] = bitcast %"struct.std::experimental::coroutines_v1::coroutine_handle"* %[[TMP2]] to i8*
117 // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* %[[HANDLE22]])
118 // CHECK-NEXT: call void @llvm.coro.resume
119 // CHECK-NEXT: %{{.+}} = call i8 @llvm.coro.suspend
120 // CHECK-NEXT: switch i8 %{{.+}}, label %coro.ret [
121 // CHECK-NEXT: i8 0, label %[[CASE2_AWAIT_READY]]
122 // CHECK-NEXT: i8 1, label %[[CASE2_AWAIT_CLEANUP:.+]]
124 // CHECK: [[CASE2_AWAIT_CLEANUP]]:
125 // make sure that the awaiter eventually gets cleaned up.
126 // CHECK: call void @{{.+Awaiter.+}}