xref: /llvm-project/clang/test/SemaCXX/warn-unsequenced-coro.cpp (revision 0b8daee028a87ab8a6f8fe54d2eb2d5b5c2babd4)
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 Lopes Task<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 Lopes generator<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 Lopes Task<int> go1(int x) {
104*0b8daee0SBruno Cardoso Lopes   co_return co_await go(++x);
105*0b8daee0SBruno Cardoso Lopes }