1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 // UNSUPPORTED: c++03, c++11
10
11 // See https://llvm.org/PR33271
12 // UNSUPPORTED: ubsan
13
14 #include <experimental/coroutine>
15 #include <vector>
16 #include <cassert>
17
18 #include "test_macros.h"
19 #include "coroutine_types.h"
20
21 using namespace std::experimental;
22
23 struct minig {
24 struct promise_type {
25 int current_value;
yield_valueminig::promise_type26 suspend_always yield_value(int value) {
27 this->current_value = value;
28 return {};
29 }
initial_suspendminig::promise_type30 suspend_always initial_suspend() { return {}; }
final_suspendminig::promise_type31 suspend_always final_suspend() noexcept { return {}; }
get_return_objectminig::promise_type32 minig get_return_object() { return minig{this}; };
return_voidminig::promise_type33 void return_void() {}
unhandled_exceptionminig::promise_type34 void unhandled_exception() {}
35 };
36
move_nextminig37 bool move_next() {
38 p.resume();
39 return !p.done();
40 }
current_valueminig41 int current_value() { return p.promise().current_value; }
42
minigminig43 minig(minig &&rhs) : p(rhs.p) { rhs.p = nullptr; }
44
~minigminig45 ~minig() {
46 if (p)
47 p.destroy();
48 }
49
50 private:
minigminig51 explicit minig(promise_type *p)
52 : p(coroutine_handle<promise_type>::from_promise(*p)) {}
53
54 coroutine_handle<promise_type> p;
55 };
56
57
mini_count(int n)58 minig mini_count(int n) {
59 for (int i = 0; i < n; i++) {
60 co_yield i;
61 }
62 }
63
count(int n)64 generator<int> count(int n) {
65 for (int i = 0; i < n; ++i)
66 co_yield i;
67 }
68
range(int from,int n)69 generator<int> range(int from, int n) {
70 for (int i = from; i < n; ++i)
71 co_yield i;
72 }
73
test_count()74 void test_count() {
75 const std::vector<int> expect = {0, 1, 2, 3, 4};
76 std::vector<int> got;
77 for (auto x : count(5))
78 got.push_back(x);
79 assert(expect == got);
80 }
81
test_range()82 void test_range() {
83 int sum = 0;
84 for (auto v: range(1, 20))
85 sum += v;
86 assert(sum == 190);
87 }
88
test_mini_generator()89 void test_mini_generator() {
90 int sum = 0;
91 auto g = mini_count(5);
92 while (g.move_next()) {
93 sum += g.current_value();
94 }
95 assert(sum == 10);
96 }
97
main(int,char **)98 int main(int, char**) {
99 test_count();
100 test_range();
101 test_mini_generator();
102
103 return 0;
104 }
105