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 | |