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