diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2022-01-10 20:48:53 +0000 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2022-01-11 13:28:46 +0000 |
commit | 265d3e1a4e3d6c71d354f859302f023dc2d33f62 (patch) | |
tree | 5b1571d3734b6991d9d70a9b400e6a345db19eee | |
parent | e4fe6dba90b831dbd8f5e23041c5e0e8bdd75332 (diff) | |
download | gcc-265d3e1a4e3d6c71d354f859302f023dc2d33f62.zip gcc-265d3e1a4e3d6c71d354f859302f023dc2d33f62.tar.gz gcc-265d3e1a4e3d6c71d354f859302f023dc2d33f62.tar.bz2 |
libstdc++: Install <coroutine> header for freestanding [PR103726]
The standard says that <coroutine> should be present for freestanding.
That was intentionally left out of the initial implementation, but can
be done without much trouble. The header should be moved to libsupc++ at
some point in stage 1.
The standard also says that <coroutine> defines a std::hash
specialization, which was missing from our implementation. That's a
problem for freestanding (see LWG 3653) so only do that for hosted.
We can use concepts to constrain the __coroutine_traits_impl base class
when compiled with concepts enabled. In a pure C++20 implementation we
would not need that base class at all and could just use a constrained
partial specialization of coroutine_traits. But the absence of the
__coroutine_traits_impl<R, void> base would create an ABI difference
between the non-standard C++14/C++17 support for coroutines and the same
code compiled as C++20. If we drop support for <coroutine> pre-C++20 we
should revisit this.
libstdc++-v3/ChangeLog:
PR libstdc++/103726
* include/Makefile.am: Install <coroutine> for freestanding.
* include/Makefile.in: Regenerate.
* include/std/coroutine: Adjust headers and preprocessor
conditions.
(__coroutine_traits_impl): Use concepts when available.
[_GLIBCXX_HOSTED] (hash<coroutine_handle>): Define.
-rw-r--r-- | libstdc++-v3/include/Makefile.am | 4 | ||||
-rw-r--r-- | libstdc++-v3/include/Makefile.in | 4 | ||||
-rw-r--r-- | libstdc++-v3/include/std/coroutine | 55 |
3 files changed, 45 insertions, 18 deletions
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index 7afebb5..8f93bf2 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -1425,7 +1425,7 @@ endif # This is a subset of the full install-headers rule. We only need <ciso646>, # <cstddef>, <cfloat>, <limits>, <climits>, <version>, <cstdint>, <cstdlib>, # <new>, <typeinfo>, <exception>, <initializer_list>, <cstdalign>, <cstdarg>, -# <concepts>, <cstdbool>, <type_traits>, <bit>, <atomic>, +# <concepts>, <coroutine>, <cstdbool>, <type_traits>, <bit>, <atomic>, # and any files which they include (and which we provide). # <new>, <typeinfo>, <exception>, <initializer_list> and <compare> # are installed by libsupc++, so only the others and the sub-includes @@ -1440,7 +1440,7 @@ install-freestanding-headers: ${glibcxx_srcdir}/$(CPU_DEFINES_SRCDIR)/cpu_defines.h; do \ $(INSTALL_DATA) $${file} $(DESTDIR)${host_installdir}; done $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${std_builddir} - for file in limits type_traits atomic bit concepts version; do \ + for file in limits type_traits atomic bit concepts coroutine version; do \ $(INSTALL_DATA) ${std_builddir}/$${file} $(DESTDIR)${gxx_include_dir}/${std_builddir}; done $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${c_base_builddir} for file in ciso646 cstddef cfloat climits cstdint cstdlib \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index 0031f54..4ab942a 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -1906,7 +1906,7 @@ ${pch3_output}: ${pch3_source} ${pch2_output} # This is a subset of the full install-headers rule. We only need <ciso646>, # <cstddef>, <cfloat>, <limits>, <climits>, <version>, <cstdint>, <cstdlib>, # <new>, <typeinfo>, <exception>, <initializer_list>, <cstdalign>, <cstdarg>, -# <concepts>, <cstdbool>, <type_traits>, <bit>, <atomic>, +# <concepts>, <coroutine>, <cstdbool>, <type_traits>, <bit>, <atomic>, # and any files which they include (and which we provide). # <new>, <typeinfo>, <exception>, <initializer_list> and <compare> # are installed by libsupc++, so only the others and the sub-includes @@ -1921,7 +1921,7 @@ install-freestanding-headers: ${glibcxx_srcdir}/$(CPU_DEFINES_SRCDIR)/cpu_defines.h; do \ $(INSTALL_DATA) $${file} $(DESTDIR)${host_installdir}; done $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${std_builddir} - for file in limits type_traits atomic bit concepts version; do \ + for file in limits type_traits atomic bit concepts coroutine version; do \ $(INSTALL_DATA) ${std_builddir}/$${file} $(DESTDIR)${gxx_include_dir}/${std_builddir}; done $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${c_base_builddir} for file in ciso646 cstddef cfloat climits cstdint cstdlib \ diff --git a/libstdc++-v3/include/std/coroutine b/libstdc++-v3/include/std/coroutine index ead5dad..f4189c7 100644 --- a/libstdc++-v3/include/std/coroutine +++ b/libstdc++-v3/include/std/coroutine @@ -34,22 +34,23 @@ // It is very likely that earlier versions would work, but they are untested. #if __cplusplus >= 201402L -#include <bits/c++config.h> +#include <type_traits> +#if __cplusplus > 201703L +# include <compare> +#endif + +#if !defined __cpp_lib_three_way_comparison && _GLIBCXX_HOSTED +# include <bits/stl_function.h> // for std::less +#endif /** * @defgroup coroutines Coroutines * * Components for supporting coroutine implementations. + * + * @since C++20 (and since C++14 as a libstdc++ extension) */ -#if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L -# include <compare> -# define _COROUTINES_USE_SPACESHIP 1 -#else -# include <bits/stl_function.h> // for std::less -# define _COROUTINES_USE_SPACESHIP 0 -#endif - namespace std _GLIBCXX_VISIBILITY (default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -60,25 +61,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline namespace __n4861 { - // 17.12.2 coroutine traits + // C++20 17.12.2 coroutine traits /// [coroutine.traits] /// [coroutine.traits.primary] /// If _Result::promise_type is valid and denotes a type then the traits /// have a single publicly accessible member, otherwise they are empty. + template <typename _Result, typename... _ArgTypes> + struct coroutine_traits; + template <typename _Result, typename = void> struct __coroutine_traits_impl {}; template <typename _Result> +#if __cpp_concepts + requires requires { typename _Result::promise_type; } + struct __coroutine_traits_impl<_Result, void> +#else struct __coroutine_traits_impl<_Result, - __void_t<typename _Result::promise_type>> + __void_t<typename _Result::promise_type>> +#endif { using promise_type = typename _Result::promise_type; }; - template <typename _Result, typename...> + template <typename _Result, typename... _ArgTypes> struct coroutine_traits : __coroutine_traits_impl<_Result> {}; - // 17.12.3 Class template coroutine_handle + // C++20 17.12.3 Class template coroutine_handle /// [coroutine.handle] template <typename _Promise = void> struct coroutine_handle; @@ -139,7 +148,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __a.address() == __b.address(); } -#if _COROUTINES_USE_SPACESHIP +#ifdef __cpp_lib_three_way_comparison constexpr strong_ordering operator<=>(coroutine_handle<> __a, coroutine_handle<> __b) noexcept { @@ -156,7 +165,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr bool operator<(coroutine_handle<> __a, coroutine_handle<> __b) noexcept { +#if _GLIBCXX_HOSTED return less<void*>()(__a.address(), __b.address()); +#else + return (__UINTPTR_TYPE__)__a.address() < (__UINTPTR_TYPE__)__b.address(); +#endif } constexpr bool @@ -330,6 +343,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } // namespace __n4861 +#if _GLIBCXX_HOSTED + template<typename _Tp> struct hash; + + template<typename _Promise> + struct hash<coroutine_handle<_Promise>> + { + size_t + operator()(const coroutine_handle<_Promise>& __h) noexcept + { + return reinterpret_cast<size_t>(__h.address()); + } + }; +#endif + #else #error "the coroutine header requires -fcoroutines" #endif |