// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s #include "Inputs/coroutine.h" using namespace std; namespace std { struct nothrow_t {}; constexpr nothrow_t nothrow = {}; } // end namespace std // Required when get_return_object_on_allocation_failure() is defined by // the promise. void* operator new(__SIZE_TYPE__ __sz, const std::nothrow_t&) noexcept; void operator delete(void* __p, const std::nothrow_t&) noexcept; template struct promise_type { RetObject get_return_object(); suspend_always initial_suspend(); suspend_never final_suspend() noexcept; void return_void(); static void unhandled_exception(); }; struct coro { using promise_type = promise_type; coro(coro const&); struct Impl; Impl *impl; }; // Verify that the RVO is applied. // CHECK-LABEL: define{{.*}} void @_Z1fi(ptr dead_on_unwind noalias writable sret(%struct.coro) align 8 %agg.result, i32 noundef %0) coro f(int) { // CHECK: %call = call noalias noundef nonnull ptr @_Znwm( // CHECK-NEXT: br label %[[CoroInit:.*]] // CHECK: {{.*}}[[CoroInit]]: // CHECK: call void @{{.*get_return_objectEv}}(ptr dead_on_unwind writable sret(%struct.coro) align 8 %agg.result co_return; } template struct promise_type_with_on_alloc_failure { static RetObject get_return_object_on_allocation_failure(); RetObject get_return_object(); suspend_always initial_suspend(); suspend_never final_suspend() noexcept; void return_void(); static void unhandled_exception(); }; struct coro_two { using promise_type = promise_type_with_on_alloc_failure; coro_two(coro_two const&); struct Impl; Impl *impl; }; // Verify that the RVO is applied. // CHECK-LABEL: define{{.*}} void @_Z1hi(ptr dead_on_unwind noalias writable sret(%struct.coro_two) align 8 %agg.result, i32 noundef %0) coro_two h(int) { // CHECK: %call = call noalias noundef ptr @_ZnwmRKSt9nothrow_t // CHECK-NEXT: %[[CheckNull:.*]] = icmp ne ptr %call, null // CHECK-NEXT: br i1 %[[CheckNull]], label %[[InitOnSuccess:.*]], label %[[InitOnFailure:.*]] // CHECK: {{.*}}[[InitOnFailure]]: // CHECK-NEXT: call void @{{.*get_return_object_on_allocation_failureEv}}(ptr dead_on_unwind writable sret(%struct.coro_two) align 8 %agg.result // CHECK-NEXT: br label %[[RetLabel:.*]] // CHECK: {{.*}}[[InitOnSuccess]]: // CHECK: call void @{{.*get_return_objectEv}}(ptr dead_on_unwind writable sret(%struct.coro_two) align 8 %agg.result // CHECK: [[RetLabel]]: // CHECK-NEXT: ret void co_return; }