1 // RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++20 -fsyntax-only -verify -Wall -Wextra -Wno-error=unreachable-code -Wno-unused -Wno-c++23-lambda-attributes
3 #include "Inputs/std-coroutine.h"
5 using std::suspend_always
;
6 using std::suspend_never
;
8 template <typename T
> struct [[clang::coro_lifetimebound
, clang::coro_return_type
]] Co
{
10 Co
<T
> get_return_object() {
13 suspend_always
initial_suspend();
14 suspend_always
final_suspend() noexcept
;
15 void unhandled_exception();
16 void return_value(const T
&t
);
19 auto await_transform(const Co
<U
> &) {
21 bool await_ready() noexcept
{ return false; }
22 void await_suspend(std::coroutine_handle
<>) noexcept
{}
23 U
await_resume() noexcept
{ return {}; }
30 Co
<int> foo_coro(const int& b
) {
36 int getInt() { return 0; }
38 Co
<int> bar_coro(const int &b
, int c
) {
39 int x
= co_await
foo_coro(b
);
40 int y
= co_await
foo_coro(1);
41 int z
= co_await
foo_coro(getInt());
42 auto unsafe1
= foo_coro(1); // expected-warning {{temporary whose address is used as value of local variable}}
43 auto unsafe2
= foo_coro(getInt()); // expected-warning {{temporary whose address is used as value of local variable}}
44 auto safe1
= foo_coro(b
);
45 auto safe2
= foo_coro(c
);
46 co_return co_await
foo_coro(co_await
foo_coro(1));
49 [[clang::coro_wrapper
]] Co
<int> plain_return_co(int b
) {
50 return foo_coro(b
); // expected-warning {{address of stack memory associated with parameter}}
53 [[clang::coro_wrapper
]] Co
<int> safe_forwarding(const int& b
) {
57 [[clang::coro_wrapper
]] Co
<int> unsafe_wrapper(int b
) {
58 return safe_forwarding(b
); // expected-warning {{address of stack memory associated with parameter}}
61 [[clang::coro_wrapper
]] Co
<int> complex_plain_return(int b
) {
63 ? foo_coro(1) // expected-warning {{returning address of local temporary object}}
64 : bar_coro(0, 1); // expected-warning {{returning address of local temporary object}}
68 auto unsafe_lambda
= [] [[clang::coro_wrapper
]] (int b
) {
69 return foo_coro(b
); // expected-warning {{address of stack memory associated with parameter}}
71 auto coro_lambda
= [] (const int&) -> Co
<int> {
74 auto unsafe_coro_lambda
= [&] (const int& b
) -> Co
<int> {
75 int x
= co_await
coro_lambda(b
);
76 auto safe
= coro_lambda(b
);
77 auto unsafe1
= coro_lambda(1); // expected-warning {{temporary whose address is used as value of local variable}}
78 auto unsafe2
= coro_lambda(getInt()); // expected-warning {{temporary whose address is used as value of local variable}}
79 auto unsafe3
= coro_lambda(co_await
coro_lambda(b
)); // expected-warning {{temporary whose address is used as value of local variable}}
80 co_return co_await safe
;
82 auto safe_lambda
= [](int b
) -> Co
<int> {
83 int x
= co_await
foo_coro(1);
84 co_return x
+ co_await
foo_coro(b
);
87 // =============================================================================
88 // Safe usage when parameters are value
89 // =============================================================================
91 Co
<int> value_coro(int b
) { co_return co_await
foo_coro(b
); }
92 [[clang::coro_wrapper
]] Co
<int> wrapper1(int b
) { return value_coro(b
); }
93 [[clang::coro_wrapper
]] Co
<int> wrapper2(const int& b
) { return value_coro(b
); }
96 // =============================================================================
97 // Lifetime bound but not a Coroutine Return Type: No analysis.
98 // =============================================================================
100 template <typename T
> struct [[clang::coro_lifetimebound
]] CoNoCRT
{
101 struct promise_type
{
102 CoNoCRT
<T
> get_return_object() {
105 suspend_always
initial_suspend();
106 suspend_always
final_suspend() noexcept
;
107 void unhandled_exception();
108 void return_value(const T
&t
);
112 CoNoCRT
<int> foo_coro(const int& a
) { co_return a
; }
113 CoNoCRT
<int> bar(int a
) {
114 auto x
= foo_coro(a
);
117 } // namespace not_a_crt