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 14 resumable get_return_object() { return {}; } 15 auto initial_suspend() { return std::suspend_always(); } 16 auto final_suspend() noexcept { return std::suspend_always(); } 17 void unhandled_exception() {} 18 void return_void(){}; 19 }; 20 }; 21 22 resumable 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. 43 resumable f2(Allocator &&) { 44 co_return; 45 } 46 47 resumable f3(Allocator &) { 48 co_return; 49 } 50 51 resumable f4(Allocator) { 52 co_return; 53 } 54 55 resumable 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 59 resumable 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 { 73 resumable2 get_return_object() { return {}; } 74 auto initial_suspend() { return std::suspend_always(); } 75 auto final_suspend() noexcept { return std::suspend_always(); } 76 void unhandled_exception() {} 77 void return_void(){}; 78 }; 79 }; 80 81 resumable2 f7() { // expected-error {{member 'operator new' found in multiple base classes of different types}} 82 co_return; 83 } 84