1 // RUN: %clang_cc1 -no-opaque-pointers -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++14 -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s 2 3 #include "Inputs/coroutine-exp-namespace.h" 4 5 using namespace std::experimental; 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 template <class RetObject> 20 struct promise_type { 21 RetObject get_return_object(); 22 suspend_always initial_suspend(); 23 suspend_never final_suspend() noexcept; 24 void return_void(); 25 static void unhandled_exception(); 26 }; 27 28 struct coro { 29 using promise_type = promise_type<coro>; 30 coro(coro const &); 31 struct Impl; 32 Impl *impl; 33 }; 34 35 // Verify that the RVO is applied. 36 // CHECK-LABEL: define{{.*}} void @_Z1fi(%struct.coro* noalias sret(%struct.coro) align 8 %agg.result, i32 noundef %0) 37 coro f(int) { 38 // CHECK: %call = call noalias noundef nonnull i8* @_Znwm( 39 // CHECK-NEXT: br label %[[CoroInit:.*]] 40 41 // CHECK: {{.*}}[[CoroInit]]: 42 // CHECK: call void @{{.*get_return_objectEv}}(%struct.coro* sret(%struct.coro) align 8 %agg.result 43 co_return; 44 } 45 46 template <class RetObject> 47 struct promise_type_with_on_alloc_failure { 48 static RetObject get_return_object_on_allocation_failure(); 49 RetObject get_return_object(); 50 suspend_always initial_suspend(); 51 suspend_never final_suspend() noexcept; 52 void return_void(); 53 static void unhandled_exception(); 54 }; 55 56 struct coro_two { 57 using promise_type = promise_type_with_on_alloc_failure<coro_two>; 58 coro_two(coro_two const &); 59 struct Impl; 60 Impl *impl; 61 }; 62 63 // Verify that the NRVO is applied to the Gro object. 64 // CHECK-LABEL: define{{.*}} void @_Z1hi(%struct.coro_two* noalias sret(%struct.coro_two) align 8 %agg.result, i32 noundef %0) 65 coro_two h(int) { 66 67 // CHECK: %call = call noalias noundef i8* @_ZnwmRKSt9nothrow_t 68 // CHECK-NEXT: %[[CheckNull:.*]] = icmp ne i8* %call, null 69 // CHECK-NEXT: br i1 %[[CheckNull]], label %[[InitOnSuccess:.*]], label %[[InitOnFailure:.*]] 70 71 // CHECK: {{.*}}[[InitOnFailure]]: 72 // CHECK-NEXT: call void @{{.*get_return_object_on_allocation_failureEv}}(%struct.coro_two* sret(%struct.coro_two) align 8 %agg.result 73 // CHECK-NEXT: br label %[[RetLabel:.*]] 74 75 // CHECK: {{.*}}[[InitOnSuccess]]: 76 // CHECK: call void @{{.*get_return_objectEv}}(%struct.coro_two* sret(%struct.coro_two) align 8 %agg.result 77 78 // CHECK: [[RetLabel]]: 79 // CHECK-NEXT: ret void 80 co_return; 81 } 82