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