// RUN: %clang_cc1 -std=c++20 -triple=x86_64-- -emit-llvm -fcxx-exceptions \
// RUN: -disable-llvm-passes %s -o - | FileCheck %s
#include "Inputs/coroutine.h"
struct NontrivialType {
~NontrivialType() {}
};
struct NontrivialTypeWithThrowingDtor {
~NontrivialTypeWithThrowingDtor() noexcept(false) {}
};
namespace can_throw {
struct Task {
struct promise_type;
using handle_type = std::coroutine_handle<promise_type>;
struct initial_suspend_awaiter {
bool await_ready() {
return false;
}
void await_suspend(handle_type h) {}
NontrivialType await_resume() { return {}; }
};
struct promise_type {
void return_void() {}
void unhandled_exception() {}
initial_suspend_awaiter initial_suspend() { return {}; }
std::suspend_never final_suspend() noexcept { return {}; }
Task get_return_object() {
return Task{handle_type::from_promise(*this)};
}
};
handle_type handler;
};
Task coro_create() {
co_return;
}
// CHECK-LABEL: define{{.*}} ptr @_ZN9can_throw11coro_createEv(
// CHECK: init.ready:
// CHECK-NEXT: store i1 true, ptr {{.*}}
// CHECK-NEXT: call void @_ZN9can_throw4Task23initial_suspend_awaiter12await_resumeEv(
// CHECK-NEXT: call void @_ZN14NontrivialTypeD1Ev(
// CHECK-NEXT: store i1 false, ptr {{.*}}
}
template <typename R>
struct NoexceptResumeTask {
struct promise_type;
using handle_type = std::coroutine_handle<promise_type>;
struct initial_suspend_awaiter {
bool await_ready() {
return false;
}
void await_suspend(handle_type h) {}
R await_resume() noexcept { return {}; }
};
struct promise_type {
void return_void() {}
void unhandled_exception() {}
initial_suspend_awaiter initial_suspend() { return {}; }
std::suspend_never final_suspend() noexcept { return {}; }
NoexceptResumeTask get_return_object() {
return NoexceptResumeTask{handle_type::from_promise(*this)};
}
};
handle_type handler;
};
namespace no_throw {
using InitNoThrowTask = NoexceptResumeTask<NontrivialType>;
InitNoThrowTask coro_create() {
co_return;
}
// CHECK-LABEL: define{{.*}} ptr @_ZN8no_throw11coro_createEv(
// CHECK: init.ready:
// CHECK-NEXT: call void @_ZN18NoexceptResumeTaskI14NontrivialTypeE23initial_suspend_awaiter12await_resumeEv(
// CHECK-NEXT: call void @_ZN14NontrivialTypeD1Ev(
}
namespace throwing_dtor {
using InitTaskWithThrowingDtor = NoexceptResumeTask<NontrivialTypeWithThrowingDtor>;
InitTaskWithThrowingDtor coro_create() {
co_return;
}
// CHECK-LABEL: define{{.*}} ptr @_ZN13throwing_dtor11coro_createEv(
// CHECK: init.ready:
// CHECK-NEXT: store i1 true, ptr {{.*}}
// CHECK-NEXT: call void @_ZN18NoexceptResumeTaskI30NontrivialTypeWithThrowingDtorE23initial_suspend_awaiter12await_resumeEv(
// CHECK-NEXT: call void @_ZN30NontrivialTypeWithThrowingDtorD1Ev(
// CHECK-NEXT: store i1 false, ptr {{.*}}
}