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 namespace std { 4 namespace experimental { 5 template <typename... T> 6 struct coroutine_traits; // expected-note {{declared here}} 7 8 template <class Promise = void> 9 struct coroutine_handle { 10 coroutine_handle() = default; 11 static coroutine_handle from_address(void *) { return {}; } 12 }; 13 14 template <> 15 struct coroutine_handle<void> { 16 static coroutine_handle from_address(void *) { return {}; } 17 coroutine_handle() = default; 18 template <class PromiseType> 19 coroutine_handle(coroutine_handle<PromiseType>) {} 20 }; 21 22 } 23 } 24 25 struct suspend_always { 26 bool await_ready() { return false; } 27 void await_suspend(std::experimental::coroutine_handle<>) {} 28 void await_resume() {} 29 }; 30 31 struct global_new_delete_tag {}; 32 33 template<> 34 struct std::experimental::coroutine_traits<void, global_new_delete_tag> { 35 struct promise_type { 36 void get_return_object() {} 37 suspend_always initial_suspend() { return {}; } 38 suspend_always final_suspend() { return {}; } 39 void return_void() {} 40 }; 41 }; 42 43 // CHECK-LABEL: f0( 44 extern "C" void f0(global_new_delete_tag) { 45 // CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16 46 // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() 47 // CHECK: call i8* @_Znwm(i64 %[[SIZE]]) 48 49 // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame() 50 // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]]) 51 // CHECK: call void @_ZdlPv(i8* %[[MEM]]) 52 co_return; 53 } 54 55 struct promise_new_tag {}; 56 57 template<> 58 struct std::experimental::coroutine_traits<void, promise_new_tag> { 59 struct promise_type { 60 void *operator new(unsigned long); 61 void get_return_object() {} 62 suspend_always initial_suspend() { return {}; } 63 suspend_always final_suspend() { return {}; } 64 void return_void() {} 65 }; 66 }; 67 68 // CHECK-LABEL: f1( 69 extern "C" void f1(promise_new_tag ) { 70 // CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16 71 // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() 72 // CHECK: call i8* @_ZNSt12experimental16coroutine_traitsIJv15promise_new_tagEE12promise_typenwEm(i64 %[[SIZE]]) 73 74 // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame() 75 // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]]) 76 // CHECK: call void @_ZdlPv(i8* %[[MEM]]) 77 co_return; 78 } 79 80 struct promise_delete_tag {}; 81 82 template<> 83 struct std::experimental::coroutine_traits<void, promise_delete_tag> { 84 struct promise_type { 85 void operator delete(void*); 86 void get_return_object() {} 87 suspend_always initial_suspend() { return {}; } 88 suspend_always final_suspend() { return {}; } 89 void return_void() {} 90 }; 91 }; 92 93 // CHECK-LABEL: f2( 94 extern "C" void f2(promise_delete_tag) { 95 // CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16 96 // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() 97 // CHECK: call i8* @_Znwm(i64 %[[SIZE]]) 98 99 // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame() 100 // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]]) 101 // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJv18promise_delete_tagEE12promise_typedlEPv(i8* %[[MEM]]) 102 co_return; 103 } 104 105 struct promise_sized_delete_tag {}; 106 107 template<> 108 struct std::experimental::coroutine_traits<void, promise_sized_delete_tag> { 109 struct promise_type { 110 void operator delete(void*, unsigned long); 111 void get_return_object() {} 112 suspend_always initial_suspend() { return {}; } 113 suspend_always final_suspend() { return {}; } 114 void return_void() {} 115 }; 116 }; 117 118 // CHECK-LABEL: f3( 119 extern "C" void f3(promise_sized_delete_tag) { 120 // CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16 121 // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() 122 // CHECK: call i8* @_Znwm(i64 %[[SIZE]]) 123 124 // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame() 125 // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]]) 126 // CHECK: %[[SIZE2:.+]] = call i64 @llvm.coro.size.i64() 127 // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJv24promise_sized_delete_tagEE12promise_typedlEPvm(i8* %[[MEM]], i64 %[[SIZE2]]) 128 co_return; 129 } 130