1 // RUN: %clang_cc1 %s -std=c++20 -fsyntax-only -verify 2 #include "Inputs/std-coroutine.h" 3 4 namespace std { 5 typedef decltype(sizeof(int)) size_t; 6 } 7 8 struct Allocator {}; 9 10 struct resumable { 11 struct promise_type { 12 void *operator new(std::size_t sz, Allocator &); 13 get_return_objectresumable::promise_type14 resumable get_return_object() { return {}; } initial_suspendresumable::promise_type15 auto initial_suspend() { return std::suspend_always(); } final_suspendresumable::promise_type16 auto final_suspend() noexcept { return std::suspend_always(); } unhandled_exceptionresumable::promise_type17 void unhandled_exception() {} return_voidresumable::promise_type18 void return_void(){}; 19 }; 20 }; 21 f1()22resumable f1() { // expected-error {{'operator new' provided by 'std::coroutine_traits<resumable>::promise_type' (aka 'resumable::promise_type') is not usable with the function signature of 'f1'}} 23 co_return; 24 } 25 26 // NOTE: Although the argument here is a rvalue reference and the corresponding 27 // allocation function in resumable::promise_type have lvalue references, it looks 28 // the signature of f2 is invalid. But according to [dcl.fct.def.coroutine]p4: 29 // 30 // In the following, pi is an lvalue of type Pi, where p1 denotes the object 31 // parameter and pi+1 denotes the ith non-object function parameter for a 32 // non-static member function. 33 // 34 // And [dcl.fct.def.coroutine]p9.1 35 // 36 // overload resolution is performed on a function call created by assembling an argument list. 37 // The first argument is the amount of space requested, and has type std::size_t. 38 // The lvalues p1…pn are the succeeding arguments. 39 // 40 // So the actual type passed to resumable::promise_type::operator new is lvalue 41 // Allocator. It is allowed to convert a lvalue to a lvalue reference. So the 42 // following one is valid. f2(Allocator &&)43resumable f2(Allocator &&) { 44 co_return; 45 } 46 f3(Allocator &)47resumable f3(Allocator &) { 48 co_return; 49 } 50 f4(Allocator)51resumable f4(Allocator) { 52 co_return; 53 } 54 f5(const Allocator)55resumable f5(const Allocator) { // expected-error {{operator new' provided by 'std::coroutine_traits<resumable, const Allocator>::promise_type' (aka 'resumable::promise_type') is not usable}} 56 co_return; 57 } 58 f6(const Allocator &)59resumable f6(const Allocator &) { // expected-error {{operator new' provided by 'std::coroutine_traits<resumable, const Allocator &>::promise_type' (aka 'resumable::promise_type') is not usable}} 60 co_return; 61 } 62 63 struct promise_base1 { 64 void *operator new(std::size_t sz); // expected-note {{member found by ambiguous name lookup}} 65 }; 66 67 struct promise_base2 { 68 void *operator new(std::size_t sz); // expected-note {{member found by ambiguous name lookup}} 69 }; 70 71 struct resumable2 { 72 struct promise_type : public promise_base1, public promise_base2 { get_return_objectresumable2::promise_type73 resumable2 get_return_object() { return {}; } initial_suspendresumable2::promise_type74 auto initial_suspend() { return std::suspend_always(); } final_suspendresumable2::promise_type75 auto final_suspend() noexcept { return std::suspend_always(); } unhandled_exceptionresumable2::promise_type76 void unhandled_exception() {} return_voidresumable2::promise_type77 void return_void(){}; 78 }; 79 }; 80 f7()81resumable2 f7() { // expected-error {{member 'operator new' found in multiple base classes of different types}} 82 co_return; 83 } 84