1 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -ast-dump %s | FileCheck %s 2 3 #include "Inputs/std-coroutine.h" 4 5 using namespace std; 6 7 struct Task { 8 struct promise_type { get_return_objectTask::promise_type9 Task get_return_object() noexcept { 10 return Task{coroutine_handle<promise_type>::from_promise(*this)}; 11 } 12 return_voidTask::promise_type13 void return_void() noexcept {} 14 15 struct final_awaiter { await_readyTask::promise_type::final_awaiter16 bool await_ready() noexcept { return false; } await_suspendTask::promise_type::final_awaiter17 coroutine_handle<> await_suspend(coroutine_handle<promise_type> h) noexcept { 18 h.destroy(); 19 return {}; 20 } await_resumeTask::promise_type::final_awaiter21 void await_resume() noexcept {} 22 }; 23 unhandled_exceptionTask::promise_type24 void unhandled_exception() noexcept {} 25 final_suspendTask::promise_type26 final_awaiter final_suspend() noexcept { return {}; } 27 initial_suspendTask::promise_type28 suspend_always initial_suspend() noexcept { return {}; } 29 30 template <typename Awaitable> await_transformTask::promise_type31 auto await_transform(Awaitable &&awaitable) { 32 return awaitable.co_viaIfAsync(); 33 } 34 }; 35 36 using handle_t = coroutine_handle<promise_type>; 37 38 class Awaiter { 39 public: 40 explicit Awaiter(handle_t coro) noexcept; 41 Awaiter(Awaiter &&other) noexcept; 42 Awaiter(const Awaiter &) = delete; 43 ~Awaiter(); 44 await_ready()45 bool await_ready() noexcept { return false; } 46 handle_t await_suspend(coroutine_handle<> continuation) noexcept; 47 void await_resume(); 48 49 private: 50 handle_t coro_; 51 }; 52 TaskTask53 Task(handle_t coro) noexcept : coro_(coro) {} 54 55 handle_t coro_; 56 57 Task(const Task &t) = delete; 58 Task(Task &&t) noexcept; 59 ~Task(); 60 Task &operator=(Task t) noexcept; 61 62 Awaiter co_viaIfAsync(); 63 }; 64 foo()65static Task foo() { 66 co_return; 67 } 68 bar()69Task bar() { 70 auto mode = 2; 71 switch (mode) { 72 case 1: 73 co_await foo(); 74 break; 75 case 2: 76 co_await foo(); 77 break; 78 default: 79 break; 80 } 81 } 82 83 // CHECK-LABEL: FunctionDecl {{.*}} bar 'Task ()' 84 // CHECK: SwitchStmt 85 // CHECK: CaseStmt 86 // CHECK: ExprWithCleanups {{.*}} 'void' 87 // CHECK-NEXT: CoawaitExpr 88 // CHECK-NEXT: CXXBindTemporaryExpr {{.*}} 'Task' (CXXTemporary {{.*}}) 89 // CHECK: MaterializeTemporaryExpr {{.*}} 'Awaiter':'Task::Awaiter' 90 // CHECK: ExprWithCleanups {{.*}} 'bool' 91 // CHECK-NEXT: CXXMemberCallExpr {{.*}} 'bool' 92 // CHECK-NEXT: MemberExpr {{.*}} .await_ready 93 // CHECK: ExprWithCleanups {{.*}} 'void *' 94 95 // CHECK: CaseStmt 96 // CHECK: ExprWithCleanups {{.*}} 'void' 97 // CHECK-NEXT: CoawaitExpr 98 // CHECK-NEXT: CXXBindTemporaryExpr {{.*}} 'Task' (CXXTemporary {{.*}}) 99 // CHECK: MaterializeTemporaryExpr {{.*}} 'Awaiter':'Task::Awaiter' 100 // CHECK: ExprWithCleanups {{.*}} 'bool' 101 // CHECK-NEXT: CXXMemberCallExpr {{.*}} 'bool' 102 // CHECK-NEXT: MemberExpr {{.*}} .await_ready 103 // CHECK: ExprWithCleanups {{.*}} 'void *' 104