diff --git a/libcxx/docs/Status/Cxx2bIssues.csv b/libcxx/docs/Status/Cxx2bIssues.csv --- a/libcxx/docs/Status/Cxx2bIssues.csv +++ b/libcxx/docs/Status/Cxx2bIssues.csv @@ -37,7 +37,7 @@ "`3449 `__","``take_view`` and ``take_while_view``'s ``sentinel`` not comparable with their ``const iterator``","November 2020","","","|ranges|" "`3453 `__","Generic code cannot call ``ranges::advance(i, s)``","November 2020","","","|ranges|" "`3455 `__","Incorrect Postconditions on ``unique_ptr`` move assignment","November 2020","|Nothing To Do|","" -"`3460 `__","Unimplementable ``noop_coroutine_handle`` guarantees","November 2020","","" +"`3460 `__","Unimplementable ``noop_coroutine_handle`` guarantees","November 2020","|Complete|","14.0" "`3461 `__","``convertible_to``'s description mishandles cv-qualified ``void``","November 2020","","" "`3465 `__","``compare_partial_order_fallback`` requires ``F < E``","November 2020","","","|spaceship|" "`3466 `__","Specify the requirements for ``promise``/``future``/``shared_future`` consistently","November 2020","","" diff --git a/libcxx/include/__coroutine/noop_coroutine_handle.h b/libcxx/include/__coroutine/noop_coroutine_handle.h --- a/libcxx/include/__coroutine/noop_coroutine_handle.h +++ b/libcxx/include/__coroutine/noop_coroutine_handle.h @@ -20,7 +20,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if __has_builtin(__builtin_coro_noop) +#if __has_builtin(__builtin_coro_noop) || defined(_LIBCPP_COMPILER_GCC) + // [coroutine.noop] // [coroutine.promise.noop] struct noop_coroutine_promise {}; @@ -64,20 +65,45 @@ _LIBCPP_HIDE_FROM_ABI friend coroutine_handle noop_coroutine() noexcept; +#if __has_builtin(__builtin_coro_noop) _LIBCPP_HIDE_FROM_ABI coroutine_handle() noexcept { this->__handle_ = __builtin_coro_noop(); } void* __handle_ = nullptr; + +#elif defined(_LIBCPP_COMPILER_GCC) + // GCC doesn't implement __builtin_coro_noop(). + // Construct the coroutine frame manually instead. + struct __noop_coroutine_frame_ty_ { + static void __dummy_resume_destroy_func() { } + + void (*__resume_)() = __dummy_resume_destroy_func; + void (*__destroy_)() = __dummy_resume_destroy_func; + struct noop_coroutine_promise __promise_; + }; + + static __noop_coroutine_frame_ty_ __noop_coroutine_frame_; + + void* __handle_ = &__noop_coroutine_frame_; + + _LIBCPP_HIDE_FROM_ABI coroutine_handle() noexcept = default; + +#endif // __has_builtin(__builtin_coro_noop) }; using noop_coroutine_handle = coroutine_handle; +#if defined(_LIBCPP_COMPILER_GCC) +inline noop_coroutine_handle::__noop_coroutine_frame_ty_ + noop_coroutine_handle::__noop_coroutine_frame_{}; +#endif + // [coroutine.noop.coroutine] inline _LIBCPP_HIDE_FROM_ABI noop_coroutine_handle noop_coroutine() noexcept { return noop_coroutine_handle(); } -#endif // __has_builtin(__builtin_coro_noop) +#endif // __has_builtin(__builtin_coro_noop) || defined(_LIBCPP_COMPILER_GCC) _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/test/std/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp b/libcxx/test/std/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp --- a/libcxx/test/std/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp +++ b/libcxx/test/std/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp @@ -21,8 +21,6 @@ #include "test_macros.h" -#if __has_builtin(__builtin_coro_noop) - static_assert(std::is_same, std::noop_coroutine_handle>::value, ""); static_assert(std::is_same::value, ""); @@ -57,20 +55,25 @@ h.resume(); h.destroy(); h(); - static_assert(h.done() == false, ""); static_assert(h, ""); + static_assert(h.done() == false, ""); + + // [coroutine.handle.noop.resumption]p2 + // Remarks: If noop_­coroutine_­handle is converted to + // coroutine_­handle<>, calls to operator(), resume and + // destroy on that handle will also have no observable + // effects. + base.resume(); + base.destroy(); + base(); + assert(base); + assert(base.done() == false); h.promise(); assert(h.address() == base.address()); - assert(h==base); + assert(h == base); assert(h.address() != nullptr); assert(std::coroutine_handle<>::from_address(h.address()) == base); return 0; } - -#else - -int main(int, char**) { return 0; } - -#endif // __has_builtin(__builtin_coro_noop)