Skip to content

Commit 6441536

Browse files
committed
[libcxx] [Coroutines] Support noop_coroutine for GCC
We didn't support noop_coroutine for GCC in previous conforming patch. So that GCC couldn't use noop_coroutine() defined in <coroutine>. And after this patch, GCC should be able to compile the whole <coroutine> header. Reviewed By: Quuxplusone Differential Revision: https://reviews.llvm.org/D116144
1 parent 64038ef commit 6441536

File tree

3 files changed

+42
-13
lines changed

3 files changed

+42
-13
lines changed

Diff for: libcxx/docs/Status/Cxx2bIssues.csv

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"`3449 <https://wg21.link/LWG3449>`__","``take_view`` and ``take_while_view``'s ``sentinel<false>`` not comparable with their ``const iterator``","November 2020","","","|ranges|"
3838
"`3453 <https://wg21.link/LWG3453>`__","Generic code cannot call ``ranges::advance(i, s)``","November 2020","","","|ranges|"
3939
"`3455 <https://wg21.link/LWG3455>`__","Incorrect Postconditions on ``unique_ptr`` move assignment","November 2020","|Nothing To Do|",""
40-
"`3460 <https://wg21.link/LWG3460>`__","Unimplementable ``noop_coroutine_handle`` guarantees","November 2020","",""
40+
"`3460 <https://wg21.link/LWG3460>`__","Unimplementable ``noop_coroutine_handle`` guarantees","November 2020","|Complete|","14.0"
4141
"`3461 <https://wg21.link/LWG3461>`__","``convertible_to``'s description mishandles cv-qualified ``void``","November 2020","",""
4242
"`3465 <https://wg21.link/LWG3465>`__","``compare_partial_order_fallback`` requires ``F < E``","November 2020","","","|spaceship|"
4343
"`3466 <https://wg21.link/LWG3466>`__","Specify the requirements for ``promise``/``future``/``shared_future`` consistently","November 2020","",""

Diff for: libcxx/include/__coroutine/noop_coroutine_handle.h

+28-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020

2121
_LIBCPP_BEGIN_NAMESPACE_STD
2222

23-
#if __has_builtin(__builtin_coro_noop)
23+
#if __has_builtin(__builtin_coro_noop) || defined(_LIBCPP_COMPILER_GCC)
24+
2425
// [coroutine.noop]
2526
// [coroutine.promise.noop]
2627
struct noop_coroutine_promise {};
@@ -64,20 +65,45 @@ struct _LIBCPP_TEMPLATE_VIS coroutine_handle<noop_coroutine_promise> {
6465
_LIBCPP_HIDE_FROM_ABI
6566
friend coroutine_handle<noop_coroutine_promise> noop_coroutine() noexcept;
6667

68+
#if __has_builtin(__builtin_coro_noop)
6769
_LIBCPP_HIDE_FROM_ABI coroutine_handle() noexcept {
6870
this->__handle_ = __builtin_coro_noop();
6971
}
7072

7173
void* __handle_ = nullptr;
74+
75+
#elif defined(_LIBCPP_COMPILER_GCC)
76+
// GCC doesn't implement __builtin_coro_noop().
77+
// Construct the coroutine frame manually instead.
78+
struct __noop_coroutine_frame_ty_ {
79+
static void __dummy_resume_destroy_func() { }
80+
81+
void (*__resume_)() = __dummy_resume_destroy_func;
82+
void (*__destroy_)() = __dummy_resume_destroy_func;
83+
struct noop_coroutine_promise __promise_;
84+
};
85+
86+
static __noop_coroutine_frame_ty_ __noop_coroutine_frame_;
87+
88+
void* __handle_ = &__noop_coroutine_frame_;
89+
90+
_LIBCPP_HIDE_FROM_ABI coroutine_handle() noexcept = default;
91+
92+
#endif // __has_builtin(__builtin_coro_noop)
7293
};
7394

7495
using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;
7596

97+
#if defined(_LIBCPP_COMPILER_GCC)
98+
inline noop_coroutine_handle::__noop_coroutine_frame_ty_
99+
noop_coroutine_handle::__noop_coroutine_frame_{};
100+
#endif
101+
76102
// [coroutine.noop.coroutine]
77103
inline _LIBCPP_HIDE_FROM_ABI
78104
noop_coroutine_handle noop_coroutine() noexcept { return noop_coroutine_handle(); }
79105

80-
#endif // __has_builtin(__builtin_coro_noop)
106+
#endif // __has_builtin(__builtin_coro_noop) || defined(_LIBCPP_COMPILER_GCC)
81107

82108
_LIBCPP_END_NAMESPACE_STD
83109

Diff for: libcxx/test/std/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp

+13-10
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121

2222
#include "test_macros.h"
2323

24-
#if __has_builtin(__builtin_coro_noop)
25-
2624
static_assert(std::is_same<std::coroutine_handle<std::noop_coroutine_promise>, std::noop_coroutine_handle>::value, "");
2725
static_assert(std::is_same<decltype(std::noop_coroutine()), std::noop_coroutine_handle>::value, "");
2826

@@ -57,20 +55,25 @@ int main(int, char**)
5755
h.resume();
5856
h.destroy();
5957
h();
60-
static_assert(h.done() == false, "");
6158
static_assert(h, "");
59+
static_assert(h.done() == false, "");
60+
61+
// [coroutine.handle.noop.resumption]p2
62+
// Remarks: If noop_­coroutine_­handle is converted to
63+
// coroutine_­handle<>, calls to operator(), resume and
64+
// destroy on that handle will also have no observable
65+
// effects.
66+
base.resume();
67+
base.destroy();
68+
base();
69+
assert(base);
70+
assert(base.done() == false);
6271

6372
h.promise();
6473
assert(h.address() == base.address());
65-
assert(h==base);
74+
assert(h == base);
6675
assert(h.address() != nullptr);
6776
assert(std::coroutine_handle<>::from_address(h.address()) == base);
6877

6978
return 0;
7079
}
71-
72-
#else
73-
74-
int main(int, char**) { return 0; }
75-
76-
#endif // __has_builtin(__builtin_coro_noop)

0 commit comments

Comments
 (0)