1 // Tests that we can mark await-suspend as noinline correctly.
3 // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s \
4 // RUN: -O1 -disable-llvm-passes | FileCheck %s
6 #include "Inputs/coroutine.h"
11 bool await_ready() const noexcept
{ return false; }
12 template <typename PromiseType
>
13 std::coroutine_handle
<> await_suspend(std::coroutine_handle
<PromiseType
> h
) noexcept
{
14 return h
.promise().continuation
;
16 void await_resume() noexcept
{}
19 Task
get_return_object() noexcept
{
20 return std::coroutine_handle
<promise_type
>::from_promise(*this);
23 std::suspend_always
initial_suspend() noexcept
{ return {}; }
24 FinalAwaiter
final_suspend() noexcept
{ return {}; }
25 void unhandled_exception() noexcept
{}
26 void return_void() noexcept
{}
28 std::coroutine_handle
<> continuation
;
31 Task(std::coroutine_handle
<promise_type
> handle
);
35 std::coroutine_handle
<promise_type
> handle
;
38 struct StatefulAwaiter
{
40 bool await_ready() const noexcept
{ return false; }
41 template <typename PromiseType
>
42 void await_suspend(std::coroutine_handle
<PromiseType
> h
) noexcept
{}
43 void await_resume() noexcept
{}
46 typedef std::suspend_always NoStateAwaiter
;
47 using AnotherStatefulAwaiter
= StatefulAwaiter
;
50 struct TemplatedAwaiter
{
52 bool await_ready() const noexcept
{ return false; }
53 template <typename PromiseType
>
54 void await_suspend(std::coroutine_handle
<PromiseType
> h
) noexcept
{}
55 void await_resume() noexcept
{}
60 StatefulAwaiter
operator co_await(Awaitable
) {
61 return StatefulAwaiter
{};
64 StatefulAwaiter GlobalAwaiter
;
66 StatefulAwaiter
& operator co_await(Awaitable2
) {
70 struct AlwaysInlineStatefulAwaiter
{
72 bool await_ready() const noexcept
{ return false; }
74 template <typename PromiseType
>
75 __attribute__((always_inline
))
76 void await_suspend(std::coroutine_handle
<PromiseType
> h
) noexcept
{}
78 void await_resume() noexcept
{}
82 co_await
std::suspend_always
{};
83 co_await StatefulAwaiter
{};
84 co_await AnotherStatefulAwaiter
{};
87 StatefulAwaiter awaiter
;
90 // The explicit call to await_suspend is not considered suspended.
91 awaiter
.await_suspend(std::coroutine_handle
<void>::from_address(nullptr));
93 co_await TemplatedAwaiter
<int>{};
94 TemplatedAwaiter
<int> TemplatedAwaiterInstace
;
95 co_await TemplatedAwaiterInstace
;
98 co_await Awaitable2
{};
100 co_await AlwaysInlineStatefulAwaiter
{};
103 struct AwaitTransformTask
{
104 struct promise_type
{
105 struct FinalAwaiter
{
106 bool await_ready() const noexcept
{ return false; }
107 template <typename PromiseType
>
108 std::coroutine_handle
<> await_suspend(std::coroutine_handle
<PromiseType
> h
) noexcept
{
109 return h
.promise().continuation
;
111 void await_resume() noexcept
{}
114 AwaitTransformTask
get_return_object() noexcept
{
115 return std::coroutine_handle
<promise_type
>::from_promise(*this);
118 std::suspend_always
initial_suspend() noexcept
{ return {}; }
119 FinalAwaiter
final_suspend() noexcept
{ return {}; }
120 void unhandled_exception() noexcept
{}
121 void return_void() noexcept
{}
123 template <typename Awaitable
>
124 auto await_transform(Awaitable
&&awaitable
) {
128 std::coroutine_handle
<> continuation
;
131 AwaitTransformTask(std::coroutine_handle
<promise_type
> handle
);
132 ~AwaitTransformTask();
135 std::coroutine_handle
<promise_type
> handle
;
138 struct awaitableWithGetAwaiter
{
139 bool await_ready() const noexcept
{ return false; }
140 template <typename PromiseType
>
141 void await_suspend(std::coroutine_handle
<PromiseType
> h
) noexcept
{}
142 void await_resume() noexcept
{}
145 AwaitTransformTask
testingWithAwaitTransform() {
146 co_await awaitableWithGetAwaiter
{};
149 // CHECK: define{{.*}}@_ZNSt14suspend_always13await_suspendESt16coroutine_handleIvE{{.*}}#[[NORMAL_ATTR:[0-9]+]]
151 // CHECK: define{{.*}}@_ZN15StatefulAwaiter13await_suspendIN4Task12promise_typeEEEvSt16coroutine_handleIT_E{{.*}}#[[NOINLINE_ATTR:[0-9]+]]
153 // CHECK: define{{.*}}@_ZN15StatefulAwaiter13await_suspendIvEEvSt16coroutine_handleIT_E{{.*}}#[[NORMAL_ATTR]]
155 // CHECK: define{{.*}}@_ZN16TemplatedAwaiterIiE13await_suspendIN4Task12promise_typeEEEvSt16coroutine_handleIT_E{{.*}}#[[NOINLINE_ATTR]]
157 // CHECK: define{{.*}}@_ZN27AlwaysInlineStatefulAwaiter13await_suspendIN4Task12promise_typeEEEvSt16coroutine_handleIT_E{{.*}}#[[ALWAYS_INLINE_ATTR:[0-9]+]]
159 // CHECK: define{{.*}}@_ZN4Task12promise_type12FinalAwaiter13await_suspendIS0_EESt16coroutine_handleIvES3_IT_E{{.*}}#[[NORMAL_ATTR]]
161 // CHECK: define{{.*}}@_ZN23awaitableWithGetAwaiter13await_suspendIN18AwaitTransformTask12promise_typeEEEvSt16coroutine_handleIT_E{{.*}}#[[NORMAL_ATTR]]
163 // CHECK: define{{.*}}@_ZN18AwaitTransformTask12promise_type12FinalAwaiter13await_suspendIS0_EESt16coroutine_handleIvES3_IT_E{{.*}}#[[NORMAL_ATTR]]
165 // CHECK-NOT: attributes #[[NORMAL_ATTR]] = noinline
166 // CHECK: attributes #[[NOINLINE_ATTR]] = {{.*}}noinline
167 // CHECK-NOT: attributes #[[ALWAYS_INLINE_ATTR]] = {{.*}}noinline
168 // CHECK: attributes #[[ALWAYS_INLINE_ATTR]] = {{.*}}alwaysinline