| 1 | // RUN: %clang_cc1 -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.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 | |
| 20 | template <class RetObject> |
| 21 | struct promise_type { |
| 22 | RetObject get_return_object(); |
| 23 | suspend_always initial_suspend(); |
| 24 | suspend_never final_suspend(); |
| 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 NRVO is applied to the Gro object. |
| 37 | // CHECK-LABEL: define void @_Z1fi(%struct.coro* noalias sret %agg.result, i32) |
| 38 | coro f(int) { |
| 39 | // CHECK: %call = call i8* @_Znwm( |
| 40 | // CHECK-NEXT: br label %[[CoroInit:.*]] |
| 41 | |
| 42 | // CHECK: {{.*}}[[CoroInit]]: |
| 43 | // CHECK: store i1 false, i1* %gro.active |
| 44 | // CHECK: call void @{{.*get_return_objectEv}}(%struct.coro* sret %agg.result |
| 45 | // CHECK-NEXT: store i1 true, i1* %gro.active |
| 46 | co_return; |
| 47 | } |
| 48 | |
| 49 | |
| 50 | template <class RetObject> |
| 51 | struct promise_type_with_on_alloc_failure { |
| 52 | static RetObject get_return_object_on_allocation_failure(); |
| 53 | RetObject get_return_object(); |
| 54 | suspend_always initial_suspend(); |
| 55 | suspend_never final_suspend(); |
| 56 | void return_void(); |
| 57 | static void unhandled_exception(); |
| 58 | }; |
| 59 | |
| 60 | struct coro_two { |
| 61 | using promise_type = promise_type_with_on_alloc_failure<coro_two>; |
| 62 | coro_two(coro_two const&); |
| 63 | struct Impl; |
| 64 | Impl *impl; |
| 65 | }; |
| 66 | |
| 67 | // Verify that the NRVO is applied to the Gro object. |
| 68 | // CHECK-LABEL: define void @_Z1hi(%struct.coro_two* noalias sret %agg.result, i32) |
| 69 | coro_two h(int) { |
| 70 | |
| 71 | // CHECK: %call = call i8* @_ZnwmRKSt9nothrow_t |
| 72 | // CHECK-NEXT: %[[CheckNull:.*]] = icmp ne i8* %call, null |
| 73 | // CHECK-NEXT: br i1 %[[CheckNull]], label %[[InitOnSuccess:.*]], label %[[InitOnFailure:.*]] |
| 74 | |
| 75 | // CHECK: {{.*}}[[InitOnFailure]]: |
| 76 | // CHECK-NEXT: call void @{{.*get_return_object_on_allocation_failureEv}}(%struct.coro_two* sret %agg.result |
| 77 | // CHECK-NEXT: br label %[[RetLabel:.*]] |
| 78 | |
| 79 | // CHECK: {{.*}}[[InitOnSuccess]]: |
| 80 | // CHECK: store i1 false, i1* %gro.active |
| 81 | // CHECK: call void @{{.*get_return_objectEv}}(%struct.coro_two* sret %agg.result |
| 82 | // CHECK-NEXT: store i1 true, i1* %gro.active |
| 83 | |
| 84 | // CHECK: [[RetLabel]]: |
| 85 | // CHECK-NEXT: ret void |
| 86 | co_return; |
| 87 | } |
| 88 | |