summaryrefslogtreecommitdiff
path: root/test/CodeGenCoroutines/coro-await.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGenCoroutines/coro-await.cpp')
-rw-r--r--test/CodeGenCoroutines/coro-await.cpp64
1 files changed, 57 insertions, 7 deletions
diff --git a/test/CodeGenCoroutines/coro-await.cpp b/test/CodeGenCoroutines/coro-await.cpp
index b0fd0129de34a..1e2deaa8f59a7 100644
--- a/test/CodeGenCoroutines/coro-await.cpp
+++ b/test/CodeGenCoroutines/coro-await.cpp
@@ -21,6 +21,17 @@ struct coroutine_handle : coroutine_handle<> {
}
}
+struct init_susp {
+ bool await_ready();
+ void await_suspend(std::experimental::coroutine_handle<>);
+ void await_resume();
+};
+struct final_susp {
+ bool await_ready();
+ void await_suspend(std::experimental::coroutine_handle<>);
+ void await_resume();
+};
+
struct suspend_always {
int stuff;
bool await_ready();
@@ -32,14 +43,22 @@ template<>
struct std::experimental::coroutine_traits<void> {
struct promise_type {
void get_return_object();
- suspend_always initial_suspend();
- suspend_always final_suspend();
+ init_susp initial_suspend();
+ final_susp final_suspend();
void return_void();
};
};
// CHECK-LABEL: f0(
extern "C" void f0() {
+ // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
+
+ // See if initial_suspend was issued:
+ // ----------------------------------
+ // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_type15initial_suspendEv(
+ // CHECK-NEXT: call zeroext i1 @_ZN9init_susp11await_readyEv(%struct.init_susp*
+ // CHECK: %[[INITSP_ID:.+]] = call token @llvm.coro.save(
+ // CHECK: call i8 @llvm.coro.suspend(token %[[INITSP_ID]], i1 false)
co_await suspend_always{};
// See if we need to suspend:
@@ -54,7 +73,6 @@ extern "C" void f0() {
// ---------------------------
// Build the coroutine handle and pass it to await_suspend
// ---------------------------
- // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame()
// CHECK: call i8* @_ZNSt12experimental16coroutine_handleINS_16coroutine_traitsIJvEE12promise_typeEE12from_addressEPv(i8* %[[FRAME]])
// ... many lines of code to coerce coroutine_handle into an i8* scalar
// CHECK: %[[CH:.+]] = load i8*, i8** %{{.+}}
@@ -76,6 +94,13 @@ extern "C" void f0() {
// --------------------------
// CHECK: [[READY_BB]]:
// CHECK: call void @_ZN14suspend_always12await_resumeEv(%struct.suspend_always* %[[AWAITABLE]])
+
+ // See if final_suspend was issued:
+ // ----------------------------------
+ // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_type13final_suspendEv(
+ // CHECK-NEXT: call zeroext i1 @_ZN10final_susp11await_readyEv(%struct.final_susp*
+ // CHECK: %[[FINALSP_ID:.+]] = call token @llvm.coro.save(
+ // CHECK: call i8 @llvm.coro.suspend(token %[[FINALSP_ID]], i1 true)
}
struct suspend_maybe {
@@ -91,8 +116,8 @@ template<>
struct std::experimental::coroutine_traits<void,int> {
struct promise_type {
void get_return_object();
- suspend_always initial_suspend();
- suspend_always final_suspend();
+ init_susp initial_suspend();
+ final_susp final_suspend();
void return_void();
suspend_maybe yield_value(int);
};
@@ -100,8 +125,9 @@ struct std::experimental::coroutine_traits<void,int> {
// CHECK-LABEL: f1(
extern "C" void f1(int) {
- co_yield 42;
// CHECK: %[[PROMISE:.+]] = alloca %"struct.std::experimental::coroutine_traits<void, int>::promise_type"
+ // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
+ co_yield 42;
// CHECK: call void @_ZNSt12experimental16coroutine_traitsIJviEE12promise_type11yield_valueEi(%struct.suspend_maybe* sret %[[AWAITER:.+]], %"struct.std::experimental::coroutine_traits<void, int>::promise_type"* %[[PROMISE]], i32 42)
// See if we need to suspend:
@@ -116,7 +142,6 @@ extern "C" void f1(int) {
// ---------------------------
// Build the coroutine handle and pass it to await_suspend
// ---------------------------
- // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame()
// CHECK: call i8* @_ZNSt12experimental16coroutine_handleINS_16coroutine_traitsIJviEE12promise_typeEE12from_addressEPv(i8* %[[FRAME]])
// ... many lines of code to coerce coroutine_handle into an i8* scalar
// CHECK: %[[CH:.+]] = load i8*, i8** %{{.+}}
@@ -228,3 +253,28 @@ extern "C" void TestOpAwait() {
// CHECK: call void @_ZN5MyAggawEv(%struct.MyAgg* %
// CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(%struct.Aggr* sret %
}
+
+// CHECK-LABEL: EndlessLoop(
+extern "C" void EndlessLoop() {
+ // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
+
+ // See if initial_suspend was issued:
+ // ----------------------------------
+ // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_type15initial_suspendEv(
+ // CHECK-NEXT: call zeroext i1 @_ZN9init_susp11await_readyEv(%struct.init_susp*
+
+ for (;;)
+ co_await suspend_always{};
+
+ // Verify that final_suspend was NOT issued:
+ // ----------------------------------
+ // CHECK-NOT: call void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_type13final_suspendEv(
+ // CHECK-NOT: call zeroext i1 @_ZN10final_susp11await_readyEv(%struct.final_susp*
+}
+
+// Verifies that we don't crash when awaiting on an lvalue.
+// CHECK-LABEL: @_Z11AwaitLValuev(
+void AwaitLValue() {
+ suspend_always lval;
+ co_await lval;
+}