1*0b8daee0SBruno Cardoso Lopes // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify -std=c++20 -I%S/Inputs -Wno-unused -Wno-uninitialized -Wunsequenced %s 2*0b8daee0SBruno Cardoso Lopes 3*0b8daee0SBruno Cardoso Lopes // expected-no-diagnostics 4*0b8daee0SBruno Cardoso Lopes 5*0b8daee0SBruno Cardoso Lopes #include "std-coroutine.h" 6*0b8daee0SBruno Cardoso Lopes 7*0b8daee0SBruno Cardoso Lopes typedef __PTRDIFF_TYPE__ ptrdiff_t; 8*0b8daee0SBruno Cardoso Lopes 9*0b8daee0SBruno Cardoso Lopes using namespace std; 10*0b8daee0SBruno Cardoso Lopes 11*0b8daee0SBruno Cardoso Lopes template<class T> 12*0b8daee0SBruno Cardoso Lopes struct Task { 13*0b8daee0SBruno Cardoso Lopes struct promise_type { 14*0b8daee0SBruno Cardoso Lopes Task<T> get_return_object() noexcept; 15*0b8daee0SBruno Cardoso Lopes suspend_always initial_suspend() noexcept; 16*0b8daee0SBruno Cardoso Lopes suspend_always final_suspend() noexcept; 17*0b8daee0SBruno Cardoso Lopes void return_value(T); 18*0b8daee0SBruno Cardoso Lopes void unhandled_exception(); yield_valueTask::promise_type19*0b8daee0SBruno Cardoso Lopes auto yield_value(Task<T>) noexcept { return final_suspend(); } 20*0b8daee0SBruno Cardoso Lopes }; await_readyTask21*0b8daee0SBruno Cardoso Lopes bool await_ready() noexcept { return false; } await_suspendTask22*0b8daee0SBruno Cardoso Lopes void await_suspend(coroutine_handle<>) noexcept {} 23*0b8daee0SBruno Cardoso Lopes T await_resume(); 24*0b8daee0SBruno Cardoso Lopes }; 25*0b8daee0SBruno Cardoso Lopes 26*0b8daee0SBruno Cardoso Lopes template<> 27*0b8daee0SBruno Cardoso Lopes struct Task<void> { 28*0b8daee0SBruno Cardoso Lopes struct promise_type { 29*0b8daee0SBruno Cardoso Lopes Task<void> get_return_object() noexcept; 30*0b8daee0SBruno Cardoso Lopes suspend_always initial_suspend() noexcept; 31*0b8daee0SBruno Cardoso Lopes suspend_always final_suspend() noexcept; 32*0b8daee0SBruno Cardoso Lopes void return_void() noexcept; 33*0b8daee0SBruno Cardoso Lopes void unhandled_exception() noexcept; yield_valueTask::promise_type34*0b8daee0SBruno Cardoso Lopes auto yield_value(Task<void>) noexcept { return final_suspend(); } 35*0b8daee0SBruno Cardoso Lopes }; await_readyTask36*0b8daee0SBruno Cardoso Lopes bool await_ready() noexcept { return false; } await_suspendTask37*0b8daee0SBruno Cardoso Lopes void await_suspend(coroutine_handle<>) noexcept {} await_resumeTask38*0b8daee0SBruno Cardoso Lopes void await_resume() noexcept {} 39*0b8daee0SBruno Cardoso Lopes }; 40*0b8daee0SBruno Cardoso Lopes 41*0b8daee0SBruno Cardoso Lopes template <typename T> 42*0b8daee0SBruno Cardoso Lopes class generator 43*0b8daee0SBruno Cardoso Lopes { 44*0b8daee0SBruno Cardoso Lopes struct Promise 45*0b8daee0SBruno Cardoso Lopes { get_return_objectgenerator::Promise46*0b8daee0SBruno Cardoso Lopes auto get_return_object() { return generator{*this}; } initial_suspendgenerator::Promise47*0b8daee0SBruno Cardoso Lopes auto initial_suspend() { return suspend_never{}; } final_suspendgenerator::Promise48*0b8daee0SBruno Cardoso Lopes auto final_suspend() noexcept { return suspend_always{}; } unhandled_exceptiongenerator::Promise49*0b8daee0SBruno Cardoso Lopes void unhandled_exception() {} return_voidgenerator::Promise50*0b8daee0SBruno Cardoso Lopes void return_void() {} 51*0b8daee0SBruno Cardoso Lopes yield_valuegenerator::Promise52*0b8daee0SBruno Cardoso Lopes auto yield_value(T value) 53*0b8daee0SBruno Cardoso Lopes { 54*0b8daee0SBruno Cardoso Lopes value_ = std::move(value); 55*0b8daee0SBruno Cardoso Lopes return suspend_always{}; 56*0b8daee0SBruno Cardoso Lopes } 57*0b8daee0SBruno Cardoso Lopes 58*0b8daee0SBruno Cardoso Lopes T value_; 59*0b8daee0SBruno Cardoso Lopes }; 60*0b8daee0SBruno Cardoso Lopes 61*0b8daee0SBruno Cardoso Lopes using Handle = coroutine_handle<Promise>; 62*0b8daee0SBruno Cardoso Lopes 63*0b8daee0SBruno Cardoso Lopes struct sentinel{}; 64*0b8daee0SBruno Cardoso Lopes struct iterator 65*0b8daee0SBruno Cardoso Lopes { 66*0b8daee0SBruno Cardoso Lopes using iterator_category = input_iterator_tag; 67*0b8daee0SBruno Cardoso Lopes using value_type = T; 68*0b8daee0SBruno Cardoso Lopes using difference_type = ptrdiff_t; 69*0b8daee0SBruno Cardoso Lopes using reference = T &; 70*0b8daee0SBruno Cardoso Lopes using const_reference = const T &; 71*0b8daee0SBruno Cardoso Lopes using pointer = T *; 72*0b8daee0SBruno Cardoso Lopes operator ++generator::iterator73*0b8daee0SBruno Cardoso Lopes iterator &operator++() 74*0b8daee0SBruno Cardoso Lopes { 75*0b8daee0SBruno Cardoso Lopes h_.resume(); 76*0b8daee0SBruno Cardoso Lopes return *this; 77*0b8daee0SBruno Cardoso Lopes } operator *generator::iterator78*0b8daee0SBruno Cardoso Lopes const_reference &operator*() const { return h_.promise().value_; } operator !=generator::iterator79*0b8daee0SBruno Cardoso Lopes bool operator!=(sentinel) { return !h_.done(); } 80*0b8daee0SBruno Cardoso Lopes 81*0b8daee0SBruno Cardoso Lopes Handle h_; 82*0b8daee0SBruno Cardoso Lopes }; 83*0b8daee0SBruno Cardoso Lopes generator(Promise & p)84*0b8daee0SBruno Cardoso Lopes explicit generator(Promise &p) : h_(Handle::from_promise(p)) {} 85*0b8daee0SBruno Cardoso Lopes Handle h_; 86*0b8daee0SBruno Cardoso Lopes public: 87*0b8daee0SBruno Cardoso Lopes using promise_type = Promise; begin()88*0b8daee0SBruno Cardoso Lopes auto begin() { return iterator{h_}; } end()89*0b8daee0SBruno Cardoso Lopes auto end() { return sentinel{}; } 90*0b8daee0SBruno Cardoso Lopes }; 91*0b8daee0SBruno Cardoso Lopes c(int i)92*0b8daee0SBruno Cardoso LopesTask<void> c(int i) { 93*0b8daee0SBruno Cardoso Lopes co_await (i = 0, std::suspend_always{}); 94*0b8daee0SBruno Cardoso Lopes } 95*0b8daee0SBruno Cardoso Lopes range(int start,int end)96*0b8daee0SBruno Cardoso Lopesgenerator<int> range(int start, int end) 97*0b8daee0SBruno Cardoso Lopes { 98*0b8daee0SBruno Cardoso Lopes while (start < end) 99*0b8daee0SBruno Cardoso Lopes co_yield start++; 100*0b8daee0SBruno Cardoso Lopes } 101*0b8daee0SBruno Cardoso Lopes 102*0b8daee0SBruno Cardoso Lopes Task<int> go(int const& val); go1(int x)103*0b8daee0SBruno Cardoso LopesTask<int> go1(int x) { 104*0b8daee0SBruno Cardoso Lopes co_return co_await go(++x); 105*0b8daee0SBruno Cardoso Lopes }