diff options
Diffstat (limited to 'test/CodeGenCoroutines/coro-alloc.cpp')
-rw-r--r-- | test/CodeGenCoroutines/coro-alloc.cpp | 61 |
1 files changed, 60 insertions, 1 deletions
diff --git a/test/CodeGenCoroutines/coro-alloc.cpp b/test/CodeGenCoroutines/coro-alloc.cpp index 820201db357fd..20b00d4fec21c 100644 --- a/test/CodeGenCoroutines/coro-alloc.cpp +++ b/test/CodeGenCoroutines/coro-alloc.cpp @@ -106,6 +106,60 @@ extern "C" void f1(promise_new_tag ) { co_return; } +struct promise_matching_placement_new_tag {}; + +template<> +struct std::experimental::coroutine_traits<void, promise_matching_placement_new_tag, int, float, double> { + struct promise_type { + void *operator new(unsigned long, promise_matching_placement_new_tag, + int, float, double); + void get_return_object() {} + suspend_always initial_suspend() { return {}; } + suspend_always final_suspend() { return {}; } + void return_void() {} + }; +}; + +// CHECK-LABEL: f1a( +extern "C" void f1a(promise_matching_placement_new_tag, int x, float y , double z) { + // CHECK: store i32 %x, i32* %x.addr, align 4 + // CHECK: store float %y, float* %y.addr, align 4 + // CHECK: store double %z, double* %z.addr, align 8 + // CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16 + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: %[[INT:.+]] = load i32, i32* %x.addr, align 4 + // CHECK: %[[FLOAT:.+]] = load float, float* %y.addr, align 4 + // CHECK: %[[DOUBLE:.+]] = load double, double* %z.addr, align 8 + // CHECK: call i8* @_ZNSt12experimental16coroutine_traitsIJv34promise_matching_placement_new_tagifdEE12promise_typenwEmS1_ifd(i64 %[[SIZE]], i32 %[[INT]], float %[[FLOAT]], double %[[DOUBLE]]) + co_return; +} + +// Declare a placement form operator new, such as the one described in +// C++ 18.6.1.3.1, which takes a void* argument. +void* operator new(SizeT __sz, void *__p) noexcept; + +struct promise_matching_global_placement_new_tag {}; +struct dummy {}; +template<> +struct std::experimental::coroutine_traits<void, promise_matching_global_placement_new_tag, dummy*> { + struct promise_type { + void get_return_object() {} + suspend_always initial_suspend() { return {}; } + suspend_always final_suspend() { return {}; } + void return_void() {} + }; +}; + +// A coroutine that takes a single pointer argument should not invoke this +// placement form operator. [dcl.fct.def.coroutine]/7 dictates that lookup for +// allocation functions matching the coroutine function's signature be done +// within the scope of the promise type's class. +// CHECK-LABEL: f1b( +extern "C" void f1b(promise_matching_global_placement_new_tag, dummy *) { + // CHECK: call i8* @_Znwm(i64 + co_return; +} + struct promise_delete_tag {}; template<> @@ -173,6 +227,7 @@ struct std::experimental::coroutine_traits<int, promise_on_alloc_failure_tag> { // CHECK-LABEL: f4( extern "C" int f4(promise_on_alloc_failure_tag) { // CHECK: %[[RetVal:.+]] = alloca i32 + // CHECK: %[[Gro:.+]] = alloca i32 // CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16 // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() // CHECK: %[[MEM:.+]] = call i8* @_ZnwmRKSt9nothrow_t(i64 %[[SIZE]], %"struct.std::nothrow_t"* dereferenceable(1) @_ZStL7nothrow) @@ -186,7 +241,11 @@ extern "C" int f4(promise_on_alloc_failure_tag) { // CHECK: [[OKBB]]: // CHECK: %[[OkRet:.+]] = call i32 @_ZNSt12experimental16coroutine_traitsIJi28promise_on_alloc_failure_tagEE12promise_type17get_return_objectEv( - // CHECK: store i32 %[[OkRet]], i32* %[[RetVal]] + // CHECK: store i32 %[[OkRet]], i32* %[[Gro]] + + // CHECK: %[[Tmp1:.*]] = load i32, i32* %[[Gro]] + // CHECK-NEXT: store i32 %[[Tmp1]], i32* %[[RetVal]] + // CHECK-NEXT: br label %[[RetBB]] // CHECK: [[RetBB]]: // CHECK: %[[LoadRet:.+]] = load i32, i32* %[[RetVal]], align 4 |