1 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s 2 3 #include "Inputs/coroutine.h" 4 5 using namespace std; 6 7 namespace std { 8 9 struct nothrow_t {}; 10 constexpr nothrow_t nothrow = {}; 11 12 } // end namespace std 13 14 // Required when get_return_object_on_allocation_failure() is defined by 15 // the promise. 16 void* operator new(__SIZE_TYPE__ __sz, const std::nothrow_t&) noexcept; 17 void operator delete(void* __p, const std::nothrow_t&) noexcept; 18 19 20 template <class RetObject> 21 struct 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 29 struct 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) f(int)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.result 44 co_return; 45 } 46 47 48 template <class RetObject> 49 struct 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 58 struct 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) h(int)67coro_two h(int) { 68 69 // CHECK: %call = call noalias noundef ptr @_ZnwmRKSt9nothrow_t 70 // CHECK-NEXT: %[[CheckNull:.*]] = icmp ne ptr %call, null 71 // 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.result 75 // 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.result 79 80 // CHECK: [[RetLabel]]: 81 // CHECK-NEXT: ret void 82 co_return; 83 } 84