1452fac95SChuanqi Xu // RUN: %clang_cc1 %s -std=c++20 -fsyntax-only -verify
2452fac95SChuanqi Xu #include "Inputs/std-coroutine.h"
3452fac95SChuanqi Xu 
4452fac95SChuanqi Xu namespace std {
5452fac95SChuanqi Xu typedef decltype(sizeof(int)) size_t;
6452fac95SChuanqi Xu }
7452fac95SChuanqi Xu 
8452fac95SChuanqi Xu struct Allocator {};
9452fac95SChuanqi Xu 
10452fac95SChuanqi Xu struct resumable {
11452fac95SChuanqi Xu   struct promise_type {
12452fac95SChuanqi Xu     void *operator new(std::size_t sz, Allocator &);
13452fac95SChuanqi Xu 
get_return_objectresumable::promise_type14452fac95SChuanqi Xu     resumable get_return_object() { return {}; }
initial_suspendresumable::promise_type15452fac95SChuanqi Xu     auto initial_suspend() { return std::suspend_always(); }
final_suspendresumable::promise_type16452fac95SChuanqi Xu     auto final_suspend() noexcept { return std::suspend_always(); }
unhandled_exceptionresumable::promise_type17452fac95SChuanqi Xu     void unhandled_exception() {}
return_voidresumable::promise_type18452fac95SChuanqi Xu     void return_void(){};
19452fac95SChuanqi Xu   };
20452fac95SChuanqi Xu };
21452fac95SChuanqi Xu 
f1()22*448995c5SChuanqi Xu 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'}}
23452fac95SChuanqi Xu   co_return;
24452fac95SChuanqi Xu }
25452fac95SChuanqi Xu 
26452fac95SChuanqi Xu // NOTE: Although the argument here is a rvalue reference and the corresponding
27452fac95SChuanqi Xu // allocation function in resumable::promise_type have lvalue references, it looks
28452fac95SChuanqi Xu // the signature of f2 is invalid. But according to [dcl.fct.def.coroutine]p4:
29452fac95SChuanqi Xu //
30452fac95SChuanqi Xu //   In the following, pi is an lvalue of type Pi, where p1 denotes the object
31452fac95SChuanqi Xu //   parameter and pi+1 denotes the ith non-object function parameter for a
32452fac95SChuanqi Xu //   non-static member function.
33452fac95SChuanqi Xu //
34452fac95SChuanqi Xu // And [dcl.fct.def.coroutine]p9.1
35452fac95SChuanqi Xu //
36452fac95SChuanqi Xu //   overload resolution is performed on a function call created by assembling an argument list.
37452fac95SChuanqi Xu //   The first argument is the amount of space requested, and has type std::size_­t.
38452fac95SChuanqi Xu //   The lvalues p1…pn are the succeeding arguments.
39452fac95SChuanqi Xu //
40*448995c5SChuanqi Xu // So the actual type passed to resumable::promise_type::operator new is lvalue
41452fac95SChuanqi Xu // Allocator. It is allowed  to convert a lvalue to a lvalue reference. So the
42452fac95SChuanqi Xu // following one is valid.
f2(Allocator &&)43452fac95SChuanqi Xu resumable f2(Allocator &&) {
44452fac95SChuanqi Xu   co_return;
45452fac95SChuanqi Xu }
46452fac95SChuanqi Xu 
f3(Allocator &)47452fac95SChuanqi Xu resumable f3(Allocator &) {
48452fac95SChuanqi Xu   co_return;
49452fac95SChuanqi Xu }
50452fac95SChuanqi Xu 
f4(Allocator)51452fac95SChuanqi Xu resumable f4(Allocator) {
52452fac95SChuanqi Xu   co_return;
53452fac95SChuanqi Xu }
54452fac95SChuanqi Xu 
f5(const Allocator)55452fac95SChuanqi Xu 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}}
56452fac95SChuanqi Xu   co_return;
57452fac95SChuanqi Xu }
58452fac95SChuanqi Xu 
f6(const Allocator &)59452fac95SChuanqi Xu 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}}
60452fac95SChuanqi Xu   co_return;
61452fac95SChuanqi Xu }
62*448995c5SChuanqi Xu 
63*448995c5SChuanqi Xu struct promise_base1 {
64*448995c5SChuanqi Xu   void *operator new(std::size_t sz); // expected-note {{member found by ambiguous name lookup}}
65*448995c5SChuanqi Xu };
66*448995c5SChuanqi Xu 
67*448995c5SChuanqi Xu struct promise_base2 {
68*448995c5SChuanqi Xu   void *operator new(std::size_t sz); // expected-note {{member found by ambiguous name lookup}}
69*448995c5SChuanqi Xu };
70*448995c5SChuanqi Xu 
71*448995c5SChuanqi Xu struct resumable2 {
72*448995c5SChuanqi Xu   struct promise_type : public promise_base1, public promise_base2 {
get_return_objectresumable2::promise_type73*448995c5SChuanqi Xu     resumable2 get_return_object() { return {}; }
initial_suspendresumable2::promise_type74*448995c5SChuanqi Xu     auto initial_suspend() { return std::suspend_always(); }
final_suspendresumable2::promise_type75*448995c5SChuanqi Xu     auto final_suspend() noexcept { return std::suspend_always(); }
unhandled_exceptionresumable2::promise_type76*448995c5SChuanqi Xu     void unhandled_exception() {}
return_voidresumable2::promise_type77*448995c5SChuanqi Xu     void return_void(){};
78*448995c5SChuanqi Xu   };
79*448995c5SChuanqi Xu };
80*448995c5SChuanqi Xu 
f7()81*448995c5SChuanqi Xu resumable2 f7() { // expected-error {{member 'operator new' found in multiple base classes of different types}}
82*448995c5SChuanqi Xu   co_return;
83*448995c5SChuanqi Xu }
84