xref: /llvm-project/clang/test/CodeGenCoroutines/pr59181.cpp (revision f78688134026686288a8d310b493d9327753a022)
1 // Test for PR59181. Tests that no conditional cleanup is created around await_suspend.
2 //
3 // REQUIRES: x86-registered-target
4 //
5 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - -std=c++20 -disable-llvm-passes -fsanitize-address-use-after-scope | FileCheck %s
6 
7 #include "Inputs/coroutine.h"
8 
9 struct Task {
10   int value_;
11   struct promise_type {
get_return_objectTask::promise_type12     Task get_return_object() {
13       return Task{0};
14     }
15 
initial_suspendTask::promise_type16     std::suspend_never initial_suspend() noexcept {
17       return {};
18     }
19 
final_suspendTask::promise_type20     std::suspend_never final_suspend() noexcept {
21       return {};
22     }
23 
return_valueTask::promise_type24     void return_value(Task t) noexcept {}
unhandled_exceptionTask::promise_type25     void unhandled_exception() noexcept {}
26 
await_transformTask::promise_type27     auto await_transform(Task t) {
28       struct Suspension {
29         auto await_ready() noexcept { return false;}
30         auto await_suspend(std::coroutine_handle<> coro) {
31           coro.destroy();
32         }
33 
34         auto await_resume() noexcept {
35           return 0;
36         }
37       };
38       return Suspension{};
39     }
40   };
41 };
42 
bar(bool cond)43 Task bar(bool cond) {
44   co_return cond ? Task{ co_await Task{}}: Task{};
45 }
46 
foo()47 void foo() {
48   bar(true);
49 }
50 
51 // CHECK: cleanup.cont:{{.*}}
52 // CHECK-NEXT: load i8
53 // CHECK-NEXT: trunc
54 // CHECK-NEXT: store i1 false
55 
56 // CHECK: await.suspend:{{.*}}
57 // CHECK-NOT: call void @llvm.lifetime
58 // CHECK: call void @llvm.coro.await.suspend.void(
59 // CHECK-NEXT: %{{[0-9]+}} = call i8 @llvm.coro.suspend(
60