1 // This addresses https://github.com/llvm/llvm-project/issues/57339 2 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -fcxx-exceptions \ 3 // RUN: -fexceptions -emit-llvm -o - %s -O1 | FileCheck %s 4 5 #include "Inputs/coroutine.h" 6 7 struct gen { 8 struct promise_type { get_return_objectgen::promise_type9 gen get_return_object() noexcept { 10 return gen{std::coroutine_handle<promise_type>::from_promise(*this)}; 11 } initial_suspendgen::promise_type12 std::suspend_always initial_suspend() noexcept { return {}; } 13 14 struct final_awaiter { 15 ~final_awaiter() noexcept; await_readygen::promise_type::final_awaiter16 bool await_ready() noexcept { 17 return false; 18 } await_suspendgen::promise_type::final_awaiter19 void await_suspend(std::coroutine_handle<>) noexcept {} await_resumegen::promise_type::final_awaiter20 void await_resume() noexcept {} 21 }; 22 final_suspendgen::promise_type23 final_awaiter final_suspend() noexcept { 24 return {}; 25 } 26 unhandled_exceptiongen::promise_type27 void unhandled_exception() { 28 throw; 29 } return_voidgen::promise_type30 void return_void() {} 31 }; 32 gengen33 gen(std::coroutine_handle<promise_type> coro) noexcept 34 : coro(coro) 35 { 36 } 37 ~gengen38 ~gen() noexcept { 39 if (coro) { 40 coro.destroy(); 41 } 42 } 43 gengen44 gen(gen&& g) noexcept 45 : coro(g.coro) 46 { 47 g.coro = {}; 48 } 49 50 std::coroutine_handle<promise_type> coro; 51 }; 52 53 struct X {}; 54 maybe_throwing(bool x)55gen maybe_throwing(bool x) { 56 if (x) { 57 throw X{}; 58 } 59 co_return; 60 } 61 62 // CHECK: define{{.*}}@_Z14maybe_throwingb.destroy 63 // CHECK: %[[INDEX:.+]] = load i1, ptr %index.addr, align 1 64 // CHECK: br i1 %[[INDEX]], label %[[AFTERSUSPEND:.+]], label %[[CORO_FREE:.+]] 65 // CHECK: [[AFTERSUSPEND]]: 66 // CHECK: call{{.*}}_ZN3gen12promise_type13final_awaiterD1Ev( 67 // CHECK: [[CORO_FREE]]: 68 // CHECK: call{{.*}}_ZdlPv 69 70 void noexcept_call() noexcept; 71 no_throwing()72gen no_throwing() { 73 noexcept_call(); 74 co_return; 75 } 76 77 // CHECK: define{{.*}}@_Z11no_throwingv.resume({{.*}}%[[ARG:.+]]) 78 // CHECK: resume: 79 // CHECK: call{{.*}}@_Z13noexcept_callv() 80 // CHECK: store ptr null, ptr %[[ARG]] 81 // CHECK: ret void 82 83 // CHECK: define{{.*}}@_Z11no_throwingv.destroy({{.*}}%[[ARG:.+]]) 84 // CHECK: %[[RESUME_FN_ADDR:.+]] = load ptr, ptr %[[ARG]] 85 // CHECK: %[[IF_NULL:.+]] = icmp eq ptr %[[RESUME_FN_ADDR]], null 86 // CHECK: br i1 %[[IF_NULL]], label %[[AFTERSUSPEND:.+]], label %[[CORO_FREE:.+]] 87 // CHECK: [[AFTERSUSPEND]]: 88 // CHECK: call{{.*}}_ZN3gen12promise_type13final_awaiterD1Ev( 89 // CHECK: [[CORO_FREE]]: 90 // CHECK: call{{.*}}_ZdlPv 91