1 // This tests that the coroutine heap allocation elision optimization could happen succesfully.
2 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -O2 -emit-llvm %s -o - | FileCheck %s
4 #include "Inputs/coroutine.h"
5 #include "Inputs/numeric.h"
7 template <typename T
> struct generator
{
10 std::suspend_always
yield_value(T value
) {
11 this->current_value
= value
;
14 std::suspend_always
initial_suspend() { return {}; }
15 std::suspend_always
final_suspend() noexcept
{ return {}; }
16 generator
get_return_object() { return generator
{this}; };
17 void unhandled_exception() {}
22 std::coroutine_handle
<promise_type
> _Coro
;
25 iterator(std::coroutine_handle
<promise_type
> Coro
, bool Done
)
26 : _Coro(Coro
), _Done(Done
) {}
28 iterator
&operator++() {
34 bool operator==(iterator
const &_Right
) const {
35 return _Done
== _Right
._Done
;
38 bool operator!=(iterator
const &_Right
) const { return !(*this == _Right
); }
39 T
const &operator*() const { return _Coro
.promise().current_value
; }
40 T
const *operator->() const { return &(operator*()); }
48 iterator
end() { return {p
, true}; }
50 generator(generator
const &) = delete;
51 generator(generator
&&rhs
) : p(rhs
.p
) { rhs
.p
= nullptr; }
59 explicit generator(promise_type
*p
)
60 : p(std::coroutine_handle
<promise_type
>::from_promise(*p
)) {}
62 std::coroutine_handle
<promise_type
> p
;
72 generator
<T
> take_until(generator
<T
> &g
, T limit
) {
81 generator
<T
> multiply(generator
<T
> &g
, T factor
) {
87 generator
<T
> add(generator
<T
> &g
, T adder
) {
94 auto t
= take_until(s
, 10);
95 auto m
= multiply(t
, 2);
97 return std::accumulate(a
.begin(), a
.end(), 0);
100 // CHECK-LABEL: define{{.*}} i32 @main(
101 // CHECK: ret i32 1190
102 // CHECK-NOT: call{{.*}}_Znwm