Index: libcxx/docs/Status/Cxx2bIssues.csv =================================================================== --- libcxx/docs/Status/Cxx2bIssues.csv +++ 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","","" Index: libcxx/include/__coroutine/noop_coroutine_handle.h =================================================================== --- libcxx/include/__coroutine/noop_coroutine_handle.h +++ libcxx/include/__coroutine/noop_coroutine_handle.h @@ -20,7 +20,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if __has_builtin(__builtin_coro_noop) +// Avoid any other compiler which didn't implement '__builtin_coro_noop' +// nor GCC to compile this. +#if __has_builtin(__builtin_coro_noop) || defined(_LIBCPP_COMPILER_GCC) // [coroutine.noop] // [coroutine.promise.noop] struct noop_coroutine_promise {}; @@ -64,20 +66,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 didn't implement '__builtin_coro_noop()' and construct the + // frame for noop_coroutine from source 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 Index: libcxx/test/std/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp =================================================================== --- libcxx/test/std/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp +++ libcxx/test/std/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp @@ -21,7 +21,7 @@ #include "test_macros.h" -#if __has_builtin(__builtin_coro_noop) +#if __has_builtin(__builtin_coro_noop) || defined(_LIBCPP_COMPILER_GCC) static_assert(std::is_same, std::noop_coroutine_handle>::value, ""); static_assert(std::is_same::value, ""); @@ -60,9 +60,20 @@ static_assert(h.done() == false, ""); static_assert(h, ""); + // [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); @@ -73,4 +84,4 @@ int main(int, char**) { return 0; } -#endif // __has_builtin(__builtin_coro_noop) +#endif // __has_builtin(__builtin_coro_noop) || defined(_LIBCPP_COMPILER_GCC)