| // This addresses https://github.com/llvm/llvm-project/issues/57339 |
| // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -fcxx-exceptions \ |
| // RUN: -fexceptions -emit-llvm -o - %s -O1 | FileCheck %s |
| |
| #include "Inputs/coroutine.h" |
| |
| struct gen { |
| struct promise_type { |
| gen get_return_object() noexcept { |
| return gen{std::coroutine_handle<promise_type>::from_promise(*this)}; |
| } |
| std::suspend_always initial_suspend() noexcept { return {}; } |
| |
| struct final_awaiter { |
| ~final_awaiter() noexcept; |
| bool await_ready() noexcept { |
| return false; |
| } |
| void await_suspend(std::coroutine_handle<>) noexcept {} |
| void await_resume() noexcept {} |
| }; |
| |
| final_awaiter final_suspend() noexcept { |
| return {}; |
| } |
| |
| void unhandled_exception() { |
| throw; |
| } |
| void return_void() {} |
| }; |
| |
| gen(std::coroutine_handle<promise_type> coro) noexcept |
| : coro(coro) |
| { |
| } |
| |
| ~gen() noexcept { |
| if (coro) { |
| coro.destroy(); |
| } |
| } |
| |
| gen(gen&& g) noexcept |
| : coro(g.coro) |
| { |
| g.coro = {}; |
| } |
| |
| std::coroutine_handle<promise_type> coro; |
| }; |
| |
| struct X {}; |
| |
| gen maybe_throwing(bool x) { |
| if (x) { |
| throw X{}; |
| } |
| co_return; |
| } |
| |
| // CHECK: define{{.*}}@_Z14maybe_throwingb.destroy |
| // CHECK: %[[INDEX:.+]] = load i1, ptr %index.addr, align 1 |
| // CHECK: br i1 %[[INDEX]], label %[[AFTERSUSPEND:.+]], label %[[CORO_FREE:.+]] |
| // CHECK: [[AFTERSUSPEND]]: |
| // CHECK: call{{.*}}_ZN3gen12promise_type13final_awaiterD1Ev( |
| // CHECK: [[CORO_FREE]]: |
| // CHECK: call{{.*}}_ZdlPv |
| |
| void noexcept_call() noexcept; |
| |
| gen no_throwing() { |
| noexcept_call(); |
| co_return; |
| } |
| |
| // CHECK: define{{.*}}@_Z11no_throwingv.resume({{.*}}%[[ARG:.+]]) |
| // CHECK: resume: |
| // CHECK: call{{.*}}@_Z13noexcept_callv() |
| // CHECK: store ptr null, ptr %[[ARG]] |
| // CHECK: ret void |
| |
| // CHECK: define{{.*}}@_Z11no_throwingv.destroy({{.*}}%[[ARG:.+]]) |
| // CHECK: %[[RESUME_FN_ADDR:.+]] = load ptr, ptr %[[ARG]] |
| // CHECK: %[[IF_NULL:.+]] = icmp eq ptr %[[RESUME_FN_ADDR]], null |
| // CHECK: br i1 %[[IF_NULL]], label %[[AFTERSUSPEND:.+]], label %[[CORO_FREE:.+]] |
| // CHECK: [[AFTERSUSPEND]]: |
| // CHECK: call{{.*}}_ZN3gen12promise_type13final_awaiterD1Ev( |
| // CHECK: [[CORO_FREE]]: |
| // CHECK: call{{.*}}_ZdlPv |