84 lines · cpp
1// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s2 3#include "Inputs/coroutine.h"4 5using namespace std;6 7namespace std {8 9struct nothrow_t {};10constexpr nothrow_t nothrow = {};11 12} // end namespace std13 14// Required when get_return_object_on_allocation_failure() is defined by15// the promise.16void* operator new(__SIZE_TYPE__ __sz, const std::nothrow_t&) noexcept;17void operator delete(void* __p, const std::nothrow_t&) noexcept;18 19 20template <class RetObject>21struct promise_type {22 RetObject get_return_object();23 suspend_always initial_suspend();24 suspend_never final_suspend() noexcept;25 void return_void();26 static void unhandled_exception();27};28 29struct coro {30 using promise_type = promise_type<coro>;31 coro(coro const&);32 struct Impl;33 Impl *impl;34};35 36// Verify that the RVO is applied.37// CHECK-LABEL: define{{.*}} void @_Z1fi(ptr dead_on_unwind noalias writable sret(%struct.coro) align 8 %agg.result, i32 noundef %0)38coro f(int) {39// CHECK: %call = call noalias noundef nonnull ptr @_Znwm(40// CHECK-NEXT: br label %[[CoroInit:.*]]41 42// CHECK: {{.*}}[[CoroInit]]:43// CHECK: call void @{{.*get_return_objectEv}}(ptr dead_on_unwind writable sret(%struct.coro) align 8 %agg.result44co_return;45}46 47 48template <class RetObject>49struct promise_type_with_on_alloc_failure {50 static RetObject get_return_object_on_allocation_failure();51 RetObject get_return_object();52 suspend_always initial_suspend();53 suspend_never final_suspend() noexcept;54 void return_void();55 static void unhandled_exception();56};57 58struct coro_two {59 using promise_type = promise_type_with_on_alloc_failure<coro_two>;60 coro_two(coro_two const&);61 struct Impl;62 Impl *impl;63};64 65// Verify that the RVO is applied.66// CHECK-LABEL: define{{.*}} void @_Z1hi(ptr dead_on_unwind noalias writable sret(%struct.coro_two) align 8 %agg.result, i32 noundef %0)67coro_two h(int) {68 69 // CHECK: %call = call noalias noundef ptr @_ZnwmRKSt9nothrow_t70 // CHECK-NEXT: %[[CheckNull:.*]] = icmp ne ptr %call, null71 // CHECK-NEXT: br i1 %[[CheckNull]], label %[[InitOnSuccess:.*]], label %[[InitOnFailure:.*]]72 73 // CHECK: {{.*}}[[InitOnFailure]]:74 // CHECK-NEXT: call void @{{.*get_return_object_on_allocation_failureEv}}(ptr dead_on_unwind writable sret(%struct.coro_two) align 8 %agg.result75 // CHECK-NEXT: br label %[[RetLabel:.*]]76 77 // CHECK: {{.*}}[[InitOnSuccess]]:78 // CHECK: call void @{{.*get_return_objectEv}}(ptr dead_on_unwind writable sret(%struct.coro_two) align 8 %agg.result79 80 // CHECK: [[RetLabel]]:81 // CHECK-NEXT: ret void82 co_return;83}84