From 14f50ba054079eccf9ac49997b92793e2a87b13c Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 29 Mar 2023 22:02:19 +0100 Subject: libstdc++: Enforce requirements on template argument of std::optional The standard does not allow std::optional, std::optional, std::optional etc. and although we do give errors, they come from down inside the internals of std::optional. We could improve the static assertions at the top of the class so that users get a more precise diagnostic: optional:721:21: error: static assertion failed 721 | static_assert(is_object_v<_Tp> && !is_array_v<_Tp>); libstdc++-v3/ChangeLog: * include/std/optional (optional): Adjust static assertion to reject arrays and functions as well as references. * testsuite/20_util/optional/requirements_neg.cc: New test. --- libstdc++-v3/include/std/optional | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional index 62ff87a..90bf741 100644 --- a/libstdc++-v3/include/std/optional +++ b/libstdc++-v3/include/std/optional @@ -718,7 +718,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { static_assert(!is_same_v, nullopt_t>); static_assert(!is_same_v, in_place_t>); - static_assert(!is_reference_v<_Tp>); + static_assert(is_object_v<_Tp> && !is_array_v<_Tp>); private: using _Base = _Optional_base<_Tp>; -- cgit v1.1 From 31a909712014b75fc6ae2ca5eaa425f218bb5f32 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 29 Mar 2023 22:16:55 +0100 Subject: libstdc++: Use std::remove_cv_t in std::optional::transform [PR109340] We need to strip cv-qualifiers from the result of the callable passed to std::optional::transform. For std::expected::transform and std::expected::transform_error I noticed we were stripping cv-qualifiers but were also incorrectly stripping references. libstdc++-v3/ChangeLog: PR libstdc++/109340 * include/std/expected (expected::transform): Use std::remove_cv_t instead of std::remove_cvref_t. (expected::transform_error): Likewise. (expected::transform): Likewise. (expected::transform_error): Likewise. * include/std/optional (transform): Use std::remove_cv_t. * testsuite/20_util/optional/monadic/pr109340.cc: New test. --- libstdc++-v3/include/std/expected | 36 ++++++++++++++++++++---------------- libstdc++-v3/include/std/optional | 8 ++++---- 2 files changed, 24 insertions(+), 20 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/std/expected b/libstdc++-v3/include/std/expected index 567a519..cb5754e 100644 --- a/libstdc++-v3/include/std/expected +++ b/libstdc++-v3/include/std/expected @@ -154,8 +154,12 @@ namespace __expected template using __result = remove_cvref_t>; + template + using __result_xform = remove_cv_t>; template using __result0 = remove_cvref_t>; + template + using __result0_xform = remove_cv_t>; template concept __can_be_unexpected @@ -953,7 +957,7 @@ namespace __expected constexpr auto transform(_Fn&& __f) & { - using _Up = __expected::__result<_Fn, _Tp&>; + using _Up = __expected::__result_xform<_Fn, _Tp&>; using _Res = expected<_Up, _Er>; if (has_value()) @@ -969,7 +973,7 @@ namespace __expected constexpr auto transform(_Fn&& __f) const & { - using _Up = __expected::__result<_Fn, const _Tp&>; + using _Up = __expected::__result_xform<_Fn, const _Tp&>; using _Res = expected<_Up, _Er>; if (has_value()) @@ -985,7 +989,7 @@ namespace __expected constexpr auto transform(_Fn&& __f) && { - using _Up = __expected::__result<_Fn, _Tp>; + using _Up = __expected::__result_xform<_Fn, _Tp>; using _Res = expected<_Up, _Er>; if (has_value()) @@ -1001,7 +1005,7 @@ namespace __expected constexpr auto transform(_Fn&& __f) const && { - using _Up = __expected::__result<_Fn, const _Tp>; + using _Up = __expected::__result_xform<_Fn, const _Tp>; using _Res = expected<_Up, _Er>; if (has_value()) @@ -1017,7 +1021,7 @@ namespace __expected constexpr auto transform_error(_Fn&& __f) & { - using _Gr = __expected::__result<_Fn, _Er&>; + using _Gr = __expected::__result_xform<_Fn, _Er&>; using _Res = expected<_Tp, _Gr>; if (has_value()) @@ -1033,7 +1037,7 @@ namespace __expected constexpr auto transform_error(_Fn&& __f) const & { - using _Gr = __expected::__result<_Fn, const _Er&>; + using _Gr = __expected::__result_xform<_Fn, const _Er&>; using _Res = expected<_Tp, _Gr>; if (has_value()) @@ -1049,7 +1053,7 @@ namespace __expected constexpr auto transform_error(_Fn&& __f) && { - using _Gr = __expected::__result<_Fn, _Er&&>; + using _Gr = __expected::__result_xform<_Fn, _Er&&>; using _Res = expected<_Tp, _Gr>; if (has_value()) @@ -1065,7 +1069,7 @@ namespace __expected constexpr auto transform_error(_Fn&& __f) const && { - using _Gr = __expected::__result<_Fn, const _Er&&>; + using _Gr = __expected::__result_xform<_Fn, const _Er&&>; using _Res = expected<_Tp, _Gr>; if (has_value()) @@ -1630,7 +1634,7 @@ namespace __expected constexpr auto transform(_Fn&& __f) & { - using _Up = __expected::__result0<_Fn>; + using _Up = __expected::__result0_xform<_Fn>; using _Res = expected<_Up, _Er>; if (has_value()) @@ -1643,7 +1647,7 @@ namespace __expected constexpr auto transform(_Fn&& __f) const & { - using _Up = __expected::__result0<_Fn>; + using _Up = __expected::__result0_xform<_Fn>; using _Res = expected<_Up, _Er>; if (has_value()) @@ -1656,7 +1660,7 @@ namespace __expected constexpr auto transform(_Fn&& __f) && { - using _Up = __expected::__result0<_Fn>; + using _Up = __expected::__result0_xform<_Fn>; using _Res = expected<_Up, _Er>; if (has_value()) @@ -1669,7 +1673,7 @@ namespace __expected constexpr auto transform(_Fn&& __f) const && { - using _Up = __expected::__result0<_Fn>; + using _Up = __expected::__result0_xform<_Fn>; using _Res = expected<_Up, _Er>; if (has_value()) @@ -1682,7 +1686,7 @@ namespace __expected constexpr auto transform_error(_Fn&& __f) & { - using _Gr = __expected::__result<_Fn, _Er&>; + using _Gr = __expected::__result_xform<_Fn, _Er&>; using _Res = expected<_Tp, _Gr>; if (has_value()) @@ -1698,7 +1702,7 @@ namespace __expected constexpr auto transform_error(_Fn&& __f) const & { - using _Gr = __expected::__result<_Fn, const _Er&>; + using _Gr = __expected::__result_xform<_Fn, const _Er&>; using _Res = expected<_Tp, _Gr>; if (has_value()) @@ -1714,7 +1718,7 @@ namespace __expected constexpr auto transform_error(_Fn&& __f) && { - using _Gr = __expected::__result<_Fn, _Er&&>; + using _Gr = __expected::__result_xform<_Fn, _Er&&>; using _Res = expected<_Tp, _Gr>; if (has_value()) @@ -1730,7 +1734,7 @@ namespace __expected constexpr auto transform_error(_Fn&& __f) const && { - using _Gr = __expected::__result<_Fn, const _Er&&>; + using _Gr = __expected::__result_xform<_Fn, const _Er&&>; using _Res = expected<_Tp, _Gr>; if (has_value()) diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional index 90bf741..bcac152 100644 --- a/libstdc++-v3/include/std/optional +++ b/libstdc++-v3/include/std/optional @@ -1100,7 +1100,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr auto transform(_Fn&& __f) & { - using _Up = invoke_result_t<_Fn, _Tp&>; + using _Up = remove_cv_t>; if (has_value()) return optional<_Up>(_Optional_func<_Fn>{__f}, **this); else @@ -1111,7 +1111,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr auto transform(_Fn&& __f) const & { - using _Up = invoke_result_t<_Fn, const _Tp&>; + using _Up = remove_cv_t>; if (has_value()) return optional<_Up>(_Optional_func<_Fn>{__f}, **this); else @@ -1122,7 +1122,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr auto transform(_Fn&& __f) && { - using _Up = invoke_result_t<_Fn, _Tp>; + using _Up = remove_cv_t>; if (has_value()) return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(**this)); else @@ -1133,7 +1133,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr auto transform(_Fn&& __f) const && { - using _Up = invoke_result_t<_Fn, const _Tp>; + using _Up = remove_cv_t>; if (has_value()) return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(**this)); else -- cgit v1.1 From ce39714a1ce58f2f32e8a44a224061290670db0f Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 29 Mar 2023 22:43:16 +0100 Subject: libstdc++: Apply small fix from LWG 3843 to std::expected LWG 3843 adds some type requirements to std::expected::value to ensure that it can correctly copy the error value if it needs to throw an exception. We don't need to do anything to enforce that, because it will already be ill-formed if the type can't be copied. The issue also makes a small drive-by fix to ensure that a const E& is copied from the non-const value()& overload, which this change implements. libstdc++-v3/ChangeLog: * include/std/expected (expected::value() &): Use const lvalue for unex member passed to bad_expected_access constructor, as per LWG 3843. --- libstdc++-v3/include/std/expected | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/std/expected b/libstdc++-v3/include/std/expected index cb5754e..0581882 100644 --- a/libstdc++-v3/include/std/expected +++ b/libstdc++-v3/include/std/expected @@ -736,7 +736,8 @@ namespace __expected { if (_M_has_value) [[likely]] return _M_val; - _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex)); + const auto& __unex = _M_unex; + _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(__unex)); } constexpr const _Tp&& -- cgit v1.1 From e0d77144aaa56ee6e00fd0ba520b0a5c7e052423 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 22 Mar 2023 17:00:11 +0000 Subject: libstdc++: Fix constexpr functions in Change ip::basic_endpoint to work in constant expressions, but only for C++20 and later (due to the use of a union, which cannot change active member in constexpr evaluation until C++20). During constant evaluation we cannot inspect the common initial sequence of basic_endpoint's union members to check whether sin_family == AF_INET or AF_INET6. This means we need to store an additional boolean member that remembers whether we have a v4 or v6 address. The address type can change behind our backs if a user copies an address to the data() pointer and then calls resize(n), so we need to inspect the sa_family_t member in the union after a resize and update the boolean. POSIX only guarantees that the sa_family_t member of each protocol-specific address structure is at the same offset and of the same type, not that there is a common initial sequence. The check in resize is done using memcmp, so that we avoid accessing an inactive member of the union if the sockaddr_in and sockaddr_in6 structures do not have a common initial sequence that includes the sa_family_t member. libstdc++-v3/ChangeLog: * include/experimental/internet (ip::make_address): Implement missing overload. (ip::address_v4::broadcast()): Avoid undefined shift. (ip::basic_endpoint): Fix member functions for constexpr. (ip::basic_endpoint::_M_is_v6): Replace member function with data member, adjust member functions using it. (ip::basic_endpoint::resize): Update _M_is_v6 based on sockaddr content. * testsuite/experimental/net/internet/address/v4/cons.cc: Fix constexpr checks to work in C++14. * testsuite/experimental/net/internet/address/v4/creation.cc: Likewise. * testsuite/experimental/net/internet/endpoint/cons.cc: Likewise. * testsuite/experimental/net/internet/network/v4/cons.cc: Likewise. * testsuite/experimental/net/internet/network/v4/members.cc: Likewise. * testsuite/experimental/net/internet/endpoint/extensible.cc: New test. --- libstdc++-v3/include/experimental/internet | 103 +++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 28 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/experimental/internet b/libstdc++-v3/include/experimental/internet index cae07f4..dff81b4 100644 --- a/libstdc++-v3/include/experimental/internet +++ b/libstdc++-v3/include/experimental/internet @@ -977,7 +977,8 @@ namespace ip { return make_address(__str, __throw_on_error{"make_address"}); } inline address - make_address(const string& __str, error_code& __ec) noexcept; // TODO + make_address(const string& __str, error_code& __ec) noexcept + { return make_address(__str.c_str(), __ec); } inline address make_address(const string& __str) @@ -1275,7 +1276,12 @@ namespace ip constexpr address_v4 broadcast() const noexcept - { return address_v4{_M_addr.to_uint() | (0xFFFFFFFFu >> _M_prefix_len)}; } + { + auto __b = _M_addr.to_uint(); + if (_M_prefix_len < 32) + __b |= 0xFFFFFFFFu >> _M_prefix_len; + return address_v4{__b}; + } address_v4_range hosts() const noexcept @@ -1510,19 +1516,31 @@ namespace ip basic_endpoint() noexcept : _M_data() { _M_data._M_v4.sin_family = protocol_type::v4().family(); } - constexpr + _GLIBCXX20_CONSTEXPR basic_endpoint(const protocol_type& __proto, port_type __port_num) noexcept : _M_data() { - __glibcxx_assert(__proto == protocol_type::v4() - || __proto == protocol_type::v6()); - - _M_data._M_v4.sin_family = __proto.family(); - _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num); + if (__proto == protocol_type::v4()) + { + _M_data._M_v4.sin_family = __proto.family(); + _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num); + } + else if (__proto == protocol_type::v6()) + { + std::_Construct(&_M_data._M_v6); + _M_data._M_v6.sin6_family = __proto.family(); + _M_data._M_v6.sin6_port = address_v4::_S_hton_16(__port_num); + _M_is_v6 = true; + } + else + { + __glibcxx_assert(__proto == protocol_type::v4() + || __proto == protocol_type::v6()); + } } - constexpr + _GLIBCXX20_CONSTEXPR basic_endpoint(const ip::address& __addr, port_type __port_num) noexcept : _M_data() @@ -1535,37 +1553,42 @@ namespace ip } else { - _M_data._M_v6 = {}; + std::_Construct(&_M_data._M_v6); _M_data._M_v6.sin6_family = protocol_type::v6().family(); _M_data._M_v6.sin6_port = address_v4::_S_hton_16(__port_num); - __builtin_memcpy(_M_data._M_v6.sin6_addr.s6_addr, - __addr._M_v6._M_bytes.data(), 16); + uint8_t* __s6a = _M_data._M_v6.sin6_addr.s6_addr; + for (int __i = 0; __i < 16; ++__i) + __s6a[__i] = __addr._M_v6._M_bytes[__i]; _M_data._M_v6.sin6_scope_id = __addr._M_v6._M_scope_id; + _M_is_v6 = true; } } // members: + constexpr protocol_type protocol() const noexcept { - return _M_is_v6() ? protocol_type::v6() : protocol_type::v4(); + return _M_is_v6 ? protocol_type::v6() : protocol_type::v4(); } constexpr ip::address address() const noexcept { - ip::address __addr; - if (_M_is_v6()) + if (_M_is_v6) { - __builtin_memcpy(&__addr._M_v6._M_bytes, - _M_data._M_v6.sin6_addr.s6_addr, 16); - __addr._M_is_v4 = false; + address_v6 __v6; + const uint8_t* __s6a = _M_data._M_v6.sin6_addr.s6_addr; + for (int __i = 0; __i < 16; ++__i) + __v6._M_bytes[__i] = __s6a[__i]; + __v6._M_scope_id = _M_data._M_v6.sin6_scope_id; + return __v6; } else { - __builtin_memcpy(&__addr._M_v4._M_addr, - &_M_data._M_v4.sin_addr.s_addr, 4); + address_v4 __v4; + __v4._M_addr = _M_data._M_v4.sin_addr.s_addr; + return __v4; } - return __addr; } void @@ -1573,37 +1596,62 @@ namespace ip { if (__addr.is_v6()) { - _M_data._M_v6 = {}; + std::_Construct(&_M_data._M_v6); _M_data._M_v6.sin6_family = protocol_type::v6().family(); __builtin_memcpy(_M_data._M_v6.sin6_addr.s6_addr, __addr._M_v6._M_bytes.data(), 16); _M_data._M_v6.sin6_scope_id = __addr._M_v6._M_scope_id; + _M_is_v6 = true; } else { + std::_Construct(&_M_data._M_v4); _M_data._M_v4.sin_family = protocol_type::v4().family(); _M_data._M_v4.sin_addr.s_addr = __addr._M_v4._M_addr; + _M_is_v6 = false; } } constexpr port_type port() const noexcept - { return address_v4::_S_ntoh_16(_M_data._M_v4.sin_port); } + { + port_type __p = 0; + if (_M_is_v6) + __p = _M_data._M_v6.sin6_port; + else + __p = _M_data._M_v4.sin_port; + return address_v4::_S_ntoh_16(__p); + } void port(port_type __port_num) noexcept - { _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num); } + { + __port_num = address_v4::_S_hton_16(__port_num); + if (_M_is_v6) + _M_data._M_v6.sin6_port = __port_num; + else + _M_data._M_v4.sin_port = __port_num; + } void* data() noexcept { return &_M_data; } const void* data() const noexcept { return &_M_data; } - constexpr size_t size() const noexcept - { return _M_is_v6() ? sizeof(sockaddr_in6) : sizeof(sockaddr_in); } + constexpr size_t + size() const noexcept + { return _M_is_v6 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in); } void resize(size_t __s) { + __glibcxx_assert(__s >= 0); + static_assert(offsetof(sockaddr_in6, sin6_family) + == offsetof(sockaddr_in, sin_family), + "sockaddr_in::sin_family and sockaddr_in6::sin6_family " + "must be at the same offset"); + const sa_family_t __in6 = AF_INET6; + const auto* __ptr = (char*)&_M_data + offsetof(sockaddr_in, sin_family); + _M_is_v6 = __builtin_memcmp(&__in6, __ptr, sizeof(__in6)) == 0; if (__s != size()) __throw_length_error("net::ip::basic_endpoint::resize"); } @@ -1617,8 +1665,7 @@ namespace ip sockaddr_in6 _M_v6; } _M_data; - constexpr bool _M_is_v6() const noexcept - { return _M_data._M_v4.sin_family == AF_INET6; } + bool _M_is_v6 = false; }; /** basic_endpoint comparisons -- cgit v1.1 From 10e573e86c6a1ed11df529288ed8fba97f876032 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 31 Mar 2023 13:17:00 +0100 Subject: libstdc++: Revert addition of boolean flag to net::ip::basic_endpoint As pointed out in P2641R1, we can use GCC's __builtin_constant_p to emulate the proposed std::is_active_member. This allows us to detect which of the union members is active during constant evaluation, so we don't need the extra bool data member. We still can't support constexpr until C++20 though, as we need to change the active member during constant evaluation. libstdc++-v3/ChangeLog: * include/experimental/internet (ip::basic_endpoint::_M_if_v6): Revert change from member function to data member. Fix for constant evaluation by detecting which union member is active. (ip::basic_endpoint::resize): Revert changes to update _M_is_v6 flag. --- libstdc++-v3/include/experimental/internet | 32 +++++++++++++----------------- 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/experimental/internet b/libstdc++-v3/include/experimental/internet index dff81b4..eb23ae2 100644 --- a/libstdc++-v3/include/experimental/internet +++ b/libstdc++-v3/include/experimental/internet @@ -1531,7 +1531,6 @@ namespace ip std::_Construct(&_M_data._M_v6); _M_data._M_v6.sin6_family = __proto.family(); _M_data._M_v6.sin6_port = address_v4::_S_hton_16(__port_num); - _M_is_v6 = true; } else { @@ -1560,7 +1559,6 @@ namespace ip for (int __i = 0; __i < 16; ++__i) __s6a[__i] = __addr._M_v6._M_bytes[__i]; _M_data._M_v6.sin6_scope_id = __addr._M_v6._M_scope_id; - _M_is_v6 = true; } } @@ -1568,13 +1566,13 @@ namespace ip constexpr protocol_type protocol() const noexcept { - return _M_is_v6 ? protocol_type::v6() : protocol_type::v4(); + return _M_is_v6() ? protocol_type::v6() : protocol_type::v4(); } constexpr ip::address address() const noexcept { - if (_M_is_v6) + if (_M_is_v6()) { address_v6 __v6; const uint8_t* __s6a = _M_data._M_v6.sin6_addr.s6_addr; @@ -1601,14 +1599,12 @@ namespace ip __builtin_memcpy(_M_data._M_v6.sin6_addr.s6_addr, __addr._M_v6._M_bytes.data(), 16); _M_data._M_v6.sin6_scope_id = __addr._M_v6._M_scope_id; - _M_is_v6 = true; } else { std::_Construct(&_M_data._M_v4); _M_data._M_v4.sin_family = protocol_type::v4().family(); _M_data._M_v4.sin_addr.s_addr = __addr._M_v4._M_addr; - _M_is_v6 = false; } } @@ -1616,7 +1612,7 @@ namespace ip port() const noexcept { port_type __p = 0; - if (_M_is_v6) + if (_M_is_v6()) __p = _M_data._M_v6.sin6_port; else __p = _M_data._M_v4.sin_port; @@ -1627,7 +1623,7 @@ namespace ip port(port_type __port_num) noexcept { __port_num = address_v4::_S_hton_16(__port_num); - if (_M_is_v6) + if (_M_is_v6()) _M_data._M_v6.sin6_port = __port_num; else _M_data._M_v4.sin_port = __port_num; @@ -1639,19 +1635,11 @@ namespace ip constexpr size_t size() const noexcept - { return _M_is_v6 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in); } + { return _M_is_v6() ? sizeof(sockaddr_in6) : sizeof(sockaddr_in); } void resize(size_t __s) { - __glibcxx_assert(__s >= 0); - static_assert(offsetof(sockaddr_in6, sin6_family) - == offsetof(sockaddr_in, sin_family), - "sockaddr_in::sin_family and sockaddr_in6::sin6_family " - "must be at the same offset"); - const sa_family_t __in6 = AF_INET6; - const auto* __ptr = (char*)&_M_data + offsetof(sockaddr_in, sin_family); - _M_is_v6 = __builtin_memcmp(&__in6, __ptr, sizeof(__in6)) == 0; if (__s != size()) __throw_length_error("net::ip::basic_endpoint::resize"); } @@ -1665,7 +1653,15 @@ namespace ip sockaddr_in6 _M_v6; } _M_data; - bool _M_is_v6 = false; + constexpr bool + _M_is_v6() const noexcept + { + // For constexpr eval we can just detect which union member is active. + // i.e. emulate P2641R1's std::is_active_member(&_M_data._M_v6)). + if (std::__is_constant_evaluated()) + return __builtin_constant_p(_M_data._M_v6.sin6_family); + return _M_data._M_v6.sin6_family == AF_INET6; + } }; /** basic_endpoint comparisons -- cgit v1.1 From a35e8042fbc7a3eb9cece1fba4cdd3b6cdfb906f Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 31 Mar 2023 13:38:14 +0100 Subject: libstdc++: Avoid -Wmaybe-uninitialized warning in std::stop_source [PR109339] We pass a const-reference to *this before it's constructed, and GCC assumes that all const-references are accessed. Add the access attribute to say it's not accessed. libstdc++-v3/ChangeLog: PR libstdc++/109339 * include/std/stop_token (_Stop_state_ptr(const stop_source&)): Add attribute access with access-mode 'none'. * testsuite/30_threads/stop_token/stop_source/109339.cc: New test. --- libstdc++-v3/include/std/stop_token | 1 + 1 file changed, 1 insertion(+) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/std/stop_token b/libstdc++-v3/include/std/stop_token index 76aef78..c90fc78 100644 --- a/libstdc++-v3/include/std/stop_token +++ b/libstdc++-v3/include/std/stop_token @@ -395,6 +395,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { _Stop_state_ref() = default; + [[__gnu__::__access__(__none__, 2)]] explicit _Stop_state_ref(const stop_source&) : _M_ptr(new _Stop_state_t()) -- cgit v1.1 From 4969dcd2b7a94ce6c0d07225b21b5f3c040a4902 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 31 Mar 2023 13:44:04 +0100 Subject: libstdc++: Teach optimizer that empty COW strings are empty [PR107087] The compiler doesn't know about the invariant that the _S_empty_rep() object is immutable and so _M_length and _M_refcount are always zero. This means that we get warnings about writing possibly-non-zero length strings into buffers that can't hold them. If we teach the compiler that the empty rep is always zero length, it knows it can be copied into any buffer. For Stage 1 we might want to also consider adding this to capacity(): if (_S_empty_rep()._M_capacity != 0) __builtin_unreachable(); And this to _Rep::_M_is_leaked() and _Rep::_M_is_shared(): if (_S_empty_rep()._M_refcount != 0) __builtin_unreachable(); libstdc++-v3/ChangeLog: PR tree-optimization/107087 * include/bits/cow_string.h (basic_string::size()): Add optimizer hint that _S_empty_rep()._M_length is always zero. (basic_string::length()): Call size(). --- libstdc++-v3/include/bits/cow_string.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/cow_string.h b/libstdc++-v3/include/bits/cow_string.h index 1ee84e6..b602436 100644 --- a/libstdc++-v3/include/bits/cow_string.h +++ b/libstdc++-v3/include/bits/cow_string.h @@ -907,17 +907,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION public: // Capacity: + /// Returns the number of characters in the string, not including any /// null-termination. size_type size() const _GLIBCXX_NOEXCEPT - { return _M_rep()->_M_length; } + { +#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0 && __OPTIMIZE__ + if (_S_empty_rep()._M_length != 0) + __builtin_unreachable(); +#endif + return _M_rep()->_M_length; + } /// Returns the number of characters in the string, not including any /// null-termination. size_type length() const _GLIBCXX_NOEXCEPT - { return _M_rep()->_M_length; } + { return size(); } /// Returns the size() of the largest possible %string. size_type -- cgit v1.1 From 44e17b8d8999a658af9f86681504d74a119a5f6f Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 4 Apr 2023 20:28:59 +0100 Subject: libstdc++: Define std::sub_match::swap member function (LWG 3204) This was approved at the C++ meeting in February. libstdc++-v3/ChangeLog: * include/bits/regex.h (sub_match::swap): New function. * testsuite/28_regex/sub_match/lwg3204.cc: New test. --- libstdc++-v3/include/bits/regex.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/regex.h b/libstdc++-v3/include/bits/regex.h index 79903fa..26ac6a2 100644 --- a/libstdc++-v3/include/bits/regex.h +++ b/libstdc++-v3/include/bits/regex.h @@ -1006,6 +1006,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { return this->_M_str().compare({__s, __n}); } /// @endcond + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3204. sub_match::swap only swaps the base class + /// Swap the values of two sub_match objects. + void + swap(sub_match& __s) noexcept(__is_nothrow_swappable<_BiIter>::value) + { + this->pair<_BiIter, _BiIter>::swap(__s); + std::swap(matched, __s.matched); + } + private: // Simplified basic_string_view for C++11 struct __string_view -- cgit v1.1 From 9d63ce7c4c0a993c419dceb823e71cba5da99e24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arsen=20Arsenovi=C4=87?= Date: Wed, 8 Mar 2023 12:04:11 +0100 Subject: libstdc++: Harmonize and other headers Due to recent, large changes in libstdc++, the feature test macros declared in got out of sync with the other headers that possibly declare them. libstdc++-v3/ChangeLog: * include/bits/unique_ptr.h (__cpp_lib_constexpr_memory): Synchronize the definition block with... * include/bits/ptr_traits.h (__cpp_lib_constexpr_memory): ... this one here. Also define the 202202L value, rather than leaving it up to purely unique_ptr.h, so that the value is synchronized across all headers. (__gnu_debug::_Safe_iterator_base): Move into new conditional block. * include/std/memory (__cpp_lib_atomic_value_initialization): Define on freestanding under the same conditions as in atomic_base.h. * include/std/version (__cpp_lib_robust_nonmodifying_seq_ops): Also define on freestanding. (__cpp_lib_to_chars): Ditto. (__cpp_lib_gcd): Ditto. (__cpp_lib_gcd_lcm): Ditto. (__cpp_lib_raw_memory_algorithms): Ditto. (__cpp_lib_array_constexpr): Ditto. (__cpp_lib_nonmember_container_access): Ditto. (__cpp_lib_clamp): Ditto. (__cpp_lib_constexpr_char_traits): Ditto. (__cpp_lib_constexpr_string): Ditto. (__cpp_lib_sample): Ditto. (__cpp_lib_lcm): Ditto. (__cpp_lib_constexpr_iterator): Ditto. (__cpp_lib_constexpr_char_traits): Ditto. (__cpp_lib_interpolate): Ditto. (__cpp_lib_constexpr_utility): Ditto. (__cpp_lib_shift): Ditto. (__cpp_lib_ranges): Ditto. (__cpp_lib_move_iterator_concept): Ditto. (__cpp_lib_constexpr_numeric): Ditto. (__cpp_lib_constexpr_functional): Ditto. (__cpp_lib_constexpr_algorithms): Ditto. (__cpp_lib_constexpr_tuple): Ditto. (__cpp_lib_constexpr_memory): Ditto. --- libstdc++-v3/include/bits/ptr_traits.h | 11 +++-- libstdc++-v3/include/bits/unique_ptr.h | 11 ++--- libstdc++-v3/include/std/memory | 6 +++ libstdc++-v3/include/std/version | 85 +++++++++++++++++++--------------- 4 files changed, 65 insertions(+), 48 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/ptr_traits.h b/libstdc++-v3/include/bits/ptr_traits.h index dc42a74..8a919ec 100644 --- a/libstdc++-v3/include/bits/ptr_traits.h +++ b/libstdc++-v3/include/bits/ptr_traits.h @@ -34,12 +34,15 @@ #include +/* Duplicate definition with unique_ptr.h. */ +#if __cplusplus > 202002L && defined(__cpp_constexpr_dynamic_alloc) +# define __cpp_lib_constexpr_memory 202202L +#elif __cplusplus > 201703L +# define __cpp_lib_constexpr_memory 201811L +#endif + #if __cplusplus > 201703L #include -# ifndef __cpp_lib_constexpr_memory -// Defined to a newer value in bits/unique_ptr.h for C++23 -# define __cpp_lib_constexpr_memory 201811L -# endif namespace __gnu_debug { struct _Safe_iterator_base; } #endif diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h index c8daff4..f0c6d23 100644 --- a/libstdc++-v3/include/bits/unique_ptr.h +++ b/libstdc++-v3/include/bits/unique_ptr.h @@ -43,12 +43,11 @@ # endif #endif -#if __cplusplus > 202002L && __cpp_constexpr_dynamic_alloc -# if __cpp_lib_constexpr_memory < 202202L -// Defined with older value in bits/ptr_traits.h for C++20 -# undef __cpp_lib_constexpr_memory -# define __cpp_lib_constexpr_memory 202202L -# endif +/* Duplicate definition with ptr_traits.h. */ +#if __cplusplus > 202002L && defined(__cpp_constexpr_dynamic_alloc) +# define __cpp_lib_constexpr_memory 202202L +#elif __cplusplus > 201703L +# define __cpp_lib_constexpr_memory 201811L #endif namespace std _GLIBCXX_VISIBILITY(default) diff --git a/libstdc++-v3/include/std/memory b/libstdc++-v3/include/std/memory index 341f985..85c36d6 100644 --- a/libstdc++-v3/include/std/memory +++ b/libstdc++-v3/include/std/memory @@ -91,6 +91,12 @@ # include #endif +/* As a hack, we declare __cpp_lib_atomic_value_initialization here even though + we don't include the bit that actually declares it, for consistency. */ +#if !defined(__cpp_lib_atomic_value_initialization) && __cplusplus >= 202002L +# define __cpp_lib_atomic_value_initialization 201911L +#endif + #if __cplusplus >= 201103L && __cplusplus <= 202002L && _GLIBCXX_HOSTED namespace std _GLIBCXX_VISIBILITY(default) { diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index a19c39c..cdd2424 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -81,18 +81,23 @@ #ifndef _GLIBCXX_DEBUG // PR libstdc++/70303 # define __cpp_lib_null_iterators 201304L #endif +#define __cpp_lib_robust_nonmodifying_seq_ops 201304L #define __cpp_lib_transformation_trait_aliases 201304L #define __cpp_lib_transparent_operators 201510L #define __cpp_lib_tuple_element_t 201402L #define __cpp_lib_tuples_by_type 201304L +#if _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 \ + && __SIZE_WIDTH__ >= 32 +# define __cpp_lib_to_chars 201611L +#endif + #if _GLIBCXX_HOSTED # define __cpp_lib_chrono_udls 201304L # define __cpp_lib_complex_udls 201309L # define __cpp_lib_generic_associative_lookup 201304L # define __cpp_lib_make_unique 201304L # define __cpp_lib_quoted_string_io 201304L -# define __cpp_lib_robust_nonmodifying_seq_ops 201304L # ifdef _GLIBCXX_HAS_GTHREADS # define __cpp_lib_shared_timed_mutex 201402L # endif @@ -108,6 +113,9 @@ #define __cpp_lib_atomic_is_always_lock_free 201603L #define __cpp_lib_bool_constant 201505L #define __cpp_lib_byte 201603L +#define __cpp_lib_clamp 201603L +#define __cpp_lib_gcd 201606L +#define __cpp_lib_gcd_lcm 201606L #ifdef _GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP # define __cpp_lib_has_unique_object_representations 201606L #endif @@ -123,12 +131,16 @@ #ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER # define __cpp_lib_launder 201606L #endif +#define __cpp_lib_lcm 201606L #define __cpp_lib_logical_traits 201510L #define __cpp_lib_make_from_tuple 201606L +#define __cpp_lib_nonmember_container_access 201411L #define __cpp_lib_not_fn 201603L #if __cplusplus == 201703L // N.B. updated value in C++20 # define __cpp_lib_optional 201606L #endif +#define __cpp_lib_raw_memory_algorithms 201606L +#define __cpp_lib_sample 201603L #define __cpp_lib_type_trait_variable_templates 201510L #define __cpp_lib_uncaught_exceptions 201411L #if !(__cpp_concepts >= 202002L && __cpp_constexpr >= 201811L) @@ -136,27 +148,23 @@ # define __cpp_lib_variant 202102L #endif #define __cpp_lib_void_t 201411L - -#if _GLIBCXX_HOSTED #if __cplusplus == 201703L // N.B. updated value in C++20 # define __cpp_lib_array_constexpr 201803L #endif -#define __cpp_lib_boyer_moore_searcher 201603L -#define __cpp_lib_chrono 201611L -#define __cpp_lib_clamp 201603L #if __cplusplus == 201703L // N.B. updated value in C++20 # if _GLIBCXX_HAVE_IS_CONSTANT_EVALUATED # define __cpp_lib_constexpr_char_traits 201611L # define __cpp_lib_constexpr_string 201611L # endif #endif + +#if _GLIBCXX_HOSTED +#define __cpp_lib_boyer_moore_searcher 201603L +#define __cpp_lib_chrono 201611L #define __cpp_lib_enable_shared_from_this 201603L #define __cpp_lib_execution 201902L // FIXME: should be 201603L #define __cpp_lib_filesystem 201703L -#define __cpp_lib_gcd 201606L -#define __cpp_lib_gcd_lcm 201606L #define __cpp_lib_hypot 201603L -#define __cpp_lib_lcm 201606L #define __cpp_lib_map_try_emplace 201411L #define __cpp_lib_math_special_functions 201603L #ifdef _GLIBCXX_HAS_GTHREADS @@ -165,20 +173,13 @@ # define __cpp_lib_memory_resource 1 #endif #define __cpp_lib_node_extract 201606L -#define __cpp_lib_nonmember_container_access 201411L #define __cpp_lib_parallel_algorithm 201603L -#define __cpp_lib_raw_memory_algorithms 201606L -#define __cpp_lib_sample 201603L #ifdef _GLIBCXX_HAS_GTHREADS # define __cpp_lib_scoped_lock 201703L # define __cpp_lib_shared_mutex 201505L #endif #define __cpp_lib_shared_ptr_weak_type 201606L #define __cpp_lib_string_view 201803L -#if _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 \ - && __SIZE_WIDTH__ >= 32 -# define __cpp_lib_to_chars 201611L -#endif #define __cpp_lib_unordered_map_try_emplace 201411L #endif @@ -224,7 +225,9 @@ #if __cpp_lib_concepts # define __cpp_lib_make_obj_using_allocator 201811L #endif -#define __cpp_lib_optional 202106L +#if __cplusplus <= 202002L // N.B. updated value in C++23 +# define __cpp_lib_optional 202106L +#endif #define __cpp_lib_remove_cvref 201711L #if __has_builtin(__builtin_source_location) # define __cpp_lib_source_location 201907L @@ -243,9 +246,27 @@ #if __cpp_concepts >= 202002L && __cpp_constexpr >= 201811L # define __cpp_lib_variant 202106L #endif +#define __cpp_lib_constexpr_algorithms 201806L +#define __cpp_lib_constexpr_functional 201907L +#if __cplusplus <= 202002L // N.B. updated value in C++23 +# define __cpp_lib_constexpr_memory 201811L +#endif // C++20 +#define __cpp_lib_constexpr_numeric 201911L +#define __cpp_lib_constexpr_tuple 201811L +#define __cpp_lib_array_constexpr 201811L +#ifdef __cpp_lib_is_constant_evaluated +# define __cpp_lib_constexpr_char_traits 201811L +#endif +#define __cpp_lib_constexpr_iterator 201811L +#define __cpp_lib_constexpr_utility 201811L +#define __cpp_lib_interpolate 201902L +#if __cpp_lib_concepts +# define __cpp_lib_move_iterator_concept 202207L +# define __cpp_lib_ranges 202110L +#endif +#define __cpp_lib_shift 201806L #if _GLIBCXX_HOSTED -#define __cpp_lib_array_constexpr 201811L #define __cpp_lib_atomic_shared_ptr 201711L #if defined _GLIBCXX_HAS_GTHREADS || defined _GLIBCXX_HAVE_LINUX_FUTEX # define __cpp_lib_atomic_wait 201907L @@ -256,16 +277,9 @@ // #undef __cpp_lib_chrono // #define __cpp_lib_chrono 201907L // FIXME: #define __cpp_lib_execution 201902L -#define __cpp_lib_constexpr_algorithms 201806L -#ifdef __cpp_lib_is_constant_evaluated -# define __cpp_lib_constexpr_char_traits 201811L -#endif #define __cpp_lib_constexpr_complex 201711L #define __cpp_lib_constexpr_dynamic_alloc 201907L -#define __cpp_lib_constexpr_functional 201907L -#define __cpp_lib_constexpr_iterator 201811L -#define __cpp_lib_constexpr_memory 201811L -#define __cpp_lib_constexpr_numeric 201911L +#define __cpp_lib_constexpr_tuple 201811L #ifdef __cpp_lib_is_constant_evaluated # if _GLIBCXX_USE_CXX11_ABI # define __cpp_lib_constexpr_string 201907L @@ -273,13 +287,10 @@ # define __cpp_lib_constexpr_string 201811L # endif #endif -#define __cpp_lib_constexpr_tuple 201811L -#define __cpp_lib_constexpr_utility 201811L #define __cpp_lib_constexpr_vector 201907L #define __cpp_lib_erase_if 202002L #define __cpp_lib_format 202106L #define __cpp_lib_generic_unordered_lookup 201811L -#define __cpp_lib_interpolate 201902L #ifdef _GLIBCXX_HAS_GTHREADS # define __cpp_lib_jthread 201911L #endif @@ -288,15 +299,10 @@ #endif #define __cpp_lib_list_remove_return_type 201806L #define __cpp_lib_polymorphic_allocator 201902L -#if __cpp_lib_concepts -# define __cpp_lib_ranges 202110L -# define __cpp_lib_move_iterator_concept 202207L -#endif #if __cpp_lib_atomic_wait || _GLIBCXX_HAVE_POSIX_SEMAPHORE # define __cpp_lib_semaphore 201907L #endif #define __cpp_lib_shared_ptr_arrays 201707L -#define __cpp_lib_shift 201806L #define __cpp_lib_smart_ptr_for_overwrite 202002L # if _GLIBCXX_USE_CXX11_ABI // Only supported with cxx11-abi @@ -330,14 +336,17 @@ #define __cpp_lib_ranges_stride 202207L #define __cpp_lib_ranges_cartesian_product 202207L #define __cpp_lib_ranges_as_rvalue 202207L - -#if _GLIBCXX_HOSTED -#define __cpp_lib_adaptor_iterator_pair_constructor 202106L #if __cpp_constexpr_dynamic_alloc -# define __cpp_lib_constexpr_bitset 202202L +# if _GLIBCXX_HOSTED +# define __cpp_lib_constexpr_bitset 202202L +# endif # undef __cpp_lib_constexpr_memory # define __cpp_lib_constexpr_memory 202202L #endif +#define __cpp_lib_stdatomic_h 202011L + +#if _GLIBCXX_HOSTED +#define __cpp_lib_adaptor_iterator_pair_constructor 202106L #define __cpp_lib_ios_noreplace 202207L #define __cpp_lib_move_only_function 202110L #if __cpp_lib_span -- cgit v1.1 From 6f0d67b912900009bff5018bd58e17ea1db1de69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arsen=20Arsenovi=C4=87?= Date: Wed, 8 Mar 2023 17:01:24 +0100 Subject: libstdc++: Add a test for FTM redefinitions This test detects redefinitions by compiling stdc++.h and , by disabling the system_header pragma on the latter, to allow warnings in it. Thanks Patrick Palka for the suggestion. libstdc++-v3/ChangeLog: * testsuite/17_intro/versionconflict.cc: New test. * include/std/version: Allow disabling the system_header pragma via _GLIBCXX_TESTING_SYSHDR. --- libstdc++-v3/include/std/version | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index cdd2424..1069bc6 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -30,7 +30,10 @@ #ifndef _GLIBCXX_VERSION_INCLUDED #define _GLIBCXX_VERSION_INCLUDED -#pragma GCC system_header +// To facilitate testsuite/17_intro/versionconflict.cc +#ifndef _GLIBCXX_TESTING_SYSHDR +# pragma GCC system_header +#endif #include -- cgit v1.1 From bff26ac162772313d3d9b8ce952b5a0846e26878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arsen=20Arsenovi=C4=87?= Date: Tue, 4 Apr 2023 19:25:09 +0200 Subject: libstdc++: Downgrade DEBUG to ASSERTIONS when !HOSTED Supporting the debug mode in freestanding is a non-trivial job, so instead, as a best-effort, enable assertions, which are light and easy. libstdc++-v3/ChangeLog: * include/bits/c++config: When __STDC_HOSTED__ is zero, disable _GLIBCXX_DEBUG and, if it was set, enable _GLIBCXX_ASSERTIONS. * testsuite/lib/libstdc++.exp (check_v3_target_debug_mode): Include when determining whether debug is set, in order to inherit the logic from above --- libstdc++-v3/include/bits/c++config | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index 71f2401..1389278 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -397,6 +397,13 @@ _GLIBCXX_END_NAMESPACE_VERSION # define _GLIBCXX_END_INLINE_ABI_NAMESPACE(X) } // inline namespace X #endif +// In the case that we don't have a hosted environment, we can't provide the +// debugging mode. Instead, we do our best and downgrade to assertions. +#if defined(_GLIBCXX_DEBUG) && !__STDC_HOSTED__ +#undef _GLIBCXX_DEBUG +#define _GLIBCXX_ASSERTIONS 1 +#endif + // Inline namespaces for special modes: debug, parallel. #if defined(_GLIBCXX_DEBUG) || defined(_GLIBCXX_PARALLEL) namespace std -- cgit v1.1 From 3bfd0420e4a17a82454ed3bdadc0f5d362d9b636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arsen=20Arsenovi=C4=87?= Date: Tue, 4 Apr 2023 23:24:52 +0200 Subject: libstdc++: Fix some freestanding test failures At some point, was added to the non-hosted bit of the C++17 block, which induced failures in many tests. In addition, some tests also lacked a dg-require-effective-target hosted tag. libstdc++-v3/ChangeLog: * include/precompiled/stdc++.h (C++17): Don't double-include , once with wrong conditions. * testsuite/18_support/96817.cc: Require hosted. * testsuite/18_support/bad_exception/59392.cc: Ditto. * testsuite/20_util/scoped_allocator/108952.cc: Ditto. * testsuite/20_util/uses_allocator/lwg3527.cc: Ditto. * testsuite/29_atomics/atomic/operators/pointer_partial_void.cc: Ditto. --- libstdc++-v3/include/precompiled/stdc++.h | 1 - 1 file changed, 1 deletion(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/precompiled/stdc++.h b/libstdc++-v3/include/precompiled/stdc++.h index bc01198..176ad79 100644 --- a/libstdc++-v3/include/precompiled/stdc++.h +++ b/libstdc++-v3/include/precompiled/stdc++.h @@ -75,7 +75,6 @@ #if __cplusplus >= 201703L #include -#include // #include #include #include -- cgit v1.1 From 9f10b4957ca6058d1a801c5e4bfe11bf159da809 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 12 Apr 2023 11:55:24 +0100 Subject: libstdc++: Initialize all members of basic_endpoint union [PR109482] On Solaris the in_addr struct contains a union and value-initializing it does not make the s_addr member active. This means we can't access that member later during constant evaluation. Make the constructors explicitly set every member that we might want to read later in constexpr member functions. This means even the default constructor can only be constexpr for C++20, because we can't change the active member of a union in older standards. libstdc++-v3/ChangeLog: PR libstdc++/109482 * include/experimental/internet (basic_endpoint::basic_endpoint()): Ensure that the required union members are active. Only define as constexpr for C++20 and later. (basic_endpoint::basic_endpoint(const protocol_type&, port_type)): Likewise. * testsuite/experimental/net/internet/endpoint/cons.cc: Only check constexpr default constructor for C++20 and later. * testsuite/experimental/net/internet/endpoint/extensible.cc: Likewise. --- libstdc++-v3/include/experimental/internet | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/experimental/internet b/libstdc++-v3/include/experimental/internet index eb23ae2..1f63c61 100644 --- a/libstdc++-v3/include/experimental/internet +++ b/libstdc++-v3/include/experimental/internet @@ -1512,9 +1512,14 @@ namespace ip // constructors: - constexpr + _GLIBCXX20_CONSTEXPR basic_endpoint() noexcept : _M_data() - { _M_data._M_v4.sin_family = protocol_type::v4().family(); } + { + _M_data._M_v4.sin_family = protocol_type::v4().family(); + // If in_addr contains a union, make the correct member active: + if (std::__is_constant_evaluated()) + std::_Construct(&_M_data._M_v4.sin_addr.s_addr); + } _GLIBCXX20_CONSTEXPR basic_endpoint(const protocol_type& __proto, @@ -1523,19 +1528,25 @@ namespace ip { if (__proto == protocol_type::v4()) { - _M_data._M_v4.sin_family = __proto.family(); + _M_data._M_v4.sin_family = protocol_type::v4().family(); _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num); + if (std::__is_constant_evaluated()) + std::_Construct(&_M_data._M_v4.sin_addr.s_addr); } else if (__proto == protocol_type::v6()) { std::_Construct(&_M_data._M_v6); _M_data._M_v6.sin6_family = __proto.family(); _M_data._M_v6.sin6_port = address_v4::_S_hton_16(__port_num); + _M_data._M_v6.sin6_scope_id = 0; + if (std::__is_constant_evaluated()) + std::_Construct(&_M_data._M_v6.sin6_addr.s6_addr); } else { __glibcxx_assert(__proto == protocol_type::v4() || __proto == protocol_type::v6()); + } } @@ -1548,13 +1559,16 @@ namespace ip { _M_data._M_v4.sin_family = protocol_type::v4().family(); _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num); - _M_data._M_v4.sin_addr.s_addr = __addr._M_v4._M_addr; + std::_Construct(&_M_data._M_v4.sin_addr.s_addr, + __addr._M_v4._M_addr); } else { std::_Construct(&_M_data._M_v6); _M_data._M_v6.sin6_family = protocol_type::v6().family(); _M_data._M_v6.sin6_port = address_v4::_S_hton_16(__port_num); + if (std::__is_constant_evaluated()) + std::_Construct(&_M_data._M_v6.sin6_addr.s6_addr); uint8_t* __s6a = _M_data._M_v6.sin6_addr.s6_addr; for (int __i = 0; __i < 16; ++__i) __s6a[__i] = __addr._M_v6._M_bytes[__i]; -- cgit v1.1 From ae8f903632c930694640a925b042c87e3bdb7200 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Wed, 12 Apr 2023 12:10:23 -0400 Subject: libstdc++: Fix chunk_by_view when value_type& and reference differ [PR108291] PR libstdc++/108291 libstdc++-v3/ChangeLog: * include/std/ranges (chunk_by_view::_M_find_next): Generalize parameter types of the lambda wrapper passed to adjacent_find. (chunk_by_view::_M_find_prev): Likewise. * testsuite/std/ranges/adaptors/chunk_by/1.cc (test04, test05): New tests. --- libstdc++-v3/include/std/ranges | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index b230ebe..ba71976d 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -6742,8 +6742,8 @@ namespace views::__adaptor _M_find_next(iterator_t<_Vp> __current) { __glibcxx_assert(_M_pred.has_value()); - auto __pred = [this](_Tp&& __x, _Tp&& __y) { - return !bool((*_M_pred)(std::forward<_Tp>(__x), std::forward<_Tp>(__y))); + auto __pred = [this](_Tp&& __x, _Up&& __y) { + return !bool((*_M_pred)(std::forward<_Tp>(__x), std::forward<_Up>(__y))); }; auto __it = ranges::adjacent_find(__current, ranges::end(_M_base), __pred); return ranges::next(__it, 1, ranges::end(_M_base)); @@ -6753,8 +6753,8 @@ namespace views::__adaptor _M_find_prev(iterator_t<_Vp> __current) requires bidirectional_range<_Vp> { __glibcxx_assert(_M_pred.has_value()); - auto __pred = [this](_Tp&& __x, _Tp&& __y) { - return !bool((*_M_pred)(std::forward<_Tp>(__y), std::forward<_Tp>(__x))); + auto __pred = [this](_Tp&& __x, _Up&& __y) { + return !bool((*_M_pred)(std::forward<_Up>(__y), std::forward<_Tp>(__x))); }; auto __rbegin = std::make_reverse_iterator(__current); auto __rend = std::make_reverse_iterator(ranges::begin(_M_base)); -- cgit v1.1 From aa65771427d32299cffecea64cbb766411aa8faf Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Wed, 12 Apr 2023 13:04:36 -0400 Subject: libstdc++: Implement LWG 3904 change to lazy_split_view's iterator libstdc++-v3/ChangeLog: * include/std/ranges (lazy_split_view::_OuterIter::_OuterIter): Propagate _M_trailing_empty in the const-converting constructor as per LWG 3904. * testsuite/std/ranges/adaptors/adjacent/1.cc (test04): Correct assertion. * testsuite/std/ranges/adaptors/lazy_split.cc (test12): New test. --- libstdc++-v3/include/std/ranges | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index ba71976d..c215281 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -3209,7 +3209,8 @@ namespace views::__adaptor _OuterIter(_OuterIter __i) requires _Const && convertible_to, iterator_t<_Base>> - : _M_parent(__i._M_parent), _M_current(std::move(__i._M_current)) + : _M_parent(__i._M_parent), _M_current(std::move(__i._M_current)), + _M_trailing_empty(__i._M_trailing_empty) { } constexpr value_type -- cgit v1.1 From 0f3b4d38d4bad8994150fe7a1e5428055d29a4bf Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Wed, 12 Apr 2023 13:24:37 -0400 Subject: libstdc++: Implement ranges::enumerate_view from P2164R9 libstdc++-v3/ChangeLog: * include/std/ranges (__cpp_lib_ranges_enumerate): Define for C++23. (__detail::__range_with_movable_reference): Likewise. (enumerate_view): Likewise. (enumerate_view::_Iterator): Likewise. (enumerate_view::_Sentinel): Likewise. (views::__detail::__can_enumerate_view): Likewise. (views::_Enumerate, views::enumerate): Likewise. * include/std/version (__cpp_lib_ranges_enumerate): Likewise. * testsuite/std/ranges/version_c++23.cc: Verify value of __cpp_lib_ranges_enumerate. * testsuite/std/ranges/adaptors/enumerate/1.cc: New test. --- libstdc++-v3/include/std/ranges | 303 +++++++++++++++++++++++++++++++++++++++ libstdc++-v3/include/std/version | 1 + 2 files changed, 304 insertions(+) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index c215281..3f6ff50 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -8626,6 +8626,309 @@ namespace views::__adaptor inline constexpr _AsRvalue as_rvalue; } + +#define __cpp_lib_ranges_enumerate 202302L + + namespace __detail + { + template + concept __range_with_movable_reference = input_range<_Range> + && move_constructible> + && move_constructible>; + } + + template + requires __detail::__range_with_movable_reference<_Vp> + class enumerate_view : public view_interface> + { + _Vp _M_base = _Vp(); + + template class _Iterator; + template class _Sentinel; + + public: + enumerate_view() requires default_initializable<_Vp> = default; + + constexpr explicit + enumerate_view(_Vp __base) + : _M_base(std::move(__base)) + { } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { return _Iterator(ranges::begin(_M_base), 0); } + + constexpr auto + begin() const requires __detail::__range_with_movable_reference + { return _Iterator(ranges::begin(_M_base), 0); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { + if constexpr (common_range<_Vp> && sized_range<_Vp>) + return _Iterator(ranges::end(_M_base), ranges::distance(_M_base)); + else + return _Sentinel(ranges::end(_M_base)); + } + + constexpr auto + end() const requires __detail::__range_with_movable_reference + { + if constexpr (common_range && sized_range) + return _Iterator(ranges::end(_M_base), ranges::distance(_M_base)); + else + return _Sentinel(ranges::end(_M_base)); + } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_base); } + + constexpr _Vp + base() const & requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + }; + + template + enumerate_view(_Range&&) -> enumerate_view>; + + template + inline constexpr bool enable_borrowed_range> + = enable_borrowed_range<_Tp>; + + template + requires __detail::__range_with_movable_reference<_Vp> + template + class enumerate_view<_Vp>::_Iterator + { + using _Base = __maybe_const_t<_Const, _Vp>; + + static auto + _S_iter_concept() + { + if constexpr (random_access_range<_Base>) + return random_access_iterator_tag{}; + else if constexpr (bidirectional_range<_Base>) + return bidirectional_iterator_tag{}; + else if constexpr (forward_range<_Base>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + friend enumerate_view; + + public: + using iterator_category = input_iterator_tag; + using iterator_concept = decltype(_S_iter_concept()); + using difference_type = range_difference_t<_Base>; + using value_type = tuple>; + + private: + using __reference_type = tuple>; + + iterator_t<_Base> _M_current = iterator_t<_Base>(); + difference_type _M_pos = 0; + + constexpr explicit + _Iterator(iterator_t<_Base> __current, difference_type __pos) + : _M_current(std::move(__current)), _M_pos(__pos) + { } + + public: + _Iterator() requires default_initializable> = default; + + constexpr + _Iterator(_Iterator __i) + requires _Const && convertible_to, iterator_t<_Base>> + : _M_current(std::move(__i._M_current)), _M_pos(__i._M_pos) + { } + + constexpr const iterator_t<_Base> & + base() const & noexcept + { return _M_current; } + + constexpr iterator_t<_Base> + base() && + { return std::move(_M_current); } + + constexpr difference_type + index() const noexcept + { return _M_pos; } + + constexpr auto + operator*() const + { return __reference_type(_M_pos, *_M_current); } + + constexpr _Iterator& + operator++() + { + ++_M_current; + ++_M_pos; + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) requires forward_range<_Base> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + --_M_current; + --_M_pos; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __n) requires random_access_range<_Base> + { + _M_current += __n; + _M_pos += __n; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __n) requires random_access_range<_Base> + { + _M_current -= __n; + _M_pos -= __n; + return *this; + } + + constexpr auto + operator[](difference_type __n) const requires random_access_range<_Base> + { return __reference_type(_M_pos + __n, _M_current[__n]); } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) noexcept + { return __x._M_pos == __y._M_pos; } + + friend constexpr strong_ordering + operator<=>(const _Iterator& __x, const _Iterator& __y) noexcept + { return __x._M_pos <=> __y._M_pos; } + + friend constexpr _Iterator + operator+(const _Iterator& __x, difference_type __y) + requires random_access_range<_Base> + { return (auto(__x) += __y); } + + friend constexpr _Iterator + operator+(difference_type __x, const _Iterator& __y) + requires random_access_range<_Base> + { return auto(__y) += __x; } + + friend constexpr _Iterator + operator-(const _Iterator& __x, difference_type __y) + requires random_access_range<_Base> + { return auto(__x) -= __y; } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + { return __x._M_pos - __y._M_pos; } + + friend constexpr auto + iter_move(const _Iterator& __i) + noexcept(noexcept(ranges::iter_move(__i._M_current)) + && is_nothrow_move_constructible_v>) + { + return tuple> + (__i._M_pos, ranges::iter_move(__i._M_current)); + } + }; + + template + requires __detail::__range_with_movable_reference<_Vp> + template + class enumerate_view<_Vp>::_Sentinel + { + using _Base = __maybe_const_t<_Const, _Vp>; + + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + constexpr explicit + _Sentinel(sentinel_t<_Base> __end) + : _M_end(std::move(__end)) + { } + + friend enumerate_view; + + public: + _Sentinel() = default; + + constexpr + _Sentinel(_Sentinel __other) + requires _Const && convertible_to, sentinel_t<_Base>> + : _M_end(std::move(__other._M_end)) + { } + + constexpr sentinel_t<_Base> + base() const + { return _M_end; } + + template + requires sentinel_for, iterator_t<__maybe_const_t<_OtherConst, _Vp>>> + friend constexpr bool + operator==(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_current == __y._M_end; } + + template + requires sized_sentinel_for, iterator_t<__maybe_const_t<_OtherConst, _Vp>>> + friend constexpr range_difference_t<__maybe_const_t<_OtherConst, _Vp>> + operator-(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_current - __y._M_end; } + + template + requires sized_sentinel_for, iterator_t<__maybe_const_t<_OtherConst, _Vp>>> + friend constexpr range_difference_t<__maybe_const_t<_OtherConst, _Vp>> + operator-(const _Sentinel& __x, const _Iterator<_OtherConst>& __y) + { return __x._M_end - __y._M_current; } + }; + + namespace views + { + namespace __detail + { + template + concept __can_enumerate_view + = requires { enumerate_view>(std::declval<_Tp>()); }; + } + + struct _Enumerate : __adaptor::_RangeAdaptorClosure + { + template + requires __detail::__can_enumerate_view<_Range> + constexpr auto + operator() [[nodiscard]] (_Range&& __r) const + { return enumerate_view>(std::forward<_Range>(__r)); } + }; + + inline constexpr _Enumerate enumerate; + } #endif // C++23 } // namespace ranges diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index 1069bc6..b35435c 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -339,6 +339,7 @@ #define __cpp_lib_ranges_stride 202207L #define __cpp_lib_ranges_cartesian_product 202207L #define __cpp_lib_ranges_as_rvalue 202207L +#define __cpp_lib_ranges_enumerate 202302L #if __cpp_constexpr_dynamic_alloc # if _GLIBCXX_HOSTED # define __cpp_lib_constexpr_bitset 202202L -- cgit v1.1 From 6a9547f3ca6c48f116478169d5fc62165dde7f43 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 13 Apr 2023 16:34:51 +0100 Subject: libstdc++: Improve diagnostics for invalid std::format calls Add a static_assert and a comment so that calling std::format for unformattable argument types will now show: /home/jwakely/gcc/13/include/c++/13.0.1/format:3563:22: error: static assertion failed: std::formatter must be specialized for each format arg 3563 | static_assert((is_default_constructible_v> && ...), | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ and: 140 | formatter() = delete; // No std::formatter specialization for this type. libstdc++-v3/ChangeLog: * include/std/format (formatter): Add comment to deleted default constructor of primary template. (_Checking_scanner): Add static_assert. --- libstdc++-v3/include/std/format | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index 72b6b45..e4ef4f9 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -137,7 +137,7 @@ namespace __format template struct formatter { - formatter() = delete; + formatter() = delete; // No std::formatter specialization for this type. formatter(const formatter&) = delete; formatter& operator=(const formatter&) = delete; }; @@ -3560,6 +3560,10 @@ namespace __format template class _Checking_scanner : public _Scanner<_CharT> { + static_assert( + (is_default_constructible_v> && ...), + "std::formatter must be specialized for each type being formatted"); + public: constexpr _Checking_scanner(basic_string_view<_CharT> __str) @@ -3581,17 +3585,17 @@ namespace __format __builtin_unreachable(); } - template + template constexpr void _M_parse_format_spec(size_t __id) { if (__id == 0) { - formatter<_Head, _CharT> __f; + formatter<_Tp, _CharT> __f; this->_M_pc.advance_to(__f.parse(this->_M_pc)); } - else if constexpr (sizeof...(_Tail) != 0) - _M_parse_format_spec<_Tail...>(__id - 1); + else if constexpr (sizeof...(_OtherArgs) != 0) + _M_parse_format_spec<_OtherArgs...>(__id - 1); else __builtin_unreachable(); } -- cgit v1.1 From 7639bf34fa1942b0a56a0ba441637c1ce75e1127 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Fri, 14 Apr 2023 10:31:44 -0400 Subject: libstdc++: Implement ranges::fold_* from P2322R6 libstdc++-v3/ChangeLog: * include/bits/ranges_algo.h: Include for C++23. (__cpp_lib_fold): Define for C++23. (in_value_result): Likewise. (__detail::__flipped): Likewise. (__detail::__indirectly_binary_left_foldable_impl): Likewise. (__detail::__indirectly_binary_left_foldable): Likewise. (___detail:__indirectly_binary_right_foldable): Likewise. (fold_left_with_iter_result): Likewise. (__fold_left_with_iter_fn, fold_left_with_iter): Likewise. (__fold_left_fn, fold_left): Likewise. (__fold_left_first_with_iter_fn, fold_left_first_with_iter): Likewise. (__fold_left_first_fn, fold_left_first): Likewise. (__fold_right_fn, fold_right): Likewise. (__fold_right_last_fn, fold_right_last): Likewise. * include/std/version (__cpp_lib_fold): Likewise. * testsuite/25_algorithms/fold_left/1.cc: New test. * testsuite/25_algorithms/fold_right/1.cc: New test. --- libstdc++-v3/include/bits/ranges_algo.h | 251 ++++++++++++++++++++++++++++++++ libstdc++-v3/include/std/version | 1 + 2 files changed, 252 insertions(+) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h index 5d039bd..f041ff1 100644 --- a/libstdc++-v3/include/bits/ranges_algo.h +++ b/libstdc++-v3/include/bits/ranges_algo.h @@ -32,6 +32,9 @@ #if __cplusplus > 201703L +#if __cplusplus > 202002L +#include +#endif #include #include #include // concept uniform_random_bit_generator @@ -3691,6 +3694,254 @@ namespace ranges }; inline constexpr __find_last_if_not_fn find_last_if_not{}; + +#define __cpp_lib_fold 202207L + + template + struct in_value_result + { + [[no_unique_address]] _Iter in; + [[no_unique_address]] _Tp value; + + template + requires convertible_to + && convertible_to + constexpr + operator in_value_result<_Iter2, _Tp2>() const & + { return {in, value}; } + + template + requires convertible_to<_Iter, _Iter2> + && convertible_to<_Tp, _Tp2> + constexpr + operator in_value_result<_Iter2, _Tp2>() && + { return {std::move(in), std::move(value)}; } + }; + + namespace __detail + { + template + class __flipped + { + _Fp _M_f; + + public: + template + requires invocable<_Fp&, _Up, _Tp> + invoke_result_t<_Fp&, _Up, _Tp> + operator()(_Tp&&, _Up&&); // not defined + }; + + template + concept __indirectly_binary_left_foldable_impl = movable<_Tp> && movable<_Up> + && convertible_to<_Tp, _Up> + && invocable<_Fp&, _Up, iter_reference_t<_Iter>> + && assignable_from<_Up&, invoke_result_t<_Fp&, _Up, iter_reference_t<_Iter>>>; + + template + concept __indirectly_binary_left_foldable = copy_constructible<_Fp> + && indirectly_readable<_Iter> + && invocable<_Fp&, _Tp, iter_reference_t<_Iter>> + && convertible_to>, + decay_t>>> + && __indirectly_binary_left_foldable_impl + <_Fp, _Tp, _Iter, decay_t>>>; + + template + concept __indirectly_binary_right_foldable + = __indirectly_binary_left_foldable<__flipped<_Fp>, _Tp, _Iter>; + } // namespace __detail + + template + using fold_left_with_iter_result = in_value_result<_Iter, _Tp>; + + struct __fold_left_with_iter_fn + { + template + static constexpr auto + _S_impl(_Iter __first, _Sent __last, _Tp __init, _Fp __f) + { + using _Up = decay_t>>; + using _Ret = fold_left_with_iter_result<_Ret_iter, _Up>; + + if (__first == __last) + return _Ret{std::move(__first), _Up(std::move(__init))}; + + _Up __accum = std::__invoke(__f, std::move(__init), *__first); + for (++__first; __first != __last; ++__first) + __accum = std::__invoke(__f, std::move(__accum), *__first); + return _Ret{std::move(__first), std::move(__accum)}; + } + + template _Sent, typename _Tp, + __detail::__indirectly_binary_left_foldable<_Tp, _Iter> _Fp> + constexpr auto + operator()(_Iter __first, _Sent __last, _Tp __init, _Fp __f) const + { + using _Ret_iter = _Iter; + return _S_impl<_Ret_iter>(std::move(__first), __last, + std::move(__init), std::move(__f)); + } + + template> _Fp> + constexpr auto + operator()(_Range&& __r, _Tp __init, _Fp __f) const + { + using _Ret_iter = borrowed_iterator_t<_Range>; + return _S_impl<_Ret_iter>(ranges::begin(__r), ranges::end(__r), + std::move(__init), std::move(__f)); + } + }; + + inline constexpr __fold_left_with_iter_fn fold_left_with_iter{}; + + struct __fold_left_fn + { + template _Sent, typename _Tp, + __detail::__indirectly_binary_left_foldable<_Tp, _Iter> _Fp> + constexpr auto + operator()(_Iter __first, _Sent __last, _Tp __init, _Fp __f) const + { + return ranges::fold_left_with_iter(std::move(__first), __last, + std::move(__init), std::move(__f)).value; + } + + template> _Fp> + constexpr auto + operator()(_Range&& __r, _Tp __init, _Fp __f) const + { return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__init), std::move(__f)); } + }; + + inline constexpr __fold_left_fn fold_left{}; + + template + using fold_left_first_with_iter_result = in_value_result<_Iter, _Tp>; + + struct __fold_left_first_with_iter_fn + { + template + static constexpr auto + _S_impl(_Iter __first, _Sent __last, _Fp __f) + { + using _Up = decltype(ranges::fold_left(std::move(__first), __last, + iter_value_t<_Iter>(*__first), __f)); + using _Ret = fold_left_first_with_iter_result<_Ret_iter, optional<_Up>>; + + if (__first == __last) + return _Ret{std::move(__first), optional<_Up>()}; + + optional<_Up> __init(in_place, *__first); + for (++__first; __first != __last; ++__first) + *__init = std::__invoke(__f, std::move(*__init), *__first); + return _Ret{std::move(__first), std::move(__init)}; + } + + template _Sent, + __detail::__indirectly_binary_left_foldable, _Iter> _Fp> + requires constructible_from, iter_reference_t<_Iter>> + constexpr auto + operator()(_Iter __first, _Sent __last, _Fp __f) const + { + using _Ret_iter = _Iter; + return _S_impl<_Ret_iter>(std::move(__first), __last, std::move(__f)); + } + + template, iterator_t<_Range>> _Fp> + requires constructible_from, range_reference_t<_Range>> + constexpr auto + operator()(_Range&& __r, _Fp __f) const + { + using _Ret_iter = borrowed_iterator_t<_Range>; + return _S_impl<_Ret_iter>(ranges::begin(__r), ranges::end(__r), std::move(__f)); + } + }; + + inline constexpr __fold_left_first_with_iter_fn fold_left_first_with_iter{}; + + struct __fold_left_first_fn + { + template _Sent, + __detail::__indirectly_binary_left_foldable, _Iter> _Fp> + requires constructible_from, iter_reference_t<_Iter>> + constexpr auto + operator()(_Iter __first, _Sent __last, _Fp __f) const + { + return ranges::fold_left_first_with_iter(std::move(__first), __last, + std::move(__f)).value; + } + + template, iterator_t<_Range>> _Fp> + requires constructible_from, range_reference_t<_Range>> + constexpr auto + operator()(_Range&& __r, _Fp __f) const + { return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__f)); } + }; + + inline constexpr __fold_left_first_fn fold_left_first{}; + + struct __fold_right_fn + { + template _Sent, typename _Tp, + __detail::__indirectly_binary_right_foldable<_Tp, _Iter> _Fp> + constexpr auto + operator()(_Iter __first, _Sent __last, _Tp __init, _Fp __f) const + { + using _Up = decay_t, _Tp>>; + + if (__first == __last) + return _Up(std::move(__init)); + + _Iter __tail = ranges::next(__first, __last); + _Up __accum = std::__invoke(__f, *--__tail, std::move(__init)); + while (__first != __tail) + __accum = std::__invoke(__f, *--__tail, std::move(__accum)); + return __accum; + } + + template> _Fp> + constexpr auto + operator()(_Range&& __r, _Tp __init, _Fp __f) const + { return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__init), std::move(__f)); } + }; + + inline constexpr __fold_right_fn fold_right{}; + + struct __fold_right_last_fn + { + template _Sent, + __detail::__indirectly_binary_right_foldable, _Iter> _Fp> + requires constructible_from, iter_reference_t<_Iter>> + constexpr auto + operator()(_Iter __first, _Sent __last, _Fp __f) const + { + using _Up = decltype(ranges::fold_right(__first, __last, + iter_value_t<_Iter>(*__first), __f)); + + if (__first == __last) + return optional<_Up>(); + + _Iter __tail = ranges::prev(ranges::next(__first, std::move(__last))); + return optional<_Up>(in_place, + ranges::fold_right(std::move(__first), __tail, + iter_value_t<_Iter>(*__tail), + std::move(__f))); + } + + template, iterator_t<_Range>> _Fp> + requires constructible_from, range_reference_t<_Range>> + constexpr auto + operator()(_Range&& __r, _Fp __f) const + { return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__f)); } + }; + + inline constexpr __fold_right_last_fn fold_right_last{}; #endif // C++23 } // namespace ranges diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index b35435c..d233b03 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -340,6 +340,7 @@ #define __cpp_lib_ranges_cartesian_product 202207L #define __cpp_lib_ranges_as_rvalue 202207L #define __cpp_lib_ranges_enumerate 202302L +#define __cpp_lib_fold 202207L #if __cpp_constexpr_dynamic_alloc # if _GLIBCXX_HOSTED # define __cpp_lib_constexpr_bitset 202202L -- cgit v1.1 From 2ab0d83e8880fe747af3f137aef382d2d4c09e4c Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Fri, 14 Apr 2023 10:31:54 -0400 Subject: libstdc++: Move down definitions of ranges::cbegin/cend/cetc This moves down the definitions of the range const-access CPOs to after the definition of input_range in preparation for implementing P2278R4 which redefines these CPOs in a way that indirectly uses input_range. libstdc++-v3/ChangeLog: * include/bits/ranges_base.h (__cust_access::__as_const) (__cust_access::_CBegin, __cust::cbegin) (__cust_access::_CEnd, __cust::cend) (__cust_access::_CRBegin, __cust::crbegin) (__cust_access::_CREnd, __cust::crend) (__cust_access::_CData, __cust::cdata): Move down definitions to shortly after the definition of input_range. --- libstdc++-v3/include/bits/ranges_base.h | 174 +++++++++++++++++--------------- 1 file changed, 91 insertions(+), 83 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index 86952b3..c89cb3e 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -177,45 +177,6 @@ namespace ranges } }; - // If _To is an lvalue-reference, return const _Tp&, otherwise const _Tp&&. - template - constexpr decltype(auto) - __as_const(_Tp& __t) noexcept - { - static_assert(std::is_same_v<_To&, _Tp&>); - - if constexpr (is_lvalue_reference_v<_To>) - return const_cast(__t); - else - return static_cast(__t); - } - - struct _CBegin - { - template - [[nodiscard]] - constexpr auto - operator()(_Tp&& __e) const - noexcept(noexcept(_Begin{}(__cust_access::__as_const<_Tp>(__e)))) - requires requires { _Begin{}(__cust_access::__as_const<_Tp>(__e)); } - { - return _Begin{}(__cust_access::__as_const<_Tp>(__e)); - } - }; - - struct _CEnd final - { - template - [[nodiscard]] - constexpr auto - operator()(_Tp&& __e) const - noexcept(noexcept(_End{}(__cust_access::__as_const<_Tp>(__e)))) - requires requires { _End{}(__cust_access::__as_const<_Tp>(__e)); } - { - return _End{}(__cust_access::__as_const<_Tp>(__e)); - } - }; - template concept __member_rbegin = requires(_Tp& __t) { @@ -337,32 +298,6 @@ namespace ranges } }; - struct _CRBegin - { - template - [[nodiscard]] - constexpr auto - operator()(_Tp&& __e) const - noexcept(noexcept(_RBegin{}(__cust_access::__as_const<_Tp>(__e)))) - requires requires { _RBegin{}(__cust_access::__as_const<_Tp>(__e)); } - { - return _RBegin{}(__cust_access::__as_const<_Tp>(__e)); - } - }; - - struct _CREnd - { - template - [[nodiscard]] - constexpr auto - operator()(_Tp&& __e) const - noexcept(noexcept(_REnd{}(__cust_access::__as_const<_Tp>(__e)))) - requires requires { _REnd{}(__cust_access::__as_const<_Tp>(__e)); } - { - return _REnd{}(__cust_access::__as_const<_Tp>(__e)); - } - }; - template concept __member_size = !disable_sized_range> && requires(_Tp& __t) @@ -547,36 +482,18 @@ namespace ranges } }; - struct _CData - { - template - [[nodiscard]] - constexpr auto - operator()(_Tp&& __e) const - noexcept(noexcept(_Data{}(__cust_access::__as_const<_Tp>(__e)))) - requires requires { _Data{}(__cust_access::__as_const<_Tp>(__e)); } - { - return _Data{}(__cust_access::__as_const<_Tp>(__e)); - } - }; - } // namespace __cust_access inline namespace __cust { inline constexpr __cust_access::_Begin begin{}; inline constexpr __cust_access::_End end{}; - inline constexpr __cust_access::_CBegin cbegin{}; - inline constexpr __cust_access::_CEnd cend{}; inline constexpr __cust_access::_RBegin rbegin{}; inline constexpr __cust_access::_REnd rend{}; - inline constexpr __cust_access::_CRBegin crbegin{}; - inline constexpr __cust_access::_CREnd crend{}; inline constexpr __cust_access::_Size size{}; inline constexpr __cust_access::_SSize ssize{}; inline constexpr __cust_access::_Empty empty{}; inline constexpr __cust_access::_Data data{}; - inline constexpr __cust_access::_CData cdata{}; } /// [range.range] The range concept. @@ -690,6 +607,97 @@ namespace ranges concept common_range = range<_Tp> && same_as, sentinel_t<_Tp>>; + namespace __cust_access + { + // If _To is an lvalue-reference, return const _Tp&, otherwise const _Tp&&. + template + constexpr decltype(auto) + __as_const(_Tp& __t) noexcept + { + static_assert(std::is_same_v<_To&, _Tp&>); + + if constexpr (is_lvalue_reference_v<_To>) + return const_cast(__t); + else + return static_cast(__t); + } + + struct _CBegin + { + template + [[nodiscard]] + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_Begin{}(__cust_access::__as_const<_Tp>(__e)))) + requires requires { _Begin{}(__cust_access::__as_const<_Tp>(__e)); } + { + return _Begin{}(__cust_access::__as_const<_Tp>(__e)); + } + }; + + struct _CEnd final + { + template + [[nodiscard]] + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_End{}(__cust_access::__as_const<_Tp>(__e)))) + requires requires { _End{}(__cust_access::__as_const<_Tp>(__e)); } + { + return _End{}(__cust_access::__as_const<_Tp>(__e)); + } + }; + + struct _CRBegin + { + template + [[nodiscard]] + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_RBegin{}(__cust_access::__as_const<_Tp>(__e)))) + requires requires { _RBegin{}(__cust_access::__as_const<_Tp>(__e)); } + { + return _RBegin{}(__cust_access::__as_const<_Tp>(__e)); + } + }; + + struct _CREnd + { + template + [[nodiscard]] + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_REnd{}(__cust_access::__as_const<_Tp>(__e)))) + requires requires { _REnd{}(__cust_access::__as_const<_Tp>(__e)); } + { + return _REnd{}(__cust_access::__as_const<_Tp>(__e)); + } + }; + + struct _CData + { + template + [[nodiscard]] + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_Data{}(__cust_access::__as_const<_Tp>(__e)))) + requires requires { _Data{}(__cust_access::__as_const<_Tp>(__e)); } + { + return _Data{}(__cust_access::__as_const<_Tp>(__e)); + } + }; + + } // namespace __cust_access + + inline namespace __cust + { + inline constexpr __cust_access::_CBegin cbegin{}; + inline constexpr __cust_access::_CEnd cend{}; + inline constexpr __cust_access::_CRBegin crbegin{}; + inline constexpr __cust_access::_CREnd crend{}; + inline constexpr __cust_access::_CData cdata{}; + } + namespace __detail { template -- cgit v1.1 From 0d94c6df183375caaa7f672e288a2094ca813749 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Fri, 14 Apr 2023 10:32:12 -0400 Subject: libstdc++: Implement P2278R4 "cbegin should always return a constant iterator" This also implements the approved follow-up LWG issues 3765, 3766, 3769, 3770, 3811, 3850, 3853, 3862 and 3872. libstdc++-v3/ChangeLog: * include/bits/ranges_base.h (const_iterator_t): Define for C++23. (const_sentinel_t): Likewise. (range_const_reference_t): Likewise. (constant_range): Likewise. (__cust_access::__possibly_const_range): Likewise, replacing ... (__cust_access::__as_const): ... this. (__cust_access::_CBegin::operator()): Redefine for C++23 as per P2278R4. (__cust_access::_CEnd::operator()): Likewise. (__cust_access::_CRBegin::operator()): Likewise. (__cust_access::_CREnd::operator()): Likewise. (__cust_access::_CData::operator()): Likewise. * include/bits/ranges_util.h (ranges::__detail::__different_from): Make it an alias of std::__detail::__different_from. (view_interface::cbegin): Define for C++23. (view_interface::cend): Likewise. * include/bits/stl_iterator.h (__detail::__different_from): Define. (iter_const_reference_t): Define for C++23. (__detail::__constant_iterator): Likewise. (__detail::__is_const_iterator): Likewise. (__detail::__not_a_const_iterator): Likewise. (__detail::__iter_const_rvalue_reference_t): Likewise. (__detail::__basic_const_iter_cat):: Likewise. (const_iterator): Likewise. (__detail::__const_sentinel): Likewise. (const_sentinel): Likewise. (basic_const_iterator): Likewise. (common_type, _Up>): Likewise. (common_type<_Up, basic_const_iterator<_Tp>>): Likewise. (common_type, basic_const_iterator>): Likewise. (make_const_iterator): Define for C++23. (make_const_sentinel): Likewise. * include/std/ranges (__cpp_lib_ranges_as_const): Likewise. (as_const_view): Likewise. (enable_borrowed_range): Likewise. (views::__detail::__is_ref_view): Likewise. (views::__detail::__can_is_const_view): Likewise. (views::_AsConst, views::as_const): Likewise. * include/std/span (span::const_iterator): Likewise. (span::const_reverse_iterator): Likewise. (span::cbegin): Likewise. (span::cend): Likewise. (span::crbegin): Likewise. (span::crend): Likewise. * include/std/version (__cpp_lib_ranges_as_const): Likewise. * testsuite/std/ranges/adaptors/join.cc (test06): Adjust to behave independently of C++20 vs C++23. * testsuite/std/ranges/version_c++23.cc: Verify value of __cpp_lib_ranges_as_const macro. * testsuite/24_iterators/const_iterator/1.cc: New test. * testsuite/std/ranges/adaptors/as_const/1.cc: New test. --- libstdc++-v3/include/bits/ranges_base.h | 99 +++++++++ libstdc++-v3/include/bits/ranges_util.h | 22 +- libstdc++-v3/include/bits/stl_iterator.h | 367 +++++++++++++++++++++++++++++++ libstdc++-v3/include/std/ranges | 106 +++++++++ libstdc++-v3/include/std/span | 22 ++ libstdc++-v3/include/std/version | 1 + 6 files changed, 614 insertions(+), 3 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index c89cb3e..698dac7 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -515,6 +515,17 @@ namespace ranges template using sentinel_t = decltype(ranges::end(std::declval<_Range&>())); +#if __cplusplus > 202002L + template + using const_iterator_t = const_iterator>; + + template + using const_sentinel_t = const_sentinel>; + + template + using range_const_reference_t = iter_const_reference_t>; +#endif + template using range_difference_t = iter_difference_t>; @@ -607,8 +618,25 @@ namespace ranges concept common_range = range<_Tp> && same_as, sentinel_t<_Tp>>; +#if __cplusplus > 202002L + template + concept constant_range + = input_range<_Tp> && std::__detail::__constant_iterator>; +#endif + namespace __cust_access { +#if __cplusplus > 202020L + template + constexpr auto& + __possibly_const_range(_Range& __r) noexcept + { + if constexpr (constant_range && !constant_range<_Range>) + return const_cast(__r); + else + return __r; + } +#else // If _To is an lvalue-reference, return const _Tp&, otherwise const _Tp&&. template constexpr decltype(auto) @@ -621,9 +649,24 @@ namespace ranges else return static_cast(__t); } +#endif struct _CBegin { +#if __cplusplus > 202002L + template<__maybe_borrowed_range _Tp> + [[nodiscard]] + constexpr auto + operator()(_Tp&& __t) const + noexcept(noexcept(std::make_const_iterator + (ranges::begin(__cust_access::__possibly_const_range(__t))))) + requires requires { std::make_const_iterator + (ranges::begin(__cust_access::__possibly_const_range(__t))); } + { + auto& __r = __cust_access::__possibly_const_range(__t); + return const_iterator_t(ranges::begin(__r)); + } +#else template [[nodiscard]] constexpr auto @@ -633,10 +676,25 @@ namespace ranges { return _Begin{}(__cust_access::__as_const<_Tp>(__e)); } +#endif }; struct _CEnd final { +#if __cplusplus > 202002L + template<__maybe_borrowed_range _Tp> + [[nodiscard]] + constexpr auto + operator()(_Tp&& __t) const + noexcept(noexcept(std::make_const_sentinel + (ranges::end(__cust_access::__possibly_const_range(__t))))) + requires requires { std::make_const_sentinel + (ranges::end(__cust_access::__possibly_const_range(__t))); } + { + auto& __r = __cust_access::__possibly_const_range(__t); + return const_sentinel_t(ranges::end(__r)); + } +#else template [[nodiscard]] constexpr auto @@ -646,10 +704,25 @@ namespace ranges { return _End{}(__cust_access::__as_const<_Tp>(__e)); } +#endif }; struct _CRBegin { +#if __cplusplus > 202002L + template<__maybe_borrowed_range _Tp> + [[nodiscard]] + constexpr auto + operator()(_Tp&& __t) const + noexcept(noexcept(std::make_const_iterator + (ranges::rbegin(__cust_access::__possibly_const_range(__t))))) + requires requires { std::make_const_iterator + (ranges::rbegin(__cust_access::__possibly_const_range(__t))); } + { + auto& __r = __cust_access::__possibly_const_range(__t); + return const_iterator(ranges::rbegin(__r)); + } +#else template [[nodiscard]] constexpr auto @@ -659,10 +732,25 @@ namespace ranges { return _RBegin{}(__cust_access::__as_const<_Tp>(__e)); } +#endif }; struct _CREnd { +#if __cplusplus > 202002L + template<__maybe_borrowed_range _Tp> + [[nodiscard]] + constexpr auto + operator()(_Tp&& __t) const + noexcept(noexcept(std::make_const_sentinel + (ranges::rend(__cust_access::__possibly_const_range(__t))))) + requires requires { std::make_const_sentinel + (ranges::rend(__cust_access::__possibly_const_range(__t))); } + { + auto& __r = __cust_access::__possibly_const_range(__t); + return const_sentinel(ranges::rend(__r)); + } +#else template [[nodiscard]] constexpr auto @@ -672,10 +760,20 @@ namespace ranges { return _REnd{}(__cust_access::__as_const<_Tp>(__e)); } +#endif }; struct _CData { +#if __cplusplus > 202002L + template<__maybe_borrowed_range _Tp> + [[nodiscard]] + constexpr const auto* + operator()(_Tp&& __t) const + noexcept(noexcept(ranges::data(__cust_access::__possibly_const_range(__t)))) + requires requires { ranges::data(__cust_access::__possibly_const_range(__t)); } + { return ranges::data(__cust_access::__possibly_const_range(__t)); } +#else template [[nodiscard]] constexpr auto @@ -685,6 +783,7 @@ namespace ranges { return _Data{}(__cust_access::__as_const<_Tp>(__e)); } +#endif }; } // namespace __cust_access diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h index 880a0ce..f7e3538 100644 --- a/libstdc++-v3/include/bits/ranges_util.h +++ b/libstdc++-v3/include/bits/ranges_util.h @@ -53,9 +53,7 @@ namespace ranges concept __has_arrow = input_iterator<_It> && (is_pointer_v<_It> || requires(_It __it) { __it.operator->(); }); - template - concept __different_from - = !same_as, remove_cvref_t<_Up>>; + using std::__detail::__different_from; } // namespace __detail /// The ranges::view_interface class template @@ -192,6 +190,24 @@ namespace ranges constexpr decltype(auto) operator[](range_difference_t<_Range> __n) const { return ranges::begin(_M_derived())[__n]; } + +#if __cplusplus > 202002L + constexpr auto + cbegin() requires input_range<_Derived> + { return ranges::cbegin(_M_derived()); } + + constexpr auto + cbegin() const requires input_range + { return ranges::cbegin(_M_derived()); } + + constexpr auto + cend() requires input_range<_Derived> + { return ranges::cend(_M_derived()); } + + constexpr auto + cend() const requires input_range + { return ranges::cend(_M_derived()); } +#endif }; namespace __detail diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index a6a09db..b22d9a4 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -102,6 +102,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template using __clamp_iter_cat = __conditional_t, _Limit, _Otherwise>; + + template + concept __different_from + = !same_as, remove_cvref_t<_Up>>; } #endif @@ -2578,6 +2582,369 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION add_pointer_t>, void>; }; + +#if __cplusplus > 202020L + template + using iter_const_reference_t + = common_reference_t&&, iter_reference_t<_It>>; + + template class basic_const_iterator; + + namespace __detail + { + template + concept __constant_iterator = input_iterator<_It> + && same_as, iter_reference_t<_It>>; + + template + inline constexpr bool __is_const_iterator = false; + + template + inline constexpr bool __is_const_iterator> = true; + + template + concept __not_a_const_iterator = !__is_const_iterator<_Tp>; + + template + using __iter_const_rvalue_reference_t + = common_reference_t&&, iter_rvalue_reference_t<_It>>; + + template + struct __basic_const_iterator_iter_cat + { }; + + template + struct __basic_const_iterator_iter_cat<_It> + { using iterator_category = iterator_traits<_It>::iterator_category; }; + } // namespace detail + + template + using const_iterator + = __conditional_t<__detail::__constant_iterator<_It>, _It, basic_const_iterator<_It>>; + + namespace __detail + { + template + struct __const_sentinel + { using type = _Sent; }; + + template + struct __const_sentinel<_Sent> + { using type = const_iterator<_Sent>; }; + } // namespace __detail + + template + using const_sentinel = typename __detail::__const_sentinel<_Sent>::type; + + template + class basic_const_iterator + : public __detail::__basic_const_iterator_iter_cat<_It> + { + _It _M_current = _It(); + using __reference = iter_const_reference_t<_It>; + using __rvalue_reference = __detail::__iter_const_rvalue_reference_t<_It>; + + static auto + _S_iter_concept() + { + if constexpr (contiguous_iterator<_It>) + return contiguous_iterator_tag{}; + else if constexpr (random_access_iterator<_It>) + return random_access_iterator_tag{}; + else if constexpr (bidirectional_iterator<_It>) + return bidirectional_iterator_tag{}; + else if constexpr (forward_iterator<_It>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + template friend class basic_const_iterator; + + public: + using iterator_concept = decltype(_S_iter_concept()); + using value_type = iter_value_t<_It>; + using difference_type = iter_difference_t<_It>; + + basic_const_iterator() requires default_initializable<_It> = default; + + constexpr + basic_const_iterator(_It __current) + noexcept(is_nothrow_move_constructible_v<_It>) + : _M_current(std::move(__current)) + { } + + template _It2> + constexpr + basic_const_iterator(basic_const_iterator<_It2> __current) + noexcept(is_nothrow_constructible_v<_It, _It2>) + : _M_current(std::move(__current._M_current)) + { } + + template<__detail::__different_from _Tp> + requires convertible_to<_Tp, _It> + constexpr + basic_const_iterator(_Tp&& __current) + noexcept(is_nothrow_constructible_v<_It, _Tp>) + : _M_current(std::forward<_Tp>(__current)) + { } + + constexpr const _It& + base() const & noexcept + { return _M_current; } + + constexpr _It + base() && + noexcept(is_nothrow_move_constructible_v<_It>) + { return std::move(_M_current); } + + constexpr __reference + operator*() const + noexcept(noexcept(static_cast<__reference>(*_M_current))) + { return static_cast<__reference>(*_M_current); } + + constexpr const auto* + operator->() const + noexcept(contiguous_iterator<_It> || noexcept(*_M_current)) + requires is_lvalue_reference_v> + && same_as>, value_type> + { + if constexpr (contiguous_iterator<_It>) + return std::to_address(_M_current); + else + return std::__addressof(*_M_current); + } + + constexpr basic_const_iterator& + operator++() + noexcept(noexcept(++_M_current)) + { + ++_M_current; + return *this; + } + + constexpr void + operator++(int) + noexcept(noexcept(++_M_current)) + { ++_M_current; } + + constexpr basic_const_iterator + operator++(int) + noexcept(noexcept(++*this) && is_nothrow_copy_constructible_v) + requires forward_iterator<_It> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr basic_const_iterator& + operator--() + noexcept(noexcept(--_M_current)) + requires bidirectional_iterator<_It> + { + --_M_current; + return *this; + } + + constexpr basic_const_iterator + operator--(int) + noexcept(noexcept(--*this) && is_nothrow_copy_constructible_v) + requires bidirectional_iterator<_It> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr basic_const_iterator& + operator+=(difference_type __n) + noexcept(noexcept(_M_current += __n)) + requires random_access_iterator<_It> + { + _M_current += __n; + return *this; + } + + constexpr basic_const_iterator& + operator-=(difference_type __n) + noexcept(noexcept(_M_current -= __n)) + requires random_access_iterator<_It> + { + _M_current -= __n; + return *this; + } + + constexpr __reference + operator[](difference_type __n) const + noexcept(noexcept(static_cast<__reference>(_M_current[__n]))) + requires random_access_iterator<_It> + { return static_cast<__reference>(_M_current[__n]); } + + template _Sent> + constexpr bool + operator==(const _Sent& __s) const + noexcept(noexcept(_M_current == __s)) + { return _M_current == __s; } + + constexpr bool + operator<(const basic_const_iterator& __y) const + noexcept(noexcept(_M_current < __y._M_current)) + requires random_access_iterator<_It> + { return _M_current < __y._M_current; } + + constexpr bool + operator>(const basic_const_iterator& __y) const + noexcept(noexcept(_M_current > __y._M_current)) + requires random_access_iterator<_It> + { return _M_current > __y._M_current; } + + constexpr bool + operator<=(const basic_const_iterator& __y) const + noexcept(noexcept(_M_current <= __y._M_current)) + requires random_access_iterator<_It> + { return _M_current <= __y._M_current; } + + constexpr bool + operator>=(const basic_const_iterator& __y) const + noexcept(noexcept(_M_current >= __y._M_current)) + requires random_access_iterator<_It> + { return _M_current >= __y._M_current; } + + constexpr auto + operator<=>(const basic_const_iterator& __y) const + noexcept(noexcept(_M_current <=> __y._M_current)) + requires random_access_iterator<_It> && three_way_comparable<_It> + { return _M_current <=> __y._M_current; } + + template<__detail::__different_from _It2> + constexpr bool + operator<(const _It2& __y) const + noexcept(noexcept(_M_current < __y)) + requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> + { return _M_current < __y; } + + template<__detail::__different_from _It2> + constexpr bool + operator>(const _It2& __y) const + noexcept(noexcept(_M_current > __y)) + requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> + { return _M_current > __y; } + + template<__detail::__different_from _It2> + constexpr bool + operator<=(const _It2& __y) const + noexcept(noexcept(_M_current <= __y)) + requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> + { return _M_current <= __y; } + + template<__detail::__different_from _It2> + constexpr bool + operator>=(const _It2& __y) const + noexcept(noexcept(_M_current >= __y)) + requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> + { return _M_current >= __y; } + + template<__detail::__different_from _It2> + constexpr auto + operator<=>(const _It2& __y) const + noexcept(noexcept(_M_current <=> __y)) + requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> + && three_way_comparable_with<_It, _It2> + { return _M_current <=> __y; } + + template<__detail::__not_a_const_iterator _It2> + friend constexpr bool + operator<(const _It2& __x, const basic_const_iterator& __y) + noexcept(noexcept(__x < __y._M_current)) + requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> + { return __x < __y._M_current; } + + template<__detail::__not_a_const_iterator _It2> + friend constexpr bool + operator>(const _It2& __x, const basic_const_iterator& __y) + noexcept(noexcept(__x > __y._M_current)) + requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> + { return __x > __y._M_current; } + + template<__detail::__not_a_const_iterator _It2> + friend constexpr bool + operator<=(const _It2& __x, const basic_const_iterator& __y) + noexcept(noexcept(__x <= __y._M_current)) + requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> + { return __x <= __y._M_current; } + + template<__detail::__not_a_const_iterator _It2> + friend constexpr bool + operator>=(const _It2& __x, const basic_const_iterator& __y) + noexcept(noexcept(__x >= __y._M_current)) + requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> + { return __x >= __y._M_current; } + + friend constexpr basic_const_iterator + operator+(const basic_const_iterator& __i, difference_type __n) + noexcept(noexcept(basic_const_iterator(__i._M_current + __n))) + requires random_access_iterator<_It> + { return basic_const_iterator(__i._M_current + __n); } + + friend constexpr basic_const_iterator + operator+(difference_type __n, const basic_const_iterator& __i) + noexcept(noexcept(basic_const_iterator(__i._M_current + __n))) + requires random_access_iterator<_It> + { return basic_const_iterator(__i._M_current + __n); } + + friend constexpr basic_const_iterator + operator-(const basic_const_iterator& __i, difference_type __n) + noexcept(noexcept(basic_const_iterator(__i._M_current - __n))) + requires random_access_iterator<_It> + { return basic_const_iterator(__i._M_current - __n); } + + template _Sent> + constexpr difference_type + operator-(const _Sent& __y) const + noexcept(noexcept(_M_current - __y)) + { return _M_current - __y; } + + template<__detail::__not_a_const_iterator _Sent> + requires sized_sentinel_for<_Sent, _It> + friend constexpr difference_type + operator-(const _Sent& __x, const basic_const_iterator& __y) + noexcept(noexcept(__x - __y._M_current)) + { return __x - __y._M_current; } + + friend constexpr __rvalue_reference + iter_move(const basic_const_iterator& __i) + noexcept(noexcept(static_cast<__rvalue_reference>(ranges::iter_move(__i._M_current)))) + { return static_cast<__rvalue_reference>(ranges::iter_move(__i._M_current)); } + }; + + template _Up> + requires input_iterator> + struct common_type, _Up> + { using type = basic_const_iterator>; }; + + template _Up> + requires input_iterator> + struct common_type<_Up, basic_const_iterator<_Tp>> + { using type = basic_const_iterator>; }; + + template _Up> + requires input_iterator> + struct common_type, basic_const_iterator<_Up>> + { using type = basic_const_iterator>; }; + + template + constexpr const_iterator<_It> + make_const_iterator(_It __it) + noexcept(is_nothrow_convertible_v<_It, const_iterator<_It>>) + { return __it; } + + template + constexpr const_sentinel<_Sent> + make_const_sentinel(_Sent __s) + noexcept(is_nothrow_convertible_v<_Sent, const_sentinel<_Sent>>) + { return __s; } +#endif // C++23 #endif // C++20 /// @} group iterators diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 3f6ff50..283d757 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -8929,6 +8929,112 @@ namespace views::__adaptor inline constexpr _Enumerate enumerate; } + +#define __cpp_lib_ranges_as_const 202207L + + template + requires input_range<_Vp> + class as_const_view : public view_interface> + { + _Vp _M_base = _Vp(); + + public: + as_const_view() requires default_initializable<_Vp> = default; + + constexpr explicit + as_const_view(_Vp __base) + noexcept(is_nothrow_move_constructible_v<_Vp>) + : _M_base(std::move(__base)) + { } + + constexpr _Vp + base() const & + noexcept(is_nothrow_copy_constructible_v<_Vp>) + requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + noexcept(is_nothrow_move_constructible_v<_Vp>) + { return std::move(_M_base); } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { return ranges::cbegin(_M_base); } + + constexpr auto + begin() const requires range + { return ranges::cbegin(_M_base); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { return ranges::cend(_M_base); } + + constexpr auto + end() const requires range + { return ranges::cend(_M_base); } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_base); } + }; + + template + as_const_view(_Range&&) -> as_const_view>; + + template + inline constexpr bool enable_borrowed_range> + = enable_borrowed_range<_Tp>; + + namespace views + { + namespace __detail + { + template + inline constexpr bool __is_ref_view = false; + + template + inline constexpr bool __is_ref_view> = true; + + template + concept __can_as_const_view = requires { as_const_view(std::declval<_Range>()); }; + } + + struct _AsConst : __adaptor::_RangeAdaptorClosure + { + template + constexpr auto + operator()(_Range&& __r) const + noexcept(noexcept(as_const_view(std::declval<_Range>()))) + requires __detail::__can_as_const_view<_Range> + { + using _Tp = remove_cvref_t<_Range>; + using element_type = remove_reference_t>; + if constexpr (constant_range>) + return views::all(std::forward<_Range>(__r)); + else if constexpr (__detail::__is_empty_view<_Tp>) + return views::empty; + else if constexpr (std::__detail::__is_span<_Tp>) + return span(std::forward<_Range>(__r)); + else if constexpr (__detail::__is_ref_view<_Tp> + && constant_range) + return ref_view(static_cast + (std::forward<_Range>(__r).base())); + else if constexpr (is_lvalue_reference_v<_Range> + && constant_range<_Tp> + && !view<_Tp>) + return ref_view(static_cast(__r)); + else + return as_const_view(std::forward<_Range>(__r)); + } + }; + + inline constexpr _AsConst as_const; + } #endif // C++23 } // namespace ranges diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span index 06d5c18..6763389 100644 --- a/libstdc++-v3/include/std/span +++ b/libstdc++-v3/include/std/span @@ -137,6 +137,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using const_reference = const element_type&; using iterator = __gnu_cxx::__normal_iterator; using reverse_iterator = std::reverse_iterator; +#if __cplusplus > 202002L + using const_iterator = std::const_iterator; + using const_reverse_iterator = std::const_iterator; +#endif // member constants static constexpr size_t extent = _Extent; @@ -301,6 +305,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION rend() const noexcept { return reverse_iterator(this->begin()); } +#if __cplusplus > 202002L + constexpr const_iterator + cbegin() const noexcept + { return begin(); } + + constexpr const_iterator + cend() const noexcept + { return end(); } + + constexpr const_reverse_iterator + crbegin() const noexcept + { return rbegin(); } + + constexpr const_reverse_iterator + crend() const noexcept + { return rend(); } +#endif + // subviews template diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index d233b03..9f31f25 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -339,6 +339,7 @@ #define __cpp_lib_ranges_stride 202207L #define __cpp_lib_ranges_cartesian_product 202207L #define __cpp_lib_ranges_as_rvalue 202207L +#define __cpp_lib_ranges_as_const 202207L #define __cpp_lib_ranges_enumerate 202302L #define __cpp_lib_fold 202207L #if __cpp_constexpr_dynamic_alloc -- cgit v1.1 From 4ec4ceafcc04ec7bafb1857cf6d491030440a765 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Tue, 18 Apr 2023 07:21:07 -0400 Subject: libstdc++: Fix typo in views::as_const's operator() [PR109525] PR libstdc++/109525 libstdc++-v3/ChangeLog: * include/std/ranges (views::_AsConst::operator()): Add missing const to constant_range test. * testsuite/std/ranges/adaptors/as_const/1.cc (test02): Improve formatting. Adjust expected type of v2. (test03): New test. --- libstdc++-v3/include/std/ranges | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 283d757..1714f3f 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -9025,7 +9025,7 @@ namespace views::__adaptor return ref_view(static_cast (std::forward<_Range>(__r).base())); else if constexpr (is_lvalue_reference_v<_Range> - && constant_range<_Tp> + && constant_range && !view<_Tp>) return ref_view(static_cast(__r)); else -- cgit v1.1 From 95525c5b8c2d6317b693d441520b7bc808cf9ec7 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Tue, 18 Apr 2023 07:21:09 -0400 Subject: libstdc++: Adding missing feature-test macros for C++23 ranges algos This patch also renames __cpp_lib_fold to __cpp_lib_ranges_fold as per the current draft standard. libstdc++-v3/ChangeLog: * include/bits/ranges_algo.h (__cpp_lib_ranges_contains): Define for C++23. (__cpp_lib_ranges_iota): Likewise. (__cpp_lib_ranges_find_last): Likewise. (__cpp_lib_fold): Rename to ... (__cpp_lib_ranges_fold): ... this. * include/std/version: As above. * testsuite/25_algorithms/fold_left/1.cc: Adjust after renaming __cpp_lib_fold. * testsuite/std/ranges/version_c++23.cc: Verify values of the above feature-test macros. --- libstdc++-v3/include/bits/ranges_algo.h | 9 ++++++++- libstdc++-v3/include/std/version | 5 ++++- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h index f041ff1..410d3ae 100644 --- a/libstdc++-v3/include/bits/ranges_algo.h +++ b/libstdc++-v3/include/bits/ranges_algo.h @@ -3468,6 +3468,9 @@ namespace ranges inline constexpr __prev_permutation_fn prev_permutation{}; #if __cplusplus > 202002L + +#define __cpp_lib_ranges_contains 202207L + struct __contains_fn { template _Sent, @@ -3521,6 +3524,8 @@ namespace ranges inline constexpr __contains_subrange_fn contains_subrange{}; +#define __cpp_lib_ranges_iota 202202L + template struct out_value_result { @@ -3569,6 +3574,8 @@ namespace ranges inline constexpr __iota_fn iota{}; +#define __cpp_lib_ranges_find_last 202207L + struct __find_last_fn { template _Sent, typename _Tp, typename _Proj = identity> @@ -3695,7 +3702,7 @@ namespace ranges inline constexpr __find_last_if_not_fn find_last_if_not{}; -#define __cpp_lib_fold 202207L +#define __cpp_lib_ranges_fold 202207L template struct in_value_result diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index 9f31f25..027e571 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -341,7 +341,10 @@ #define __cpp_lib_ranges_as_rvalue 202207L #define __cpp_lib_ranges_as_const 202207L #define __cpp_lib_ranges_enumerate 202302L -#define __cpp_lib_fold 202207L +#define __cpp_lib_ranges_contains 202207L +#define __cpp_lib_ranges_iota 202202L +#define __cpp_lib_ranges_find_last 202207L +#define __cpp_lib_ranges_fold 202207L #if __cpp_constexpr_dynamic_alloc # if _GLIBCXX_HOSTED # define __cpp_lib_constexpr_bitset 202202L -- cgit v1.1 From cb5c71d16d0fb47638498365f5c857ce7c673eaf Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Tue, 18 Apr 2023 07:21:13 -0400 Subject: libstdc++: Implement range_adaptor_closure from P2387R3 [PR108827] PR libstdc++/108827 libstdc++-v3/ChangeLog: * include/bits/ranges_cmp.h (__cpp_lib_ranges): Bump value for C++23. * include/std/ranges (range_adaptor_closure): Define for C++23. * include/std/version (__cpp_lib_ranges): Bump value for C++23. * testsuite/std/ranges/version_c++23.cc: Bump expected value of __cpp_lib_ranges. * testsuite/std/ranges/range_adaptor_closure.cc: New test. --- libstdc++-v3/include/bits/ranges_cmp.h | 4 ++++ libstdc++-v3/include/std/ranges | 8 ++++++++ libstdc++-v3/include/std/version | 3 +++ 3 files changed, 15 insertions(+) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/ranges_cmp.h b/libstdc++-v3/include/bits/ranges_cmp.h index 85c1a77..6710d82 100644 --- a/libstdc++-v3/include/bits/ranges_cmp.h +++ b/libstdc++-v3/include/bits/ranges_cmp.h @@ -57,7 +57,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #ifdef __cpp_lib_concepts // Define this here, included by all the headers that need to define it. +#if __cplusplus > 202002L +#define __cpp_lib_ranges 202202L +#else #define __cpp_lib_ranges 202110L +#endif namespace ranges { diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 1714f3f..c4d4d85 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -1122,6 +1122,14 @@ namespace views::__adaptor }; } // namespace views::__adaptor +#if __cplusplus > 202002L + template + requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>> + class range_adaptor_closure + : public views::__adaptor::_RangeAdaptorClosure + { }; +#endif + template requires is_object_v<_Range> class ref_view : public view_interface> { diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index 027e571..02ead8f 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -265,8 +265,10 @@ #define __cpp_lib_interpolate 201902L #if __cpp_lib_concepts # define __cpp_lib_move_iterator_concept 202207L +#if __cplusplus <= 202002L // N.B. updated value in C++23 # define __cpp_lib_ranges 202110L #endif +#endif #define __cpp_lib_shift 201806L #if _GLIBCXX_HOSTED @@ -330,6 +332,7 @@ #define __cpp_lib_reference_from_temporary 202202L #define __cpp_lib_to_underlying 202102L #define __cpp_lib_unreachable 202202L +#define __cpp_lib_ranges 202202L #define __cpp_lib_ranges_zip 202110L #define __cpp_lib_ranges_chunk 202202L #define __cpp_lib_ranges_slide 202202L -- cgit v1.1 From 58b7dbf865b146a4e65dbda9be6df78f212c03b6 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Wed, 19 Apr 2023 15:36:34 -0400 Subject: c++: Define built-in for std::tuple_element [PR100157] This adds a new built-in to replace the recursive class template instantiations done by traits such as std::tuple_element and std::variant_alternative. The purpose is to select the Nth type from a list of types, e.g. __type_pack_element<1, char, int, float> is int. We implement it as a special kind of TRAIT_TYPE. For a pathological example tuple_element_t<1000, tuple<2000 types...>> the compilation time is reduced by more than 90% and the memory used by the compiler is reduced by 97%. In realistic examples the gains will be much smaller, but still relevant. Unlike the other built-in traits, __type_pack_element uses template-id syntax instead of call syntax and is SFINAE-enabled, matching Clang's implementation. And like the other built-in traits, it's not mangleable so we can't use it directly in function signatures. N.B. Clang seems to implement __type_pack_element as a first-class template that can e.g. be used as a template-template argument. For simplicity we implement it in a more ad-hoc way. Co-authored-by: Jonathan Wakely PR c++/100157 gcc/cp/ChangeLog: * cp-trait.def (TYPE_PACK_ELEMENT): Define. * cp-tree.h (finish_trait_type): Add complain parameter. * cxx-pretty-print.cc (pp_cxx_trait): Handle CPTK_TYPE_PACK_ELEMENT. * parser.cc (cp_parser_constant_expression): Document default arguments. (cp_parser_trait): Handle CPTK_TYPE_PACK_ELEMENT. Pass tf_warning_or_error to finish_trait_type. * pt.cc (tsubst) : Handle non-type first argument. Pass complain to finish_trait_type. * semantics.cc (finish_type_pack_element): Define. (finish_trait_type): Add complain parameter. Handle CPTK_TYPE_PACK_ELEMENT. * tree.cc (strip_typedefs): Handle non-type first argument. Pass tf_warning_or_error to finish_trait_type. * typeck.cc (structural_comptypes) : Use cp_tree_equal instead of same_type_p for the first argument. libstdc++-v3/ChangeLog: * include/bits/utility.h (_Nth_type): Conditionally define in terms of __type_pack_element if available. * testsuite/20_util/tuple/element_access/get_neg.cc: Prune additional errors from the new built-in. gcc/testsuite/ChangeLog: * g++.dg/ext/type_pack_element1.C: New test. * g++.dg/ext/type_pack_element2.C: New test. * g++.dg/ext/type_pack_element3.C: New test. --- libstdc++-v3/include/bits/utility.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/utility.h b/libstdc++-v3/include/bits/utility.h index abaaae2..4692aa0 100644 --- a/libstdc++-v3/include/bits/utility.h +++ b/libstdc++-v3/include/bits/utility.h @@ -224,6 +224,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif // C++17 #endif // C++14 +#if __has_builtin(__type_pack_element) + template + struct _Nth_type + { using type = __type_pack_element<_Np, _Types...>; }; +#else template struct _Nth_type { }; @@ -262,6 +267,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct _Nth_type<1, _Tp0, _Tp1, _Tp2, _Rest...> { using type = _Tp1; }; #endif +#endif #if __cplusplus > 202002L #define __cpp_lib_ranges_zip 202110L // for and -- cgit v1.1 From 83470a5cd4c3d233e1d55b5e5553e1b9c553bf28 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Mon, 24 Apr 2023 13:39:54 -0400 Subject: libstdc++: Fix __max_diff_type::operator>>= for negative values This patch fixes sign bit propagation when right-shifting a negative __max_diff_type value by more than one, a bug that our existing test coverage didn't expose until r14-159-g03cebd304955a6 fixed the front end's 'signed typedef-name' handling that the test relies on (which is a non-standard extension to the language grammar). libstdc++-v3/ChangeLog: * include/bits/max_size_type.h (__max_diff_type::operator>>=): Fix propagation of sign bit. * testsuite/std/ranges/iota/max_size_type.cc: Avoid using the non-standard 'signed typedef-name'. Add some compile-time tests for right-shifting a negative __max_diff_type value by more than one. --- libstdc++-v3/include/bits/max_size_type.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/max_size_type.h b/libstdc++-v3/include/bits/max_size_type.h index 92b8168..4796135 100644 --- a/libstdc++-v3/include/bits/max_size_type.h +++ b/libstdc++-v3/include/bits/max_size_type.h @@ -560,7 +560,8 @@ namespace ranges // Arithmetic right shift. const auto __msb = _M_rep._M_msb; _M_rep >>= __r._M_rep; - _M_rep._M_msb |= __msb; + if (__msb) + _M_rep |= ~(__max_size_type(-1) >> __r._M_rep); return *this; } -- cgit v1.1 From 865869dc6943eb5dee855bc1ea88b09b7dabc641 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 26 Apr 2023 22:48:35 +0100 Subject: libstdc++: Add @headerfile and @since to doxygen comments [PR40380] libstdc++-v3/ChangeLog: PR libstdc++/40380 * include/bits/basic_string.h: Improve doxygen comments. * include/bits/cow_string.h: Likewise. * include/bits/forward_list.h: Likewise. * include/bits/fs_dir.h: Likewise. * include/bits/fs_path.h: Likewise. * include/bits/quoted_string.h: Likewise. * include/bits/stl_bvector.h: Likewise. * include/bits/stl_map.h: Likewise. * include/bits/stl_multimap.h: Likewise. * include/bits/stl_multiset.h: Likewise. * include/bits/stl_set.h: Likewise. * include/bits/stl_vector.h: Likewise. * include/bits/unordered_map.h: Likewise. * include/bits/unordered_set.h: Likewise. * include/std/filesystem: Likewise. * include/std/iomanip: Likewise. --- libstdc++-v3/include/bits/basic_string.h | 2 ++ libstdc++-v3/include/bits/cow_string.h | 2 ++ libstdc++-v3/include/bits/forward_list.h | 2 ++ libstdc++-v3/include/bits/fs_dir.h | 35 +++++++++++++++++++++++++++++-- libstdc++-v3/include/bits/fs_path.h | 18 +++++++++++++++- libstdc++-v3/include/bits/quoted_string.h | 12 +++++++---- libstdc++-v3/include/bits/stl_bvector.h | 2 ++ libstdc++-v3/include/bits/stl_map.h | 2 ++ libstdc++-v3/include/bits/stl_multimap.h | 2 ++ libstdc++-v3/include/bits/stl_multiset.h | 3 ++- libstdc++-v3/include/bits/stl_set.h | 2 ++ libstdc++-v3/include/bits/stl_vector.h | 2 ++ libstdc++-v3/include/bits/unordered_map.h | 4 ++++ libstdc++-v3/include/bits/unordered_set.h | 4 ++++ libstdc++-v3/include/std/filesystem | 2 ++ libstdc++-v3/include/std/iomanip | 1 + 16 files changed, 87 insertions(+), 8 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 5d040e2..8247ee6 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -69,6 +69,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * * @ingroup strings * @ingroup sequences + * @headerfile string + * @since C++98 * * @tparam _CharT Type of character * @tparam _Traits Traits for character type, defaults to diff --git a/libstdc++-v3/include/bits/cow_string.h b/libstdc++-v3/include/bits/cow_string.h index b602436..e5f094f 100644 --- a/libstdc++-v3/include/bits/cow_string.h +++ b/libstdc++-v3/include/bits/cow_string.h @@ -54,6 +54,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * @ingroup strings * @ingroup sequences + * @headerfile string + * @since C++98 * * @tparam _CharT Type of character * @tparam _Traits Traits for character type, defaults to diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h index e1e68bd..72b1ef4 100644 --- a/libstdc++-v3/include/bits/forward_list.h +++ b/libstdc++-v3/include/bits/forward_list.h @@ -406,6 +406,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * and fixed time insertion/deletion at any point in the sequence. * * @ingroup sequences + * @headerfile forward_list + * @since C++11 * * @tparam _Tp Type of element. * @tparam _Alloc Allocator type, defaults to allocator<_Tp>. diff --git a/libstdc++-v3/include/bits/fs_dir.h b/libstdc++-v3/include/bits/fs_dir.h index b4adf49..9dd0f89 100644 --- a/libstdc++-v3/include/bits/fs_dir.h +++ b/libstdc++-v3/include/bits/fs_dir.h @@ -52,6 +52,10 @@ namespace filesystem */ /// Information about a file's type and permissions. + /** + * @headerfile filesystem + * @since C++17 + */ class file_status { public: @@ -94,6 +98,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 class recursive_directory_iterator; /// The value type used by directory iterators + /** + * @headerfile filesystem + * @since C++17 + */ class directory_entry { public: @@ -354,7 +362,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 file_type _M_type = file_type::none; }; + /// @cond undocumented + /// Proxy returned by post-increment on directory iterators. + /** + * @headerfile filesystem + * @since C++17 + */ struct __directory_iterator_proxy { const directory_entry& operator*() const& noexcept { return _M_entry; } @@ -370,8 +384,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 directory_entry _M_entry; }; + /// @endcond /// Iterator type for traversing the entries in a single directory. + /** + * @headerfile filesystem + * @since C++17 + */ class directory_iterator { public: @@ -451,7 +470,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 std::__shared_ptr<_Dir> _M_dir; }; - /// @relates std::filesystem::directory_iterator @{ + /** @relates std::filesystem::directory_iterator + * @headerfile filesystem + * @since C++17 + * @{ + */ /** @brief Enable range-based `for` using directory_iterator. * @@ -468,6 +491,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 /// @} /// Iterator type for recursively traversing a directory hierarchy. + /** + * @headerfile filesystem + * @since C++17 + */ class recursive_directory_iterator { public: @@ -566,7 +593,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 filesystem::remove_all(const path&); }; - /// @relates std::filesystem::recursive_directory_iterator @{ + /** @relates std::filesystem::directory_iterator + * @headerfile filesystem + * @since C++17 + * @{ + */ /** @brief Enable range-based `for` using recursive_directory_iterator. * diff --git a/libstdc++-v3/include/bits/fs_path.h b/libstdc++-v3/include/bits/fs_path.h index 0d7bb10..853c55f 100644 --- a/libstdc++-v3/include/bits/fs_path.h +++ b/libstdc++-v3/include/bits/fs_path.h @@ -285,7 +285,11 @@ namespace __detail /// @{ /// A filesystem path - /// @ingroup filesystem + /** + * @ingroup filesystem + * @headerfile filesystem + * @since C++17 + */ class path { public: @@ -736,6 +740,10 @@ namespace __detail /// @} /// Exception type thrown by the Filesystem library + /** + * @headerfile filesystem + * @since C++17 + */ class filesystem_error : public std::system_error { public: @@ -798,6 +806,8 @@ namespace __detail /** Create a path from a UTF-8-encoded sequence of char * * @relates std::filesystem::path + * @headerfile filesystem + * @since C++17 */ template, @@ -822,6 +832,8 @@ namespace __detail /** Create a path from a UTF-8-encoded sequence of char * * @relates std::filesystem::path + * @headerfile filesystem + * @since C++17 */ template, @@ -923,6 +935,10 @@ namespace __detail /// @endcond /// An iterator for the components of a path + /** + * @headerfile filesystem + * @since C++17 + */ class path::iterator { public: diff --git a/libstdc++-v3/include/bits/quoted_string.h b/libstdc++-v3/include/bits/quoted_string.h index 0644b07..ae961a9 100644 --- a/libstdc++-v3/include/bits/quoted_string.h +++ b/libstdc++-v3/include/bits/quoted_string.h @@ -85,14 +85,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * @brief Inserter for quoted strings. * - * _GLIBCXX_RESOLVE_LIB_DEFECTS - * DR 2344 quoted()'s interaction with padding is unclear + * @headerfile iomanip */ template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const _Quoted_string& __str) { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 2344 quoted()'s interaction with padding is unclear std::basic_ostringstream<_CharT, _Traits> __ostr; __ostr << __str._M_delim; for (const _CharT* __c = __str._M_string; *__c; ++__c) @@ -109,14 +110,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * @brief Inserter for quoted strings. * - * _GLIBCXX_RESOLVE_LIB_DEFECTS - * DR 2344 quoted()'s interaction with padding is unclear + * @headerfile iomanip */ template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const _Quoted_string<_String, _CharT>& __str) { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 2344 quoted()'s interaction with padding is unclear std::basic_ostringstream<_CharT, _Traits> __ostr; __ostr << __str._M_delim; for (auto __c : __str._M_string) @@ -133,6 +135,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * @brief Extractor for delimited strings. * The left and right delimiters can be different. + * + * @headerfile iomanip */ template std::basic_istream<_CharT, _Traits>& diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h index d4d4bfc..ad462c5 100644 --- a/libstdc++-v3/include/bits/stl_bvector.h +++ b/libstdc++-v3/include/bits/stl_bvector.h @@ -684,6 +684,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * access to individual elements in any order. * * @ingroup sequences + * @headerfile vector + * @since C++98 * * @tparam _Alloc Allocator type. * diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h index e1ce90e..059916d 100644 --- a/libstdc++-v3/include/bits/stl_map.h +++ b/libstdc++-v3/include/bits/stl_map.h @@ -76,6 +76,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * retrieved based on a key, in logarithmic time. * * @ingroup associative_containers + * @headerfile map + * @since C++98 * * @tparam _Key Type of key objects. * @tparam _Tp Type of mapped objects. diff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h index 6b11d4b..2efd53d 100644 --- a/libstdc++-v3/include/bits/stl_multimap.h +++ b/libstdc++-v3/include/bits/stl_multimap.h @@ -74,6 +74,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * retrieved based on a key, in logarithmic time. * * @ingroup associative_containers + * @headerfile map + * @since C++98 * * @tparam _Key Type of key objects. * @tparam _Tp Type of mapped objects. diff --git a/libstdc++-v3/include/bits/stl_multiset.h b/libstdc++-v3/include/bits/stl_multiset.h index 8f70f89..a399877 100644 --- a/libstdc++-v3/include/bits/stl_multiset.h +++ b/libstdc++-v3/include/bits/stl_multiset.h @@ -74,7 +74,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * in logarithmic time. * * @ingroup associative_containers - * + * @headerfile set + * @since C++98 * * @tparam _Key Type of key objects. * @tparam _Compare Comparison function object type, defaults to less<_Key>. diff --git a/libstdc++-v3/include/bits/stl_set.h b/libstdc++-v3/include/bits/stl_set.h index 9ce05e0..ddaf7fe 100644 --- a/libstdc++-v3/include/bits/stl_set.h +++ b/libstdc++-v3/include/bits/stl_set.h @@ -74,6 +74,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * retrieved in logarithmic time. * * @ingroup associative_containers + * @headerfile set + * @since C++98 * * @tparam _Key Type of key objects. * @tparam _Compare Comparison function object type, defaults to less<_Key>. diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index 86ff83d..acb2939 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -403,6 +403,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * individual elements in any order. * * @ingroup sequences + * @headerfile vector + * @since C++98 * * @tparam _Tp Type of element. * @tparam _Alloc Allocator type, defaults to allocator<_Tp>. diff --git a/libstdc++-v3/include/bits/unordered_map.h b/libstdc++-v3/include/bits/unordered_map.h index f11ccda..2f63bc5 100644 --- a/libstdc++-v3/include/bits/unordered_map.h +++ b/libstdc++-v3/include/bits/unordered_map.h @@ -83,6 +83,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * with the keys. * * @ingroup unordered_associative_containers + * @headerfile unordered_map + * @since C++11 * * @tparam _Key Type of key objects. * @tparam _Tp Type of mapped objects. @@ -1226,6 +1228,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * values of another type with the keys. * * @ingroup unordered_associative_containers + * @headerfile unordered_map + * @since C++11 * * @tparam _Key Type of key objects. * @tparam _Tp Type of mapped objects. diff --git a/libstdc++-v3/include/bits/unordered_set.h b/libstdc++-v3/include/bits/unordered_set.h index 68fcfd2..f3b0c07 100644 --- a/libstdc++-v3/include/bits/unordered_set.h +++ b/libstdc++-v3/include/bits/unordered_set.h @@ -80,6 +80,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * the elements themselves. * * @ingroup unordered_associative_containers + * @headerfile unordered_set + * @since C++11 * * @tparam _Value Type of key objects. * @tparam _Hash Hashing function object type, defaults to hash<_Value>. @@ -948,6 +950,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * elements' keys are the elements themselves. * * @ingroup unordered_associative_containers + * @headerfile unordered_set + * @since C++11 * * @tparam _Value Type of key objects. * @tparam _Hash Hashing function object type, defaults to hash<_Value>. diff --git a/libstdc++-v3/include/std/filesystem b/libstdc++-v3/include/std/filesystem index eff2b93..d46e842 100644 --- a/libstdc++-v3/include/std/filesystem +++ b/libstdc++-v3/include/std/filesystem @@ -41,6 +41,8 @@ * * Utilities for performing operations on file systems and their components, * such as paths, regular files, and directories. + * + * @since C++17 */ #include diff --git a/libstdc++-v3/include/std/iomanip b/libstdc++-v3/include/std/iomanip index a5366655..5c0fb09 100644 --- a/libstdc++-v3/include/std/iomanip +++ b/libstdc++-v3/include/std/iomanip @@ -457,6 +457,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __string String to quote. * @param __delim Character to quote string with. * @param __escape Escape character to escape itself or quote character. + * @since C++14 */ template inline auto -- cgit v1.1 From afcf2b09b8317d2777f44e830c3b8de1791312d5 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 26 Apr 2023 22:50:03 +0100 Subject: libstdc++: Improve doxygen docs for libstdc++-v3/ChangeLog: * include/bits/memory_resource.h: Improve doxygen comments. * include/std/memory_resource: Likewise. --- libstdc++-v3/include/bits/memory_resource.h | 12 ++++++ libstdc++-v3/include/std/memory_resource | 63 +++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/memory_resource.h b/libstdc++-v3/include/bits/memory_resource.h index 1b9e51d..f12555d 100644 --- a/libstdc++-v3/include/bits/memory_resource.h +++ b/libstdc++-v3/include/bits/memory_resource.h @@ -53,6 +53,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION namespace pmr { /// Class memory_resource + /** + * @ingroup pmr + * @headerfile memory_resource + * @since C++17 + */ class memory_resource { static constexpr size_t _S_max_align = alignof(max_align_t); @@ -104,6 +109,13 @@ namespace pmr #endif // C++17 23.12.3 Class template polymorphic_allocator + + /// Class template polymorphic_allocator + /** + * @ingroup pmr + * @headerfile memory_resource + * @since C++17 + */ template class polymorphic_allocator { diff --git a/libstdc++-v3/include/std/memory_resource b/libstdc++-v3/include/std/memory_resource index 0085926..fdfc23c 100644 --- a/libstdc++-v3/include/std/memory_resource +++ b/libstdc++-v3/include/std/memory_resource @@ -24,6 +24,9 @@ /** @file include/memory_resource * This is a Standard C++ Library header. + * + * This header declares the @ref pmr (std::pmr) memory resources. + * @ingroup pmr */ #ifndef _GLIBCXX_MEMORY_RESOURCE @@ -35,6 +38,25 @@ #if __cplusplus >= 201703L +/** + * @defgroup pmr Polymorphic memory resources + * + * @anchor pmr + * @ingroup memory + * @since C++17 + * + * Memory resources are classes that implement the `std::pmr::memory_resource` + * interface for allocating and deallocating memory. Unlike traditional C++ + * allocators, memory resources are not value types and are used via pointers + * to the abstract base class. They are only responsible for allocating and + * deallocating, not for construction and destruction of objects. As a result, + * memory resources just allocate raw memory as type `void*` and are not + * templates that allocate/deallocate and construct/destroy a specific type. + * + * The class template `std::pmr::polymorphic_allocator` is an allocator that + * uses a memory resource for its allocations. + */ + #include #include // vector #include // shared_mutex @@ -63,6 +85,11 @@ namespace pmr // Global memory resources /// A pmr::memory_resource that uses `new` to allocate memory + /** + * @ingroup pmr + * @headerfile memory_resource + * @since C++17 + */ [[nodiscard, __gnu__::__returns_nonnull__, __gnu__::__const__]] memory_resource* new_delete_resource() noexcept; @@ -91,6 +118,11 @@ namespace pmr class monotonic_buffer_resource; /// Parameters for tuning a pool resource's behaviour. + /** + * @ingroup pmr + * @headerfile memory_resource + * @since C++17 + */ struct pool_options { /** @brief Upper limit on number of blocks in a chunk. @@ -152,6 +184,11 @@ namespace pmr #ifdef _GLIBCXX_HAS_GTHREADS /// A thread-safe memory resource that manages pools of fixed-size blocks. + /** + * @ingroup pmr + * @headerfile memory_resource + * @since C++17 + */ class synchronized_pool_resource : public memory_resource { public: @@ -218,6 +255,11 @@ namespace pmr #endif /// A non-thread-safe memory resource that manages pools of fixed-size blocks. + /** + * @ingroup pmr + * @headerfile memory_resource + * @since C++17 + */ class unsynchronized_pool_resource : public memory_resource { public: @@ -275,6 +317,27 @@ namespace pmr _Pool* _M_pools = nullptr; }; + /// A memory resource that allocates from a fixed-size buffer. + /** + * The main feature of a `pmr::monotonic_buffer_resource` is that its + * `do_deallocate` does nothing. This makes it very fast because there is no + * need to manage a free list, and every allocation simply returns a new + * block of memory, rather than searching for a suitably-sized free block. + * Because deallocating is a no-op, the amount of memory used by the resource + * only grows until `release()` (or the destructor) is called to return all + * memory to upstream. + * + * A `monotonic_buffer_resource` can be initialized with a buffer that + * will be used to satisfy all allocation requests, until the buffer is full. + * After that a new buffer will be allocated from the upstream resource. + * By using a stack buffer and `pmr::null_memory_resource()` as the upstream + * you can get a memory resource that only uses the stack and never + * dynamically allocates. + * + * @ingroup pmr + * @headerfile memory_resource + * @since C++17 + */ class monotonic_buffer_resource : public memory_resource { public: -- cgit v1.1 From afa69618d1627435841c9164b019ef98000e0365 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 26 Apr 2023 12:27:59 +0100 Subject: libstdc++: Reduce Doxygen output for PDF Including the header source code in the doxygen-generated PDF file makes it too large, and causes pdflatex to run out of memory. If we only set SOURCE_BROWSER=YES for the HTML docs then we won't include the sources in the PDF file. There are several macros defined for std::valarray that are only used to generate repetitive code and then #undef'd. Those aren't useful in the doxygen docs, especially the ones that reuse the same name in different files. Omitting them avoids warnings about duplicate labels in the refman.tex file. libstdc++-v3/ChangeLog: * doc/doxygen/user.cfg.in (SOURCE_BROWSER): Only set to YES for HTML docs. * include/bits/gslice_array.h (_DEFINE_VALARRAY_OPERATOR): Omit from doxygen docs. * include/bits/indirect_array.h (_DEFINE_VALARRAY_OPERATOR): Likewise. * include/bits/mask_array.h (_DEFINE_VALARRAY_OPERATOR): Likewise. * include/bits/slice_array.h (_DEFINE_VALARRAY_OPERATOR): Likewise. * include/std/valarray (_DEFINE_VALARRAY_UNARY_OPERATOR) (_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT) (_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT) (_DEFINE_BINARY_OPERATOR): Likewise. --- libstdc++-v3/include/bits/gslice_array.h | 2 ++ libstdc++-v3/include/bits/indirect_array.h | 2 ++ libstdc++-v3/include/bits/mask_array.h | 2 ++ libstdc++-v3/include/bits/slice_array.h | 2 ++ libstdc++-v3/include/std/valarray | 2 ++ 5 files changed, 10 insertions(+) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/gslice_array.h b/libstdc++-v3/include/bits/gslice_array.h index f117a17..6a48d41 100644 --- a/libstdc++-v3/include/bits/gslice_array.h +++ b/libstdc++-v3/include/bits/gslice_array.h @@ -183,6 +183,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Array(_M_index)); } + /// @cond undocumented #undef _DEFINE_VALARRAY_OPERATOR #define _DEFINE_VALARRAY_OPERATOR(_Op, _Name) \ template \ @@ -214,6 +215,7 @@ _DEFINE_VALARRAY_OPERATOR(<<, __shift_left) _DEFINE_VALARRAY_OPERATOR(>>, __shift_right) #undef _DEFINE_VALARRAY_OPERATOR + /// @endcond /// @} group numeric_arrays diff --git a/libstdc++-v3/include/bits/indirect_array.h b/libstdc++-v3/include/bits/indirect_array.h index deeed99..8d34a36 100644 --- a/libstdc++-v3/include/bits/indirect_array.h +++ b/libstdc++-v3/include/bits/indirect_array.h @@ -174,6 +174,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION indirect_array<_Tp>::operator=(const _Expr<_Dom, _Tp>& __e) const { std::__valarray_copy(__e, _M_sz, _M_array, _M_index); } + /// @cond undocumented #undef _DEFINE_VALARRAY_OPERATOR #define _DEFINE_VALARRAY_OPERATOR(_Op, _Name) \ template \ @@ -203,6 +204,7 @@ _DEFINE_VALARRAY_OPERATOR(<<, __shift_left) _DEFINE_VALARRAY_OPERATOR(>>, __shift_right) #undef _DEFINE_VALARRAY_OPERATOR + /// @endcond /// @} group numeric_arrays diff --git a/libstdc++-v3/include/bits/mask_array.h b/libstdc++-v3/include/bits/mask_array.h index d4112a9..a3174dd 100644 --- a/libstdc++-v3/include/bits/mask_array.h +++ b/libstdc++-v3/include/bits/mask_array.h @@ -181,6 +181,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::__valarray_copy(__e, __e.size(), _M_array, _M_mask); } + /// @cond undocumented #undef _DEFINE_VALARRAY_OPERATOR #define _DEFINE_VALARRAY_OPERATOR(_Op, _Name) \ template \ @@ -213,6 +214,7 @@ _DEFINE_VALARRAY_OPERATOR(<<, __shift_left) _DEFINE_VALARRAY_OPERATOR(>>, __shift_right) #undef _DEFINE_VALARRAY_OPERATOR + /// @endcond /// @} group numeric_arrays diff --git a/libstdc++-v3/include/bits/slice_array.h b/libstdc++-v3/include/bits/slice_array.h index 571e372..42b136d 100644 --- a/libstdc++-v3/include/bits/slice_array.h +++ b/libstdc++-v3/include/bits/slice_array.h @@ -245,6 +245,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION slice_array<_Tp>::operator=(const _Expr<_Dom,_Tp>& __e) const { std::__valarray_copy(__e, _M_sz, _M_array, _M_stride); } + /// @cond undocumented #undef _DEFINE_VALARRAY_OPERATOR #define _DEFINE_VALARRAY_OPERATOR(_Op,_Name) \ template \ @@ -275,6 +276,7 @@ _DEFINE_VALARRAY_OPERATOR(<<, __shift_left) _DEFINE_VALARRAY_OPERATOR(>>, __shift_right) #undef _DEFINE_VALARRAY_OPERATOR + /// @endcond /// @} group numeric_arrays diff --git a/libstdc++-v3/include/std/valarray b/libstdc++-v3/include/std/valarray index 504d02b..6bd23e0 100644 --- a/libstdc++-v3/include/std/valarray +++ b/libstdc++-v3/include/std/valarray @@ -1080,6 +1080,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return _Expr<_Closure, _Tp>(_Closure(*this, __func)); } + /// @cond undocumented #define _DEFINE_VALARRAY_UNARY_OPERATOR(_Op, _Name) \ template \ inline typename valarray<_Tp>::template _UnaryOp<_Name>::_Rt \ @@ -1206,6 +1207,7 @@ _DEFINE_BINARY_OPERATOR(<=, __less_equal) _DEFINE_BINARY_OPERATOR(>=, __greater_equal) #undef _DEFINE_BINARY_OPERATOR + /// @endcond #if __cplusplus >= 201103L /** -- cgit v1.1 From 481281ccf41aa2bc596e548edaad4e57833f3340 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 26 Apr 2023 23:38:43 +0100 Subject: libstdc++: Fix typos in doxygen comments libstdc++-v3/ChangeLog: * include/bits/mofunc_impl.h: Fix typo in doxygen comment. * include/std/format: Likewise. --- libstdc++-v3/include/bits/mofunc_impl.h | 3 +-- libstdc++-v3/include/std/format | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/mofunc_impl.h b/libstdc++-v3/include/bits/mofunc_impl.h index 47e1e50..318a55e 100644 --- a/libstdc++-v3/include/bits/mofunc_impl.h +++ b/libstdc++-v3/include/bits/mofunc_impl.h @@ -51,14 +51,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @headerfile functional * * The `std::move_only_function` class template is a call wrapper similar - * to * `std::function`, but does not require the stored target function + * to `std::function`, but does not require the stored target function * to be copyable. * * It also supports const-qualification, ref-qualification, and * no-throw guarantees. The qualifications and exception-specification * of the `move_only_function::operator()` member function are respected * when invoking the target function. - * */ template class move_only_function<_Res(_ArgTypes...) _GLIBCXX_MOF_CV diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index e4ef4f9..6edc320 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -185,7 +185,7 @@ namespace __format __failed_to_parse_format_spec() { __throw_format_error("format error: failed to parse format-spec"); } } // namespace __format -/// @endcond + /// @endcond // [format.parse.ctx], class template basic_format_parse_context template class basic_format_parse_context; @@ -3870,7 +3870,7 @@ namespace __format }; #endif } // namespace __format -/// @@endcond +/// @endcond template [[nodiscard]] -- cgit v1.1 From 9a41d2cdbcd2af77a3a91a840a3a13f0eb39971b Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 28 Apr 2023 10:49:40 +0200 Subject: libstdc++: Another attempt to ensure g++ 13+ compiled programs enforce gcc 13.2+ libstdc++.so.6 [PR108969] GCC used to emit an instance of an empty ios_base::Init class in every TU which included to ensure it is std::cout etc. is initialized, but thanks to Patrick work on some targets (which have init_priority attribute support) it is now initialized only inside of libstdc++.so.6/libstdc++.a. This causes a problem if people do something that has never been supported, try to run GCC 13 compiled C++ code against GCC 12 or earlier libstdc++.so.6 - std::cout etc. are then never initialized because code including expects the library to initialize it and the library expects code including to do that. The following patch is second attempt to make this work cheaply as the earlier attempt of aliasing the std::cout etc. symbols with another symbol version didn't work out due to copy relocation breaking the aliases appart. The patch forces just a _ZSt21ios_base_library_initv undefined symbol into all *.o files which include and while there is no runtime relocation against that, it seems to enforce the right version of libstdc++.so.6. /home/jakub/src/gcc/obj08i/usr/local/ is the install directory of trunk patched with this patch, /home/jakub/src/gcc/obj06/ is builddir of trunk without this patch, system g++ is GCC 12.1.1. $ cat /tmp/hw.C #include int main () { std::cout << "Hello, world!" << std::endl; } $ cd /home/jakub/src/gcc/obj08i/usr/local/bin $ ./g++ -o /tmp/hw /tmp/hw.C $ readelf -Wa /tmp/hw 2>/dev/null | grep initv 4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZSt21ios_base_library_initv@GLIBCXX_3.4.32 (4) 71: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZSt21ios_base_library_initv@GLIBCXX_3.4.32 $ /tmp/hw /tmp/hw: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.32' not found (required by /tmp/hw) $ LD_LIBRARY_PATH=/home/jakub/src/gcc/obj08i/usr/local/lib64/ /tmp/hw Hello, world! $ LD_LIBRARY_PATH=/home/jakub/src/gcc/obj06/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs/ /tmp/hw /tmp/hw: /home/jakub/src/gcc/obj06/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6: version `GLIBCXX_3.4.32' not found (required by /tmp/hw) $ g++ -o /tmp/hw /tmp/hw.C $ /tmp/hw Hello, world! $ LD_LIBRARY_PATH=/home/jakub/src/gcc/obj06/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs/ /tmp/hw Hello, world! $ LD_LIBRARY_PATH=/home/jakub/src/gcc/obj08i/usr/local/lib64/ /tmp/hw Hello, world! On sparc-sun-solaris2.11 one I've actually checked a version which had defined(_GLIBCXX_SYMVER_SUN) next to defined(_GLIBCXX_SYMVER_GNU), but init_priority attribute doesn't seem to be supported there and so I couldn't actually test how this works there. Using gas and Sun ld, Rainer, does one need to use gas + gld for init_priority or something else? 2023-04-28 Jakub Jelinek PR libstdc++/108969 * config/abi/pre/gnu.ver (GLIBCXX_3.4.32): Export _ZSt21ios_base_library_initv. * testsuite/util/testsuite_abi.cc (check_version): Add GLIBCXX_3.4.32 symver and make it the latestp. * src/c++98/ios_init.cc (ios_base_library_init): New alias. * acinclude.m4 (libtool_VERSION): Change to 6:32:0. * include/std/iostream: If init_priority attribute is supported and _GLIBCXX_SYMVER_GNU, force undefined _ZSt21ios_base_library_initv symbol into the object. * configure: Regenerated. --- libstdc++-v3/include/std/iostream | 2 ++ 1 file changed, 2 insertions(+) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/std/iostream b/libstdc++-v3/include/std/iostream index 7653002..cfd124d 100644 --- a/libstdc++-v3/include/std/iostream +++ b/libstdc++-v3/include/std/iostream @@ -77,6 +77,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // in the compiled library instead (src/c++98/globals_io.cc). #if !__has_attribute(__init_priority__) static ios_base::Init __ioinit; +#elif defined(_GLIBCXX_SYMVER_GNU) + __extension__ __asm (".globl _ZSt21ios_base_library_initv"); #endif _GLIBCXX_END_NAMESPACE_VERSION -- cgit v1.1 From 5c8b154c56a65faf64dfc5f8852e801150cb2f26 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 28 Apr 2023 11:07:40 +0100 Subject: libstdc++: Simplify preprocessor/namespace nesting in There's no good reason to conditionally close and reopen namespace std within an #if block. Just include the header at the top instead. libstdc++-v3/ChangeLog: * include/bits/move.h: Simplify opening/closing namespace std. --- libstdc++-v3/include/bits/move.h | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/move.h b/libstdc++-v3/include/bits/move.h index 6bc70e8..4a8fcef 100644 --- a/libstdc++-v3/include/bits/move.h +++ b/libstdc++-v3/include/bits/move.h @@ -33,6 +33,8 @@ #include #if __cplusplus < 201103L # include +#else +# include // Brings in std::declval too. #endif namespace std _GLIBCXX_VISIBILITY(default) @@ -51,15 +53,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#include // Brings in std::declval too. - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - /** * @addtogroup utilities * @{ -- cgit v1.1 From 30f6aace7fe5c535af41a1f08ab00dc14fedf02d Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 28 Apr 2023 11:40:01 +0100 Subject: libstdc++: Minor fixes to doxygen comments libstdc++-v3/ChangeLog: * include/bits/uses_allocator.h: Add missing @file comment. * include/bits/regex.tcc: Remove stray doxygen comments. * include/experimental/memory_resource: Likewise. * include/std/bit: Tweak doxygen @cond comments. * include/std/expected: Likewise. * include/std/numbers: Likewise. --- libstdc++-v3/include/bits/regex.tcc | 4 ---- libstdc++-v3/include/bits/uses_allocator.h | 5 +++++ libstdc++-v3/include/experimental/memory_resource | 2 -- libstdc++-v3/include/std/bit | 4 ++-- libstdc++-v3/include/std/expected | 4 ++-- libstdc++-v3/include/std/numbers | 2 +- 6 files changed, 10 insertions(+), 11 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/regex.tcc b/libstdc++-v3/include/bits/regex.tcc index a58ed3f..6f0a486 100644 --- a/libstdc++-v3/include/bits/regex.tcc +++ b/libstdc++-v3/include/bits/regex.tcc @@ -116,8 +116,6 @@ namespace __detail /// @endcond } // namespace __detail - /// @cond - template template typename regex_traits<_Ch_type>::string_type @@ -665,7 +663,5 @@ namespace __detail _M_result = nullptr; } - /// @endcond - _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/include/bits/uses_allocator.h b/libstdc++-v3/include/bits/uses_allocator.h index d1841bb..d3b26c7 100644 --- a/libstdc++-v3/include/bits/uses_allocator.h +++ b/libstdc++-v3/include/bits/uses_allocator.h @@ -22,6 +22,11 @@ // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . +/** @file include/bits/uses_allocator_args.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + #ifndef _USES_ALLOCATOR_H #define _USES_ALLOCATOR_H 1 diff --git a/libstdc++-v3/include/experimental/memory_resource b/libstdc++-v3/include/experimental/memory_resource index 070cf79..9f1cb42 100644 --- a/libstdc++-v3/include/experimental/memory_resource +++ b/libstdc++-v3/include/experimental/memory_resource @@ -45,14 +45,12 @@ #include #include -/// @cond namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION template class malloc_allocator; _GLIBCXX_END_NAMESPACE_VERSION } // namespace __gnu_cxx -/// @endcond namespace std { _GLIBCXX_BEGIN_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/std/bit b/libstdc++-v3/include/std/bit index 0c58971..5eb4021 100644 --- a/libstdc++-v3/include/std/bit +++ b/libstdc++-v3/include/std/bit @@ -144,7 +144,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #endif - /// @cond undoc + /// @cond undocumented template constexpr _Tp @@ -374,7 +374,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #define __cpp_lib_bitops 201907L - /// @cond undoc + /// @cond undocumented template using _If_is_unsigned_integer = enable_if_t<__is_unsigned_integer<_Tp>::value, _Up>; diff --git a/libstdc++-v3/include/std/expected b/libstdc++-v3/include/std/expected index 0581882..c6d26b0 100644 --- a/libstdc++-v3/include/std/expected +++ b/libstdc++-v3/include/std/expected @@ -139,7 +139,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ inline constexpr unexpect_t unexpect{}; -/// @cond undoc +/// @cond undocumented namespace __expected { template @@ -254,7 +254,7 @@ namespace __expected template unexpected(_Er) -> unexpected<_Er>; -/// @cond undoc +/// @cond undocumented namespace __expected { template diff --git a/libstdc++-v3/include/std/numbers b/libstdc++-v3/include/std/numbers index d9d202f..d7d9e81 100644 --- a/libstdc++-v3/include/std/numbers +++ b/libstdc++-v3/include/std/numbers @@ -49,7 +49,7 @@ namespace numbers { #define __cpp_lib_math_constants 201907L - /// @cond undoc + /// @cond undocumented template using _Enable_if_floating = enable_if_t, _Tp>; /// @endcond -- cgit v1.1 From d711f8f81fc5f3a5a0420337f414bce93e1cad1e Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 28 Apr 2023 12:01:58 +0100 Subject: libstdc++: Improve doxygen docs for Add @headerfile and @since tags. Add gamma_distribution to the correct group (poisson distributions). Add a group for the sampling distributions and add the missing definitions of their probability functions. Add uniform_int_distribution back to the uniform distributions group. libstdc++-v3/ChangeLog: * include/bits/random.h (gamma_distribution): Add to the right doxygen group. (discrete_distribution, piecewise_constant_distribution) (piecewise_linear_distribution): Create a new doxygen group and fix the incomplete doxygen comments. * include/bits/uniform_int_dist.h (uniform_int_distribution): Add to doxygen group. --- libstdc++-v3/include/bits/random.h | 127 +++++++++++++++++++++++++-- libstdc++-v3/include/bits/uniform_int_dist.h | 11 +++ 2 files changed, 132 insertions(+), 6 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h index 42f37c1..f77005a 100644 --- a/libstdc++-v3/include/bits/random.h +++ b/libstdc++-v3/include/bits/random.h @@ -256,6 +256,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * parameters @p __a and @p __c must be less than @p __m. * * The size of the state is @f$1@f$. + * + * @headerfile random + * @since C++11 */ template class linear_congruential_engine @@ -471,6 +474,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @tparam __c The second left-shift tempering matrix mask. * @tparam __l The second right-shift tempering matrix parameter. * @tparam __f Initialization multiplier. + * + * @headerfile random + * @since C++11 */ template class subtract_with_carry_engine @@ -890,7 +899,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * Produces random numbers from some base engine by discarding blocks of * data. * - * 0 <= @p __r <= @p __p + * @pre @f$ 0 \leq r \leq p @f$ + * + * @headerfile random + * @since C++11 */ template class discard_block_engine @@ -1114,6 +1126,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * Produces random numbers by combining random numbers from some base * engine to produce random numbers with a specified number of bits @p __w. + * + * @headerfile random + * @since C++11 */ template class independent_bits_engine @@ -1338,6 +1353,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * The values from the base engine are stored in a sequence of size @p __k * and shuffled by an algorithm that depends on those values. + * + * @headerfile random + * @since C++11 */ template class shuffle_order_engine @@ -1625,6 +1643,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * A standard interface to a platform-specific non-deterministic * random number generator (if any are available). + * + * @headerfile random + * @since C++11 */ class random_device { @@ -1750,6 +1771,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * A continuous random distribution on the range [min, max) with equal * probability throughout the range. The URNG should be real-valued and * deliver number in the range [0, 1). + * + * @headerfile random + * @since C++11 */ template class uniform_real_distribution @@ -1984,6 +2008,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * p(x|\mu,\sigma) = \frac{1}{\sigma \sqrt{2 \pi}} * e^{- \frac{{x - \mu}^ {2}}{2 \sigma ^ {2}} } * @f] + * + * @headerfile random + * @since C++11 */ template class normal_distribution @@ -2208,6 +2235,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * p(x|m,s) = \frac{1}{sx\sqrt{2\pi}} * \exp{-\frac{(\ln{x} - m)^2}{2s^2}} * @f] + * + * @headerfile random + * @since C++11 */ template class lognormal_distribution @@ -2414,6 +2444,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return !(__d1 == __d2); } #endif + /// @} group random_distributions_normal + + /** + * @addtogroup random_distributions_poisson Poisson Distributions + * @ingroup random_distributions + * @{ + */ + /** * @brief A gamma continuous distribution for random numbers. * @@ -2422,6 +2460,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * p(x|\alpha,\beta) = \frac{1}{\beta\Gamma(\alpha)} * (x/\beta)^{\alpha - 1} e^{-x/\beta} * @f] + * + * @headerfile random + * @since C++11 */ template class gamma_distribution @@ -2645,14 +2686,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline bool operator!=(const std::gamma_distribution<_RealType>& __d1, const std::gamma_distribution<_RealType>& __d2) - { return !(__d1 == __d2); } + { return !(__d1 == __d2); } #endif + /// @} group random_distributions_poisson + + /** + * @addtogroup random_distributions_normal Normal Distributions + * @ingroup random_distributions + * @{ + */ + /** * @brief A chi_squared_distribution random number distribution. * * The formula for the normal probability mass function is * @f$p(x|n) = \frac{x^{(n/2) - 1}e^{-x/2}}{\Gamma(n/2) 2^{n/2}}@f$ + * + * @headerfile random + * @since C++11 */ template class chi_squared_distribution @@ -2880,6 +2932,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * The formula for the normal probability mass function is * @f$p(x|a,b) = (\pi b (1 + (\frac{x-a}{b})^2))^{-1}@f$ + * + * @headerfile random + * @since C++11 */ template class cauchy_distribution @@ -3092,6 +3147,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * (\frac{m}{n})^{m/2} x^{(m/2)-1} * (1 + \frac{mx}{n})^{-(m+n)/2} * @f] + * + * @headerfile random + * @since C++11 */ template class fisher_f_distribution @@ -3328,6 +3386,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * p(x|n) = \frac{1}{\sqrt(n\pi)} \frac{\Gamma((n+1)/2)}{\Gamma(n/2)} * (1 + \frac{x^2}{n}) ^{-(n+1)/2} * @f] + * + * @headerfile random + * @since C++11 */ template class student_t_distribution @@ -3559,6 +3620,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * Generates a sequence of true and false values with likelihood @f$p@f$ * that true will come up and @f$(1 - p)@f$ that false will appear. + * + * @headerfile random + * @since C++11 */ class bernoulli_distribution { @@ -3779,6 +3843,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * The formula for the binomial probability density function is * @f$p(i|t,p) = \binom{t}{i} p^i (1 - p)^{t - i}@f$ where @f$t@f$ * and @f$p@f$ are the parameters of the distribution. + * + * @headerfile random + * @since C++11 */ template class binomial_distribution @@ -4022,6 +4089,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * The formula for the geometric probability density function is * @f$p(i|p) = p(1 - p)^{i}@f$ where @f$p@f$ is the parameter of the * distribution. + * + * @headerfile random + * @since C++11 */ template class geometric_distribution @@ -4236,6 +4306,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * The formula for the negative binomial probability mass function is * @f$p(i) = \binom{n}{i} p^i (1 - p)^{t - i}@f$ where @f$t@f$ * and @f$p@f$ are the parameters of the distribution. + * + * @headerfile random + * @since C++11 */ template class negative_binomial_distribution @@ -4470,6 +4543,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * The formula for the Poisson probability density function is * @f$p(i|\mu) = \frac{\mu^i}{i!} e^{-\mu}@f$ where @f$\mu@f$ is the * parameter of the distribution. + * + * @headerfile random + * @since C++11 */ template class poisson_distribution @@ -4699,6 +4775,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * Range@f$[0, \infty]@f$ * Standard Deviation@f$\frac{1}{\lambda}@f$ * + * + * @headerfile random + * @since C++11 */ template class exponential_distribution @@ -4918,6 +4997,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * p(x|\alpha,\beta) = \frac{\alpha}{\beta} (\frac{x}{\beta})^{\alpha-1} * \exp{(-(\frac{x}{\beta})^\alpha)} * @f] + * + * @headerfile random + * @since C++11 */ template class weibull_distribution @@ -5132,6 +5214,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * p(x|a,b) = \frac{1}{b} * \exp( \frac{a-x}{b} - \exp(\frac{a-x}{b})) * @f] + * + * @headerfile random + * @since C++11 */ template class extreme_value_distribution @@ -5337,12 +5422,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, std::extreme_value_distribution<_RealType>& __x); + /// @} group random_distributions_poisson + + /** + * @addtogroup random_distributions_sampling Sampling Distributions + * @ingroup random_distributions + * @{ + */ /** * @brief A discrete_distribution random number distribution. * - * The formula for the discrete probability mass function is + * This distribution produces random numbers @f$ i, 0 \leq i < n @f$, + * distributed according to the probability mass function + * @f$ p(i | p_0, ..., p_{n-1}) = p_i @f$. * + * @headerfile random + * @since C++11 */ template class discrete_distribution @@ -5579,8 +5675,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * @brief A piecewise_constant_distribution random number distribution. * - * The formula for the piecewise constant probability mass function is + * This distribution produces random numbers @f$ x, b_0 \leq x < b_n @f$, + * uniformly distributed over each subinterval @f$ [b_i, b_{i+1}) @f$ + * according to the probability mass function + * @f[ + * p(x | b_0, ..., b_n, \rho_0, ..., \rho_{n-1}) + * = \rho_i \cdot \frac{b_{i+1} - x}{b_{i+1} - b_i} + * + \rho_{i+1} \cdot \frac{ x - b_i}{b_{i+1} - b_i} + * @f] + * for @f$ b_i \leq x < b_{i+1} @f$. * + * @headerfile random + * @since C++11 */ template class piecewise_constant_distribution @@ -5853,8 +5959,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * @brief A piecewise_linear_distribution random number distribution. * - * The formula for the piecewise linear probability mass function is + * This distribution produces random numbers @f$ x, b_0 \leq x < b_n @f$, + * distributed over each subinterval @f$ [b_i, b_{i+1}) @f$ + * according to the probability mass function + * @f$ p(x | b_0, ..., b_n, \rho_0, ..., \rho_n) = \rho_i @f$, + * for @f$ b_i \leq x < b_{i+1} @f$. * + * @headerfile random + * @since C++11 */ template class piecewise_linear_distribution @@ -6126,7 +6238,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return !(__d1 == __d2); } #endif - /// @} group random_distributions_poisson + /// @} group random_distributions_sampling /// @} *group random_distributions @@ -6139,6 +6251,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * @brief The seed_seq class generates sequences of seeds for random * number generators. + * + * @headerfile random + * @since C++11 */ class seed_seq { diff --git a/libstdc++-v3/include/bits/uniform_int_dist.h b/libstdc++-v3/include/bits/uniform_int_dist.h index 5776e5d..7ccf930 100644 --- a/libstdc++-v3/include/bits/uniform_int_dist.h +++ b/libstdc++-v3/include/bits/uniform_int_dist.h @@ -44,6 +44,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #ifdef __cpp_lib_concepts /// Requirements for a uniform random bit generator. + /** + * @ingroup random_distributions_uniform + * @headerfile random + * @since C++20 + */ template concept uniform_random_bit_generator = invocable<_Gen&> && unsigned_integral> @@ -55,6 +60,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; #endif + /// @cond undocumented namespace __detail { // Determine whether number is a power of two. @@ -67,11 +73,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return ((__x - 1) & __x) == 0; } } + /// @endcond /** * @brief Uniform discrete distribution for random numbers. * A discrete random distribution on the range @f$[min, max]@f$ with equal * probability throughout the range. + * + * @ingroup random_distributions_uniform + * @headerfile random + * @since C++11 */ template class uniform_int_distribution -- cgit v1.1 From cbf6c7a1d16490a1e63e9a5ce00e9a5c44c4c2f2 Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Mon, 1 May 2023 21:24:26 +0100 Subject: libstdc++: Set _M_string_length before calling _M_dispose() [PR109703] This always sets _M_string_length in the constructor for ranges of input iterators, such as stream iterators. We copy from the source range to the local buffer, and then repeatedly reallocate a larger one if necessary. When disposing the old buffer, _M_is_local() is used to tell if the buffer is the local one or not (and so must be deallocated). In addition to comparing the buffer address with the local buffer, _M_is_local() has an optimization hint so that the compiler knows that for a string using the local buffer, there is an invariant that _M_string_length <= _S_local_capacity (added for PR109299 via r13-6915-gbf78b43873b0b7). But we failed to set _M_string_length in the constructor taking a pair of iterators, so the invariant might not hold, and __builtin_unreachable() is reached. This causes UBsan errors, and potentially misoptimization. To ensure the invariant holds, _M_string_length is initialized to zero before doing anything else, so that _M_is_local() doesn't see an uninitialized value. This issue only surfaces when constructing a string with a range of input iterator, and the uninitialized _M_string_length happens to be greater than _S_local_capacity, i.e., 15 for the std::string specialization. libstdc++-v3/ChangeLog: PR libstdc++/109703 * include/bits/basic_string.h (basic_string(Iter, Iter, Alloc)): Initialize _M_string_length. Signed-off-by: Kefu Chai Co-authored-by: Jonathan Wakely --- libstdc++-v3/include/bits/basic_string.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 8247ee6..b16b289 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -760,7 +760,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _GLIBCXX20_CONSTEXPR basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a = _Alloc()) - : _M_dataplus(_M_local_data(), __a) + : _M_dataplus(_M_local_data(), __a), _M_string_length(0) { #if __cplusplus >= 201103L _M_construct(__beg, __end, std::__iterator_category(__beg)); -- cgit v1.1 From 5476c9142830d01c4b8f2d91e9d439cb32d76378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Dumont?= Date: Wed, 3 May 2023 06:45:47 +0200 Subject: libstdc++: [_Hashtable] Implement several small methods implicitly inline Make implementation of 3 simple _Hashtable methods implicitly inline. Avoid usage of const_iterator abstraction within _Hashtable implementation. Replace several usages of __node_type* with expected __node_ptr. libstdc++-v3/ChangeLog: * include/bits/hashtable_policy.h (_NodeBuilder<>::_S_build): Use __node_ptr. (_ReuseOrAllocNode<>): Use __node_ptr in place of __node_type*. (_AllocNode<>): Likewise. (_Equality<>::_M_equal): Remove const_iterator usages. Only preserved to call std::is_permutation in the non-unique key implementation. * include/bits/hashtable.h (_Hashtable<>::_M_update_begin()): Capture _M_begin() once. (_Hashtable<>::_M_bucket_begin(size_type)): Implement implicitly inline. (_Hashtable<>::_M_insert_bucket_begin): Likewise. (_Hashtable<>::_M_remove_bucket_begin): Likewise. (_Hashtable<>::_M_compute_hash_code): Use __node_ptr rather than const_iterator. (_Hashtable<>::find): Likewise. (_Hashtable<>::_M_emplace): Likewise. (_Hashtable<>::_M_insert_unique): Likewise. --- libstdc++-v3/include/bits/hashtable.h | 181 +++++++++++---------------- libstdc++-v3/include/bits/hashtable_policy.h | 57 +++++---- 2 files changed, 106 insertions(+), 132 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h index d2ff153..954a1c7 100644 --- a/libstdc++-v3/include/bits/hashtable.h +++ b/libstdc++-v3/include/bits/hashtable.h @@ -401,8 +401,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void _M_update_bbegin() { - if (_M_begin()) - _M_buckets[_M_bucket_index(*_M_begin())] = &_M_before_begin; + if (auto __begin = _M_begin()) + _M_buckets[_M_bucket_index(*__begin)] = &_M_before_begin; } void @@ -458,7 +458,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Gets bucket begin, deals with the fact that non-empty buckets contain // their before begin node. __node_ptr - _M_bucket_begin(size_type __bkt) const; + _M_bucket_begin(size_type __bkt) const + { + __node_base_ptr __n = _M_buckets[__bkt]; + return __n ? static_cast<__node_ptr>(__n->_M_nxt) : nullptr; + } __node_ptr _M_begin() const @@ -831,19 +835,57 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Insert a node at the beginning of a bucket. void - _M_insert_bucket_begin(size_type, __node_ptr); + _M_insert_bucket_begin(size_type __bkt, __node_ptr __node) + { + if (_M_buckets[__bkt]) + { + // Bucket is not empty, we just need to insert the new node + // after the bucket before begin. + __node->_M_nxt = _M_buckets[__bkt]->_M_nxt; + _M_buckets[__bkt]->_M_nxt = __node; + } + else + { + // The bucket is empty, the new node is inserted at the + // beginning of the singly-linked list and the bucket will + // contain _M_before_begin pointer. + __node->_M_nxt = _M_before_begin._M_nxt; + _M_before_begin._M_nxt = __node; + + if (__node->_M_nxt) + // We must update former begin bucket that is pointing to + // _M_before_begin. + _M_buckets[_M_bucket_index(*__node->_M_next())] = __node; + + _M_buckets[__bkt] = &_M_before_begin; + } + } // Remove the bucket first node void _M_remove_bucket_begin(size_type __bkt, __node_ptr __next_n, - size_type __next_bkt); + size_type __next_bkt) + { + if (!__next_n || __next_bkt != __bkt) + { + // Bucket is now empty + // First update next bucket if any + if (__next_n) + _M_buckets[__next_bkt] = _M_buckets[__bkt]; + + // Second update before begin node if necessary + if (&_M_before_begin == _M_buckets[__bkt]) + _M_before_begin._M_nxt = __next_n; + _M_buckets[__bkt] = nullptr; + } + } // Get the node before __n in the bucket __bkt __node_base_ptr _M_get_previous_node(size_type __bkt, __node_ptr __n); - pair - _M_compute_hash_code(const_iterator __hint, const key_type& __k) const; + pair<__node_ptr, __hash_code> + _M_compute_hash_code(__node_ptr __hint, const key_type& __k) const; // Insert node __n with hash code __code, in bucket __bkt if no // rehash (assumes no element with same key already present). @@ -1157,20 +1199,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename _ExtractKey, typename _Equal, typename _Hash, typename _RangeHash, typename _Unused, typename _RehashPolicy, typename _Traits> - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>:: - _M_bucket_begin(size_type __bkt) const - -> __node_ptr - { - __node_base_ptr __n = _M_buckets[__bkt]; - return __n ? static_cast<__node_ptr>(__n->_M_nxt) : nullptr; - } - - template _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>:: _Hashtable(size_type __bkt_count_hint, @@ -1653,9 +1681,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if (size() <= __small_size_threshold()) { - for (auto __it = begin(); __it != end(); ++__it) - if (this->_M_key_equals(__k, *__it._M_cur)) - return __it; + for (auto __it = _M_begin(); __it; __it = __it->_M_next()) + if (this->_M_key_equals(__k, *__it)) + return iterator(__it); return end(); } @@ -1676,9 +1704,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if (size() <= __small_size_threshold()) { - for (auto __it = begin(); __it != end(); ++__it) - if (this->_M_key_equals(__k, *__it._M_cur)) - return __it; + for (auto __it = _M_begin(); __it; __it = __it->_M_next()) + if (this->_M_key_equals(__k, *__it)) + return const_iterator(__it); return end(); } @@ -1988,63 +2016,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename _ExtractKey, typename _Equal, typename _Hash, typename _RangeHash, typename _Unused, typename _RehashPolicy, typename _Traits> - void - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>:: - _M_insert_bucket_begin(size_type __bkt, __node_ptr __node) - { - if (_M_buckets[__bkt]) - { - // Bucket is not empty, we just need to insert the new node - // after the bucket before begin. - __node->_M_nxt = _M_buckets[__bkt]->_M_nxt; - _M_buckets[__bkt]->_M_nxt = __node; - } - else - { - // The bucket is empty, the new node is inserted at the - // beginning of the singly-linked list and the bucket will - // contain _M_before_begin pointer. - __node->_M_nxt = _M_before_begin._M_nxt; - _M_before_begin._M_nxt = __node; - - if (__node->_M_nxt) - // We must update former begin bucket that is pointing to - // _M_before_begin. - _M_buckets[_M_bucket_index(*__node->_M_next())] = __node; - - _M_buckets[__bkt] = &_M_before_begin; - } - } - - template - void - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>:: - _M_remove_bucket_begin(size_type __bkt, __node_ptr __next, - size_type __next_bkt) - { - if (!__next || __next_bkt != __bkt) - { - // Bucket is now empty - // First update next bucket if any - if (__next) - _M_buckets[__next_bkt] = _M_buckets[__bkt]; - - // Second update before begin node if necessary - if (&_M_before_begin == _M_buckets[__bkt]) - _M_before_begin._M_nxt = __next; - _M_buckets[__bkt] = nullptr; - } - } - - template auto _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>:: @@ -2073,10 +2044,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const key_type& __k = _ExtractKey{}(__node._M_node->_M_v()); if (size() <= __small_size_threshold()) { - for (auto __it = begin(); __it != end(); ++__it) - if (this->_M_key_equals(__k, *__it._M_cur)) + for (auto __it = _M_begin(); __it; __it = __it->_M_next()) + if (this->_M_key_equals(__k, *__it)) // There is already an equivalent node, no insertion - return { __it, false }; + return { iterator(__it), false }; } __hash_code __code = this->_M_hash_code(__k); @@ -2108,10 +2079,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Scoped_node __node { this, std::forward<_Args>(__args)... }; const key_type& __k = _ExtractKey{}(__node._M_node->_M_v()); - auto __res = this->_M_compute_hash_code(__hint, __k); + auto __res = this->_M_compute_hash_code(__hint._M_cur, __k); auto __pos - = _M_insert_multi_node(__res.first._M_cur, __res.second, - __node._M_node); + = _M_insert_multi_node(__res.first, __res.second, __node._M_node); __node._M_node = nullptr; return __pos; } @@ -2123,21 +2093,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION auto _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>:: - _M_compute_hash_code(const_iterator __hint, const key_type& __k) const - -> pair + _M_compute_hash_code(__node_ptr __hint, const key_type& __k) const + -> pair<__node_ptr, __hash_code> { if (size() <= __small_size_threshold()) { - if (__hint != cend()) + if (__hint) { - for (auto __it = __hint; __it != cend(); ++__it) - if (this->_M_key_equals(__k, *__it._M_cur)) - return { __it, this->_M_hash_code(*__it._M_cur) }; + for (auto __it = __hint; __it; __it = __it->_M_next()) + if (this->_M_key_equals(__k, *__it)) + return { __it, this->_M_hash_code(*__it) }; } - for (auto __it = cbegin(); __it != __hint; ++__it) - if (this->_M_key_equals(__k, *__it._M_cur)) - return { __it, this->_M_hash_code(*__it._M_cur) }; + for (auto __it = _M_begin(); __it != __hint; __it = __it->_M_next()) + if (this->_M_key_equals(__k, *__it)) + return { __it, this->_M_hash_code(*__it) }; + + __hint = nullptr; } return { __hint, this->_M_hash_code(__k) }; @@ -2242,9 +2214,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION -> pair { if (size() <= __small_size_threshold()) - for (auto __it = begin(); __it != end(); ++__it) - if (this->_M_key_equals_tr(__k, *__it._M_cur)) - return { __it, false }; + for (auto __it = _M_begin(); __it; __it = __it->_M_next()) + if (this->_M_key_equals_tr(__k, *__it)) + return { iterator(__it), false }; __hash_code __code = this->_M_hash_code_tr(__k); size_type __bkt = _M_bucket_index(__code); @@ -2284,11 +2256,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Second compute the hash code so that we don't rehash if it throws. auto __res = this->_M_compute_hash_code( - __hint, _ExtractKey{}(__node._M_node->_M_v())); + __hint._M_cur, _ExtractKey{}(__node._M_node->_M_v())); auto __pos - = _M_insert_multi_node(__res.first._M_cur, __res.second, - __node._M_node); + = _M_insert_multi_node(__res.first, __res.second, __node._M_node); __node._M_node = nullptr; return __pos; } diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h index cce4e28..347d468 100644 --- a/libstdc++-v3/include/bits/hashtable_policy.h +++ b/libstdc++-v3/include/bits/hashtable_policy.h @@ -156,7 +156,7 @@ namespace __detail template static auto _S_build(_Kt&& __k, _Arg&& __arg, const _NodeGenerator& __node_gen) - -> typename _NodeGenerator::__node_type* + -> typename _NodeGenerator::__node_ptr { return __node_gen(std::forward<_Kt>(__k), std::forward<_Arg>(__arg).second); @@ -169,7 +169,7 @@ namespace __detail template static auto _S_build(_Kt&& __k, _Arg&&, const _NodeGenerator& __node_gen) - -> typename _NodeGenerator::__node_type* + -> typename _NodeGenerator::__node_ptr { return __node_gen(std::forward<_Kt>(__k)); } }; @@ -188,9 +188,9 @@ namespace __detail typename __hashtable_alloc::__node_alloc_traits; public: - using __node_type = typename __hashtable_alloc::__node_type; + using __node_ptr = typename __hashtable_alloc::__node_ptr; - _ReuseOrAllocNode(__node_type* __nodes, __hashtable_alloc& __h) + _ReuseOrAllocNode(__node_ptr __nodes, __hashtable_alloc& __h) : _M_nodes(__nodes), _M_h(__h) { } _ReuseOrAllocNode(const _ReuseOrAllocNode&) = delete; @@ -198,12 +198,12 @@ namespace __detail { _M_h._M_deallocate_nodes(_M_nodes); } template - __node_type* + __node_ptr operator()(_Args&&... __args) const { if (_M_nodes) { - __node_type* __node = _M_nodes; + __node_ptr __node = _M_nodes; _M_nodes = _M_nodes->_M_next(); __node->_M_nxt = nullptr; auto& __a = _M_h._M_node_allocator(); @@ -224,7 +224,7 @@ namespace __detail } private: - mutable __node_type* _M_nodes; + mutable __node_ptr _M_nodes; __hashtable_alloc& _M_h; }; @@ -237,13 +237,13 @@ namespace __detail using __hashtable_alloc = _Hashtable_alloc<_NodeAlloc>; public: - using __node_type = typename __hashtable_alloc::__node_type; + using __node_ptr = typename __hashtable_alloc::__node_ptr; _AllocNode(__hashtable_alloc& __h) : _M_h(__h) { } template - __node_type* + __node_ptr operator()(_Args&&... __args) const { return _M_h._M_allocate_node(std::forward<_Args>(__args)...); } @@ -1809,22 +1809,22 @@ namespace __detail _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits, true>:: _M_equal(const __hashtable& __other) const { - using __node_type = typename __hashtable::__node_type; + using __node_ptr = typename __hashtable::__node_ptr; const __hashtable* __this = static_cast(this); if (__this->size() != __other.size()) return false; - for (auto __itx = __this->begin(); __itx != __this->end(); ++__itx) + for (auto __x_n = __this->_M_begin(); __x_n; __x_n = __x_n->_M_next()) { - std::size_t __ybkt = __other._M_bucket_index(*__itx._M_cur); + std::size_t __ybkt = __other._M_bucket_index(*__x_n); auto __prev_n = __other._M_buckets[__ybkt]; if (!__prev_n) return false; - for (__node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt);; + for (__node_ptr __n = static_cast<__node_ptr>(__prev_n->_M_nxt);; __n = __n->_M_next()) { - if (__n->_M_v() == *__itx) + if (__n->_M_v() == __x_n->_M_v()) break; if (!__n->_M_nxt @@ -1861,31 +1861,32 @@ namespace __detail _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits, false>:: _M_equal(const __hashtable& __other) const { - using __node_type = typename __hashtable::__node_type; + using __node_ptr = typename __hashtable::__node_ptr; + using const_iterator = typename __hashtable::const_iterator; const __hashtable* __this = static_cast(this); if (__this->size() != __other.size()) return false; - for (auto __itx = __this->begin(); __itx != __this->end();) + for (auto __x_n = __this->_M_begin(); __x_n;) { std::size_t __x_count = 1; - auto __itx_end = __itx; - for (++__itx_end; __itx_end != __this->end() - && __this->key_eq()(_ExtractKey{}(*__itx), - _ExtractKey{}(*__itx_end)); - ++__itx_end) + auto __x_n_end = __x_n->_M_next(); + for (; __x_n_end + && __this->key_eq()(_ExtractKey{}(__x_n->_M_v()), + _ExtractKey{}(__x_n_end->_M_v())); + __x_n_end = __x_n_end->_M_next()) ++__x_count; - std::size_t __ybkt = __other._M_bucket_index(*__itx._M_cur); + std::size_t __ybkt = __other._M_bucket_index(*__x_n); auto __y_prev_n = __other._M_buckets[__ybkt]; if (!__y_prev_n) return false; - __node_type* __y_n = static_cast<__node_type*>(__y_prev_n->_M_nxt); + __node_ptr __y_n = static_cast<__node_ptr>(__y_prev_n->_M_nxt); for (;;) { if (__this->key_eq()(_ExtractKey{}(__y_n->_M_v()), - _ExtractKey{}(*__itx))) + _ExtractKey{}(__x_n->_M_v()))) break; auto __y_ref_n = __y_n; @@ -1897,18 +1898,20 @@ namespace __detail return false; } - typename __hashtable::const_iterator __ity(__y_n); - for (auto __ity_end = __ity; __ity_end != __other.end(); ++__ity_end) + auto __y_n_end = __y_n; + for (; __y_n_end; __y_n_end = __y_n_end->_M_next()) if (--__x_count == 0) break; if (__x_count != 0) return false; + const_iterator __itx(__x_n), __itx_end(__x_n_end); + const_iterator __ity(__y_n); if (!std::is_permutation(__itx, __itx_end, __ity)) return false; - __itx = __itx_end; + __x_n = __x_n_end; } return true; } -- cgit v1.1 From af595613acbd9863198ae69c7b1c9e856bca9e4f Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 10 May 2023 12:20:58 +0100 Subject: libstdc++: Fix std::abs(__float128) for -NaN and -0.0 [PR109758] The current implementation of this non-standard overload of std::abs incorrectly returns a negative value for negative NaNs and negative zero, because x < 0 is false in both cases. Use fabsl(long double) or fabsf128(_Float128) if those do the right thing. Otherwise, use __builtin_signbit(x) instead of x < 0 to detect negative inputs. This assumes that __builtin_signbit handles __float128 correctly, but that seems to be true for all of GCC, clang and icc. libstdc++-v3/ChangeLog: PR libstdc++/109758 * include/bits/std_abs.h (abs(__float128)): Handle negative NaN and negative zero correctly. * testsuite/26_numerics/headers/cmath/109758.cc: New test. --- libstdc++-v3/include/bits/std_abs.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/std_abs.h b/libstdc++-v3/include/bits/std_abs.h index 1bb7ffbc..c70c8e4 100644 --- a/libstdc++-v3/include/bits/std_abs.h +++ b/libstdc++-v3/include/bits/std_abs.h @@ -135,11 +135,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __extension__ inline _GLIBCXX_CONSTEXPR __float128 abs(__float128 __x) - { return __x < 0 ? -__x : __x; } + { +#if defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) + return __builtin_fabsl(__x); +#elif defined(_GLIBCXX_HAVE_FLOAT128_MATH) + return __builtin_fabsf128(__x); +#else + // Assume that __builtin_signbit works for __float128. + return __builtin_signbit(__x) ? -__x : __x; +#endif + } #endif _GLIBCXX_END_NAMESPACE_VERSION } // namespace -} // extern "C"++" +} // extern "C++" #endif // _GLIBCXX_BITS_STD_ABS_H -- cgit v1.1 From c62e945492afbbd2a09896fc7b0b07f7e719a606 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 10 May 2023 21:30:10 +0100 Subject: libstdc++: Enforce value_type consistency in strings and streams P1463R1 made it ill-formed for allocator-aware containers (including std::basic_string) to use an allocator that has a different value_type from the container itself. We already enforce that for other containers (since r8-4828-g866e4d3853ccc0), but not for std::basic_string. We traditionally accepted it as an extension and rebound the allocator, so this change only adds the enforcement for C++20 and later. Similarly, P1148R0 made it ill-formed for strings and streams to use a traits type that has an incorrect char_type. We already enforce that for std::basic_string_view, so we just need to add it to std::basic_ios and std::basic_string. The assertion for the allocator's value_type caused some testsuite regressions: FAIL: 21_strings/basic_string/cons/char/deduction.cc (test for excess errors) FAIL: 21_strings/basic_string/cons/wchar_t/deduction.cc (test for excess errors) FAIL: 21_strings/basic_string/requirements/explicit_instantiation/debug.cc (test for excess errors) FAIL: 21_strings/basic_string/requirements/explicit_instantiation/int.cc (test for excess errors) The last two are testing the traditional extension that rebinds the allocator, so need to be disabled for C++20. The first two are similar to LWG 3076 where an incorrect constructor is considered for CTAD. In this case, determining that it's not viable requires instantiating std::basic_string, Alloc> which then fails the new assertion, because Alloc::value_type is not the same as Iter. This is only a problem because the size_type parameter of the non-viable constructor is an alias for _Alloc_traits_impl::size_type which is a nested type, and so the enclosing basic_string specialization needs to be instantiated. If we remove the _Alloc_traits_impl wrapper that was added in r12-5413-g2d76292bd6719d, then the definition of size_type no longer depends on basic_string, and we don't instantiate an invalid specialization and don't fail the assertion. The work done by _Alloc_traits_impl::allocate can be done in a _S_allocate function instead, which is probably more efficient to compile anyway. libstdc++-v3/ChangeLog: * config/abi/pre/gnu.ver: Export basic_string::_S_allocate. * include/bits/basic_ios.h: Add static assertion checking traits_type::value_type. * include/bits/basic_string.h: Likewise. Do not rebind allocator, and add static assertion checking its value_type. (basic_string::_Alloc_traits_impl): Remove class template. (basic_string::_S_allocate): New static member function. (basic_string::assign): Use _S_allocate. * include/bits/basic_string.tcc (basic_string::_M_create) (basic_string::reserve, basic_string::_M_replace): Likewise. * testsuite/21_strings/basic_string/requirements/explicit_instantiation/debug.cc: Disable for C++20 and later. * testsuite/21_strings/basic_string/requirements/explicit_instantiation/int.cc: Likweise. --- libstdc++-v3/include/bits/basic_ios.h | 4 +++ libstdc++-v3/include/bits/basic_string.h | 53 +++++++++++++----------------- libstdc++-v3/include/bits/basic_string.tcc | 8 ++--- 3 files changed, 30 insertions(+), 35 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/basic_ios.h b/libstdc++-v3/include/bits/basic_ios.h index de5719c..c7c391c 100644 --- a/libstdc++-v3/include/bits/basic_ios.h +++ b/libstdc++-v3/include/bits/basic_ios.h @@ -66,6 +66,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template class basic_ios : public ios_base { +#if __cplusplus >= 202002L + static_assert(is_same_v<_CharT, typename _Traits::char_type>); +#endif + public: ///@{ /** diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index b16b289..d15f0f0 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -86,39 +86,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 template class basic_string { +#if __cplusplus >= 202002L + static_assert(is_same_v<_CharT, typename _Traits::char_type>); + static_assert(is_same_v<_CharT, typename _Alloc::value_type>); + using _Char_alloc_type = _Alloc; +#else typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template rebind<_CharT>::other _Char_alloc_type; +#endif -#if __cpp_lib_constexpr_string < 201907L typedef __gnu_cxx::__alloc_traits<_Char_alloc_type> _Alloc_traits; -#else - template - struct _Alloc_traits_impl : __gnu_cxx::__alloc_traits<_Char_alloc_type> - { - typedef __gnu_cxx::__alloc_traits<_Char_alloc_type> _Base; - - [[__gnu__::__always_inline__]] - static constexpr typename _Base::pointer - allocate(_Char_alloc_type& __a, typename _Base::size_type __n) - { - pointer __p = _Base::allocate(__a, __n); - if (std::is_constant_evaluated()) - // Begin the lifetime of characters in allocated storage. - for (size_type __i = 0; __i < __n; ++__i) - std::construct_at(__builtin_addressof(__p[__i])); - return __p; - } - }; - - template - struct _Alloc_traits_impl, _Dummy_for_PR85282> - : __gnu_cxx::__alloc_traits<_Char_alloc_type> - { - // std::char_traits begins the lifetime of characters. - }; - - using _Alloc_traits = _Alloc_traits_impl<_Traits, void>; -#endif // Types: public: @@ -149,6 +126,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #endif private: + static _GLIBCXX20_CONSTEXPR pointer + _S_allocate(_Char_alloc_type& __a, size_type __n) + { + pointer __p = _Alloc_traits::allocate(__a, __n); +#if __cpp_lib_constexpr_string >= 201907L + // std::char_traits begins the lifetime of characters, + // but custom traits might not, so do it here. + if constexpr (!is_same_v<_Traits, char_traits<_CharT>>) + if (std::__is_constant_evaluated()) + // Begin the lifetime of characters in allocated storage. + for (size_type __i = 0; __i < __n; ++__i) + std::construct_at(__builtin_addressof(__p[__i])); +#endif + return __p; + } + #if __cplusplus >= 201703L // A helper type for avoiding boiler-plate. typedef basic_string_view<_CharT, _Traits> __sv_type; @@ -1596,7 +1589,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 const auto __len = __str.size(); auto __alloc = __str._M_get_allocator(); // If this allocation throws there are no effects: - auto __ptr = _Alloc_traits::allocate(__alloc, __len + 1); + auto __ptr = _S_allocate(__alloc, __len + 1); _M_destroy(_M_allocated_capacity); _M_data(__ptr); _M_capacity(__len); diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc index 99fdbee..d8a279f 100644 --- a/libstdc++-v3/include/bits/basic_string.tcc +++ b/libstdc++-v3/include/bits/basic_string.tcc @@ -152,7 +152,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // NB: Need an array of char_type[__capacity], plus a terminating // null char_type() element. - return _Alloc_traits::allocate(_M_get_allocator(), __capacity + 1); + return _S_allocate(_M_get_allocator(), __capacity + 1); } // NB: This is the special case for Input Iterators, used in @@ -376,8 +376,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION else if (__length < __capacity) try { - pointer __tmp - = _Alloc_traits::allocate(_M_get_allocator(), __length + 1); + pointer __tmp = _S_allocate(_M_get_allocator(), __length + 1); this->_S_copy(__tmp, _M_data(), __length + 1); _M_dispose(); _M_data(__tmp); @@ -521,8 +520,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cpp_lib_is_constant_evaluated if (std::is_constant_evaluated()) { - auto __newp = _Alloc_traits::allocate(_M_get_allocator(), - __new_size); + auto __newp = _S_allocate(_M_get_allocator(), __new_size); _S_copy(__newp, this->_M_data(), __pos); _S_copy(__newp + __pos, __s, __len2); _S_copy(__newp + __pos + __len2, __p + __len1, __how_much); -- cgit v1.1 From aa39ed4467db0cf18f300fcf475e09c4496527cf Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 10 May 2023 16:15:03 +0100 Subject: libstdc++: Fix chrono::hh_mm_ss::subseconds() [PR109772] I borked the logic in r13-4526-g5329e1a8e1480d so that the selected partial specialization of hh_mm_ss::__subseconds might not be able to represent the correct number of subseconds. This can result in a truncated value being stored for the subseconds, e.g., 4755859375 gets truncated to 460892079 because the correct value doesn't fit in uint_least32_t. Instead of checking whether the maximum value of the incoming duration type can be represented, we would need to check whether that maximum value can be represented after being converted to the correct precision type: template static constexpr bool __fits = duration_cast(_Duration::max()).count() <= duration_values<_Tp>::max(); However, this can fail to compile, due to integer overflow in the constexpr multiplications. Instead, we could limit the check to the case where the incoming duration has the same period as the precision, where no conversion is needed and so no overflow can happen. But that seems of very limited value, as it would only benefit specializations like hh_mm_ss>, which can only represent a time-of-day between -00:00:00.0215 and +00:00:00.0215 measured in picoseconds! Additionally, the hh_mm_ss::__subseconds partial specializations do not have disjoint constraints, so that some hh_mm_ss specializations result in ambiguities tying to match a __subseconds partial specialization. The most practical fix is to just stop using the __fits variable template in the constraints of the partial specializations. This fixes the truncated values by not selecting an inappropriate partial specialization, and fixes the ambiguous match by ensuring the constraints are disjoint. Fixing this changes the layout of some specializations, so is an ABI change. It only affects specializations that have a small (less than 64-bit) representation type and either a very small period (e.g. like the picosecond specialization above) or a non-power-of-ten period like ratio<1, 1024>. For example both hh_mm_ss> and hh_mm_ss> are affected (increasing from 16 bytes to 24 on x86_64), but hh_mm_ss> and hh_mm_ss> are not affected. libstdc++-v3/ChangeLog: PR libstdc++/109772 * include/std/chrono (hh_mm_ss::__fits): Remove variable template. (hh_mm_ss::__subseconds): Remove __fits from constraints. * testsuite/std/time/hh_mm_ss/109772.cc: New test. * testsuite/std/time/hh_mm_ss/1.cc: Adjust expected size for hh_mm_ss>. --- libstdc++-v3/include/std/chrono | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono index 7bfc9b79..660e8d2 100644 --- a/libstdc++-v3/include/std/chrono +++ b/libstdc++-v3/include/std/chrono @@ -2398,17 +2398,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return {}; } }; - // True if the maximum constructor argument can be represented in _Tp. - template - static constexpr bool __fits - = duration_values::max() - <= duration_values<_Tp>::max(); - template requires (!treat_as_floating_point_v<_Rep>) && ratio_less_v<_Period, ratio<1, 1>> - && (ratio_greater_equal_v<_Period, ratio<1, 250>> - || __fits) + && ratio_greater_equal_v<_Period, ratio<1, 250>> struct __subseconds> { unsigned char _M_r{}; @@ -2421,8 +2414,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template requires (!treat_as_floating_point_v<_Rep>) && ratio_less_v<_Period, ratio<1, 250>> - && (ratio_greater_equal_v<_Period, ratio<1, 4000000000>> - || __fits) + && ratio_greater_equal_v<_Period, ratio<1, 4000000000>> struct __subseconds> { uint_least32_t _M_r{}; -- cgit v1.1 From 6d664515720bb277d49eb1457477a9d88f4ba5ed Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 12 May 2023 13:55:17 +0100 Subject: libstdc++: Remove dependency on _GLIBCXX_USE_C99_STDINT_TR1 Since r9-2028-g8ba7f29e3dd064 we've defined most of unconditionally, including uint_least32_t. This means that all of can be defined unconditionally, which means that std::shuffle and std::ranges::shuffle can be too. libstdc++-v3/ChangeLog: * include/bits/algorithmfwd.h (shuffle): Do not depend on _GLIBCXX_USE_C99_STDINT_TR1. * include/bits/ranges_algo.h (shuffle): Likewise. * include/bits/stl_algo.h (shuffle): Likewise. * include/ext/random: Likewise. * include/ext/throw_allocator.h (random_condition): Likewise. * include/std/random: Likewise. * src/c++11/cow-string-inst.cc: Likewise. * src/c++11/random.cc: Likewise. --- libstdc++-v3/include/bits/algorithmfwd.h | 2 +- libstdc++-v3/include/bits/ranges_algo.h | 2 -- libstdc++-v3/include/bits/stl_algo.h | 3 --- libstdc++-v3/include/ext/random | 4 ++-- libstdc++-v3/include/ext/throw_allocator.h | 8 -------- libstdc++-v3/include/std/random | 7 +------ 6 files changed, 4 insertions(+), 22 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/algorithmfwd.h b/libstdc++-v3/include/bits/algorithmfwd.h index 03e6278..0d62390 100644 --- a/libstdc++-v3/include/bits/algorithmfwd.h +++ b/libstdc++-v3/include/bits/algorithmfwd.h @@ -622,7 +622,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) // set_symmetric_difference // set_union -#if (__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99_STDINT_TR1) +#if __cplusplus >= 201103L template void shuffle(_RAIter, _RAIter, _UGenerator&&); diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h index 410d3ae..da66ff8 100644 --- a/libstdc++-v3/include/bits/ranges_algo.h +++ b/libstdc++-v3/include/bits/ranges_algo.h @@ -1564,7 +1564,6 @@ namespace ranges inline constexpr __sample_fn sample{}; -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 struct __shuffle_fn { template _Sent, @@ -1591,7 +1590,6 @@ namespace ranges }; inline constexpr __shuffle_fn shuffle{}; -#endif struct __push_heap_fn { diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h index 3d37091..5469549 100644 --- a/libstdc++-v3/include/bits/stl_algo.h +++ b/libstdc++-v3/include/bits/stl_algo.h @@ -3692,7 +3692,6 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) #endif // C++17 #endif // C++14 -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 /** * @brief Generate two uniformly distributed integers using a * single distribution invocation. @@ -3803,8 +3802,6 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) std::iter_swap(__i, __first + __d(__g, __p_type(0, __i - __first))); } -#endif // USE C99_STDINT - #endif // C++11 _GLIBCXX_BEGIN_NAMESPACE_ALGO diff --git a/libstdc++-v3/include/ext/random b/libstdc++-v3/include/ext/random index 795c3c5..62acb67 100644 --- a/libstdc++-v3/include/ext/random +++ b/libstdc++-v3/include/ext/random @@ -45,7 +45,7 @@ # include #endif -#if defined(_GLIBCXX_USE_C99_STDINT_TR1) && defined(UINT32_C) +#ifdef UINT32_C namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { @@ -3923,7 +3923,7 @@ _GLIBCXX_END_NAMESPACE_VERSION #include #include -#endif // _GLIBCXX_USE_C99_STDINT_TR1 && UINT32_C +#endif // UINT32_C #endif // C++11 diff --git a/libstdc++-v3/include/ext/throw_allocator.h b/libstdc++-v3/include/ext/throw_allocator.h index 0dbf001..71b7198 100644 --- a/libstdc++-v3/include/ext/throw_allocator.h +++ b/libstdc++-v3/include/ext/throw_allocator.h @@ -495,7 +495,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } }; -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 /** * @brief Base class for random probability control and throw. */ @@ -613,7 +612,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return _S_e; } }; -#endif // _GLIBCXX_USE_C99_STDINT_TR1 /** * @brief Class with exception generation control. Intended to be @@ -769,7 +767,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif }; -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 /// Type throwing via random condition. struct throw_value_random : public throw_value_base { @@ -800,7 +797,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator=(throw_value_random&&) = default; #endif }; -#endif // _GLIBCXX_USE_C99_STDINT_TR1 /** * @brief Allocator class with logging and exception generation control. @@ -947,7 +943,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif }; -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 /// Allocator throwing via random condition. template struct throw_allocator_random @@ -973,7 +968,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator=(const throw_allocator_random&) = default; #endif }; -#endif // _GLIBCXX_USE_C99_STDINT_TR1 _GLIBCXX_END_NAMESPACE_VERSION } // namespace @@ -1002,7 +996,6 @@ namespace std _GLIBCXX_VISIBILITY(default) } }; -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 /// Explicit specialization of std::hash for __gnu_cxx::throw_value_random. template<> struct hash<__gnu_cxx::throw_value_random> @@ -1017,7 +1010,6 @@ namespace std _GLIBCXX_VISIBILITY(default) return __result; } }; -#endif #pragma GCC diagnostic pop } // end namespace std diff --git a/libstdc++-v3/include/std/random b/libstdc++-v3/include/std/random index e6591bc..a0785a4 100644 --- a/libstdc++-v3/include/std/random +++ b/libstdc++-v3/include/std/random @@ -38,22 +38,17 @@ #else #include +#include // For uint_fast32_t, uint_fast64_t, uint_least32_t #include #include #include #include #include #include - -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 - -#include // For uint_fast32_t, uint_fast64_t, uint_least32_t #include #include #include -#endif // _GLIBCXX_USE_C99_STDINT_TR1 - #endif // C++11 #endif // _GLIBCXX_RANDOM -- cgit v1.1 From 0b6aebf7bbe1256d8d9ace7e4e44c7b032e8592b Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 12 May 2023 14:04:04 +0100 Subject: libstdc++: Reduce dependency on _GLIBCXX_USE_C99_STDINT_TR1 Since r9-2028-g8ba7f29e3dd064 we've defined most of unconditionally, so we can do the same for most of the std::atomic aliases such as std::atomic_int_least32_t. The only aliases that need to depend on _GLIBCXX_USE_C99_STDINT_TR1 are the ones for the integer types that are not guaranteed to be defined, e.g. std::atomic_int32_t. libstdc++-v3/ChangeLog: * include/std/atomic (atomic_int_least8_t, atomic_uint_least8_t) (atomic_int_least16_t, atomic_uint_least16_t) (atomic_int_least32_t, atomic_uint_least32_t) (atomic_int_least64_t, atomic_uint_least64_t) (atomic_int_fast16_t, atomic_uint_fast16_t) (atomic_int_fast32_t, atomic_uint_fast32_t) (atomic_int_fast64_t, atomic_uint_fast64_t) (atomic_intmax_t, atomic_uintmax_t): Define unconditionally. * testsuite/29_atomics/headers/stdatomic.h/c_compat.cc: Adjust. --- libstdc++-v3/include/std/atomic | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/std/atomic b/libstdc++-v3/include/std/atomic index 96e87de..b502027 100644 --- a/libstdc++-v3/include/std/atomic +++ b/libstdc++-v3/include/std/atomic @@ -1130,7 +1130,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// atomic_uint64_t typedef atomic atomic_uint64_t; - +#endif /// atomic_int_least8_t typedef atomic atomic_int_least8_t; @@ -1180,7 +1180,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// atomic_uint_fast64_t typedef atomic atomic_uint_fast64_t; -#endif /// atomic_intptr_t @@ -1195,13 +1194,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// atomic_ptrdiff_t typedef atomic atomic_ptrdiff_t; -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 /// atomic_intmax_t typedef atomic atomic_intmax_t; /// atomic_uintmax_t typedef atomic atomic_uintmax_t; -#endif // Function definitions, atomic_flag operations. inline bool -- cgit v1.1 From 1f973c295b699011acd7d5fcb04bd2bf887da16d Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 12 May 2023 14:25:50 +0100 Subject: libstdc++: Remove redundant dependencies on _GLIBCXX_USE_C99_STDINT_TR1 We never need to use std::make_unsigned in std::char_traits and std::char_traits because guarantees to provide the types we need, since r9-2028-g8ba7f29e3dd064. Similarly, experimental::source_location can just assume uint_least32_t is defined by . libstdc++-v3/ChangeLog: * include/bits/char_traits.h (char_traits): Do not depend on _GLIBCXX_USE_C99_STDINT_TR1. (char_traits): Likewise. * include/experimental/source_location: Likewise. --- libstdc++-v3/include/bits/char_traits.h | 8 ++------ libstdc++-v3/include/experimental/source_location | 6 ------ 2 files changed, 2 insertions(+), 12 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h index 68ed827..0928137 100644 --- a/libstdc++-v3/include/bits/char_traits.h +++ b/libstdc++-v3/include/bits/char_traits.h @@ -762,10 +762,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef char16_t char_type; #ifdef __UINT_LEAST16_TYPE__ typedef __UINT_LEAST16_TYPE__ int_type; -#elif defined _GLIBCXX_USE_C99_STDINT_TR1 - typedef uint_least16_t int_type; #else - typedef make_unsigned::type int_type; + typedef uint_least16_t int_type; #endif #if _GLIBCXX_HOSTED typedef streamoff off_type; @@ -891,10 +889,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef char32_t char_type; #ifdef __UINT_LEAST32_TYPE__ typedef __UINT_LEAST32_TYPE__ int_type; -#elif defined _GLIBCXX_USE_C99_STDINT_TR1 - typedef uint_least32_t int_type; #else - typedef make_unsigned::type int_type; + typedef uint_least32_t int_type; #endif #if _GLIBCXX_HOSTED typedef streamoff off_type; diff --git a/libstdc++-v3/include/experimental/source_location b/libstdc++-v3/include/experimental/source_location index 1dfce73..ee94a36 100644 --- a/libstdc++-v3/include/experimental/source_location +++ b/libstdc++-v3/include/experimental/source_location @@ -44,12 +44,6 @@ inline namespace fundamentals_v2 { struct source_location { -#ifndef _GLIBCXX_USE_C99_STDINT_TR1 - private: - using uint_least32_t = unsigned; - public: -#endif - // 14.1.2, source_location creation static constexpr source_location current(const char* __file = __builtin_FILE(), -- cgit v1.1 From 0d76fb1582c1fc38e4f214b90f42f9536e071342 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 12 May 2023 12:44:03 +0100 Subject: libstdc++: Stop using _GLIBCXX_USE_C99_COMPLEX_TR1 in The _GLIBCXX_USE_C99_COMPLEX_TR1 macro (and the comments about it in acinclude.m4 and config.h) are misleading when it is also used for , not only . It is also wrong, because the configure checks for TR1 use -std=c++98 and a target might define cacos etc. for C++11 but not for C++98. Add a separate configure check for the inverse trigonometric functions that are covered by _GLIBCXX_USE_C99_COMPLEX_TR1, but using -std=c++11 for the checks. Use the result of that separate check in . libstdc++-v3/ChangeLog: * acinclude.m4 (GLIBCXX_USE_C99): Check for complex inverse trig functions in C++11 mode and define _GLIBCXX_USE_C99_COMPLEX_ARC. * config.h.in: Regenerate. * configure: Regenerate. * doc/doxygen/user.cfg.in (PREDEFINED): Add new macro. * include/std/complex: Check _GLIBCXX_USE_C99_COMPLEX_ARC instead of _GLIBCXX_USE_C99_COMPLEX_TR1. --- libstdc++-v3/include/std/complex | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex index 0f5f14c..40fc062 100644 --- a/libstdc++-v3/include/std/complex +++ b/libstdc++-v3/include/std/complex @@ -2021,7 +2021,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return std::complex<_Tp>(__pi_2 - __t.real(), -__t.imag()); } -#if _GLIBCXX_USE_C99_COMPLEX_TR1 +#if _GLIBCXX_USE_C99_COMPLEX_ARC #if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) inline __complex__ _Float16 __complex_acos(__complex__ _Float16 __z) @@ -2177,7 +2177,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif #endif -#if _GLIBCXX_USE_C99_COMPLEX_TR1 +#if _GLIBCXX_USE_C99_COMPLEX_ARC inline __complex__ float __complex_acos(__complex__ float __z) { return __builtin_cacosf(__z); } @@ -2213,7 +2213,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return std::complex<_Tp>(__t.imag(), -__t.real()); } -#if _GLIBCXX_USE_C99_COMPLEX_TR1 +#if _GLIBCXX_USE_C99_COMPLEX_ARC inline __complex__ float __complex_asin(__complex__ float __z) { return __builtin_casinf(__z); } @@ -2257,7 +2257,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Tp(0.25) * log(__num / __den)); } -#if _GLIBCXX_USE_C99_COMPLEX_TR1 +#if _GLIBCXX_USE_C99_COMPLEX_ARC inline __complex__ float __complex_atan(__complex__ float __z) { return __builtin_catanf(__z); } @@ -2293,7 +2293,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION + std::sqrt(_Tp(0.5) * (__z - _Tp(1.0)))); } -#if _GLIBCXX_USE_C99_COMPLEX_TR1 +#if _GLIBCXX_USE_C99_COMPLEX_ARC inline __complex__ float __complex_acosh(__complex__ float __z) { return __builtin_cacoshf(__z); } @@ -2332,7 +2332,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return std::log(__t + __z); } -#if _GLIBCXX_USE_C99_COMPLEX_TR1 +#if _GLIBCXX_USE_C99_COMPLEX_ARC inline __complex__ float __complex_asinh(__complex__ float __z) { return __builtin_casinhf(__z); } @@ -2376,7 +2376,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Tp(0.5) * atan2(_Tp(2.0) * __z.imag(), __x)); } -#if _GLIBCXX_USE_C99_COMPLEX_TR1 +#if _GLIBCXX_USE_C99_COMPLEX_ARC inline __complex__ float __complex_atanh(__complex__ float __z) { return __builtin_catanhf(__z); } -- cgit v1.1 From 5baabdb15d0ee24da414f273a5bafd5eca262ede Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 12 May 2023 18:53:55 +0100 Subject: libstdc++: Stop using _GLIBCXX_USE_C99_STDINT_TR1 in The _GLIBCXX_USE_C99_STDINT_TR1 macro (and the comments about it in acinclude.m4 and config.h) are misleading when it is also used for , not only . It is also wrong, because the configure checks for TR1 use -std=c++98 and a target might define uint32_t etc. for C++11 but not for C++98. Add a separate configure check for the types using -std=c++11 for the checks. Use the result of that separate check in and most other places that still depend on the macro (many uses of that macro have been removed already). The remaining uses of the STDINT_TR1 macro are really for TR1, or are in the src/c++11/compatibility-*.cc files, where we don't want/need to change the condition they depend on (if those symbols were only exported when types were available for -std=c++98, then that's the condition we should continue to use for whether to export the compat symbols now). Make similar changes for the related _GLIBCXX_USE_C99_INTTYPES_TR1 and _GLIBCXX_USE_C99_INTTYPES_WCHAR_T_TR1 macros, adding new macros for non-TR1 uses. libstdc++-v3/ChangeLog: * acinclude.m4 (GLIBCXX_USE_C99): Check for types in C++11 mode and define _GLIBCXX_USE_C99_STDINT. Check for features in C++11 mode and define _GLIBCXX_USE_C99_INTTYPES and _GLIBCXX_USE_C99_INTTYPES_WCHAR_T. * config.h.in: Regenerate. * configure: Regenerate. * doc/doxygen/user.cfg.in (PREDEFINED): Add new macros. * include/bits/chrono.h: Check _GLIBCXX_USE_C99_STDINT instead of _GLIBCXX_USE_C99_STDINT_TR1. * include/c_compatibility/inttypes.h: Check _GLIBCXX_USE_C99_INTTYPES and _GLIBCXX_USE_C99_INTTYPES_WCHAR_T instead of _GLIBCXX_USE_C99_INTTYPES_TR1 and _GLIBCXX_USE_C99_INTTYPES_WCHAR_T_TR1. * include/c_compatibility/stdatomic.h: Check _GLIBCXX_USE_C99_STDINT instead of _GLIBCXX_USE_C99_STDINT_TR1. * include/c_compatibility/stdint.h: Likewise. * include/c_global/cinttypes: Check _GLIBCXX_USE_C99_INTTYPES and _GLIBCXX_USE_C99_INTTYPES_WCHAR_T instead of _GLIBCXX_USE_C99_INTTYPES_TR1 and _GLIBCXX_USE_C99_INTTYPES_WCHAR_T_TR1. * include/c_global/cstdint: Check _GLIBCXX_USE_C99_STDINT instead of _GLIBCXX_USE_C99_STDINT_TR1. * include/std/atomic: Likewise. * src/c++11/cow-stdexcept.cc: Likewise. * testsuite/29_atomics/headers/stdatomic.h/c_compat.cc: Likewise. * testsuite/lib/libstdc++.exp (check_v3_target_cstdint): Likewise. --- libstdc++-v3/include/bits/chrono.h | 2 +- libstdc++-v3/include/c_compatibility/inttypes.h | 6 +++--- libstdc++-v3/include/c_compatibility/stdatomic.h | 4 ++-- libstdc++-v3/include/c_compatibility/stdint.h | 4 ++-- libstdc++-v3/include/c_global/cinttypes | 6 +++--- libstdc++-v3/include/c_global/cstdint | 6 +++--- libstdc++-v3/include/std/atomic | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/chrono.h b/libstdc++-v3/include/bits/chrono.h index fb99fe5..81b92d7 100644 --- a/libstdc++-v3/include/bits/chrono.h +++ b/libstdc++-v3/include/bits/chrono.h @@ -884,7 +884,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// @} /// @cond undocumented -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 +#ifdef _GLIBCXX_USE_C99_STDINT # define _GLIBCXX_CHRONO_INT64_T int64_t #elif defined __INT64_TYPE__ # define _GLIBCXX_CHRONO_INT64_T __INT64_TYPE__ diff --git a/libstdc++-v3/include/c_compatibility/inttypes.h b/libstdc++-v3/include/c_compatibility/inttypes.h index 9c2b7d6..070fcbc 100644 --- a/libstdc++-v3/include/c_compatibility/inttypes.h +++ b/libstdc++-v3/include/c_compatibility/inttypes.h @@ -48,7 +48,7 @@ # endif # endif -#ifdef _GLIBCXX_USE_C99_INTTYPES_TR1 +#ifdef _GLIBCXX_USE_C99_INTTYPES namespace std { @@ -72,13 +72,13 @@ namespace std using ::strtoimax; using ::strtoumax; -#if defined(_GLIBCXX_USE_WCHAR_T) && _GLIBCXX_USE_C99_INTTYPES_WCHAR_T_TR1 +#if defined(_GLIBCXX_USE_WCHAR_T) && _GLIBCXX_USE_C99_INTTYPES_WCHAR_T using ::wcstoimax; using ::wcstoumax; #endif } // namespace -#endif _GLIBCXX_USE_C99_INTTYPES_TR1 +#endif _GLIBCXX_USE_C99_INTTYPES #else diff --git a/libstdc++-v3/include/c_compatibility/stdatomic.h b/libstdc++-v3/include/c_compatibility/stdatomic.h index b565a1c..0b63326 100644 --- a/libstdc++-v3/include/c_compatibility/stdatomic.h +++ b/libstdc++-v3/include/c_compatibility/stdatomic.h @@ -62,7 +62,7 @@ using std::atomic_char8_t; using std::atomic_char16_t; using std::atomic_char32_t; using std::atomic_wchar_t; -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 +#ifdef _GLIBCXX_USE_C99_STDINT using std::atomic_int8_t; using std::atomic_uint8_t; using std::atomic_int16_t; @@ -92,7 +92,7 @@ using std::atomic_intptr_t; using std::atomic_uintptr_t; using std::atomic_size_t; using std::atomic_ptrdiff_t; -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 +#ifdef _GLIBCXX_USE_C99_STDINT using std::atomic_intmax_t; using std::atomic_uintmax_t; #endif diff --git a/libstdc++-v3/include/c_compatibility/stdint.h b/libstdc++-v3/include/c_compatibility/stdint.h index c264e97..85948a5 100644 --- a/libstdc++-v3/include/c_compatibility/stdint.h +++ b/libstdc++-v3/include/c_compatibility/stdint.h @@ -56,7 +56,7 @@ # endif # endif -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 +#ifdef _GLIBCXX_USE_C99_STDINT namespace std { @@ -97,7 +97,7 @@ namespace std using ::uintptr_t; } // namespace -#endif // _GLIBCXX_USE_C99_STDINT_TR1 +#endif // _GLIBCXX_USE_C99_STDINT #else diff --git a/libstdc++-v3/include/c_global/cinttypes b/libstdc++-v3/include/c_global/cinttypes index 8a9de63..06fc34d 100644 --- a/libstdc++-v3/include/c_global/cinttypes +++ b/libstdc++-v3/include/c_global/cinttypes @@ -50,7 +50,7 @@ # endif #endif -#ifdef _GLIBCXX_USE_C99_INTTYPES_TR1 +#ifdef _GLIBCXX_USE_C99_INTTYPES namespace std { @@ -68,13 +68,13 @@ namespace std using ::strtoimax; using ::strtoumax; -#if defined(_GLIBCXX_USE_WCHAR_T) && _GLIBCXX_USE_C99_INTTYPES_WCHAR_T_TR1 +#if defined(_GLIBCXX_USE_WCHAR_T) && _GLIBCXX_USE_C99_INTTYPES_WCHAR_T using ::wcstoimax; using ::wcstoumax; #endif } // namespace std -#endif // _GLIBCXX_USE_C99_INTTYPES_TR1 +#endif // _GLIBCXX_USE_C99_INTTYPES #endif // C++11 diff --git a/libstdc++-v3/include/c_global/cstdint b/libstdc++-v3/include/c_global/cstdint index 64e8574..97a30d5 100644 --- a/libstdc++-v3/include/c_global/cstdint +++ b/libstdc++-v3/include/c_global/cstdint @@ -47,7 +47,7 @@ namespace std { -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 +#ifdef _GLIBCXX_USE_C99_STDINT using ::int8_t; using ::int16_t; using ::int32_t; @@ -83,7 +83,7 @@ namespace std using ::uintmax_t; using ::uintptr_t; -#else // !_GLIBCXX_USE_C99_STDINT_TR1 +#else // !_GLIBCXX_USE_C99_STDINT using intmax_t = __INTMAX_TYPE__; using uintmax_t = __UINTMAX_TYPE__; @@ -138,7 +138,7 @@ namespace std using uintptr_t = __UINTPTR_TYPE__; #endif -#endif // _GLIBCXX_USE_C99_STDINT_TR1 +#endif // _GLIBCXX_USE_C99_STDINT } // namespace std #endif // C++11 diff --git a/libstdc++-v3/include/std/atomic b/libstdc++-v3/include/std/atomic index b502027..111df2a 100644 --- a/libstdc++-v3/include/std/atomic +++ b/libstdc++-v3/include/std/atomic @@ -1103,7 +1103,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// atomic_char32_t typedef atomic atomic_char32_t; -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 +#ifdef _GLIBCXX_USE_C99_STDINT // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2441. Exact-width atomic typedefs should be provided -- cgit v1.1 From ac3a5bbc62949aeb061c01360632b3b8f5fafefa Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 12 May 2023 21:36:56 +0100 Subject: libstdc++: Stop using TR1 macros in and As with the two commits before this, the _GLIBCXX_USE_C99_CTYPE_TR1 and _GLIBCXX_USE_C99_FENV_TR1 macros are misleading when they are also used for and , not only for TR1 headers. It is also wrong, because the configure checks for TR1 use -std=c++98 and a target might define the C99 features for C++11 but not for C++98. Add separate configure checks for the and features using -std=c++11 for the checks. Use the new macros defined by those checks in the C++11-specific parts of , , and . libstdc++-v3/ChangeLog: * acinclude.m4 (GLIBCXX_USE_C99): Check for isblank in C++11 mode and define _GLIBCXX_USE_C99_CTYPE. Check for functions in C++11 mode and define _GLIBCXX_USE_C99_FENV. * config.h.in: Regenerate. * configure: Regenerate. * include/c_compatibility/fenv.h: Check _GLIBCXX_USE_C99_FENV instead of _GLIBCXX_USE_C99_FENV_TR1. * include/c_global/cfenv: Likewise. * include/c_global/cctype: Check _GLIBCXX_USE_C99_CTYPE instead of _GLIBCXX_USE_C99_CTYPE_TR1. --- libstdc++-v3/include/c_compatibility/fenv.h | 4 ++-- libstdc++-v3/include/c_global/cctype | 4 ++-- libstdc++-v3/include/c_global/cfenv | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/c_compatibility/fenv.h b/libstdc++-v3/include/c_compatibility/fenv.h index 70ce3f8..83e930f 100644 --- a/libstdc++-v3/include/c_compatibility/fenv.h +++ b/libstdc++-v3/include/c_compatibility/fenv.h @@ -38,7 +38,7 @@ #if __cplusplus >= 201103L -#if _GLIBCXX_USE_C99_FENV_TR1 +#if _GLIBCXX_USE_C99_FENV #undef feclearexcept #undef fegetexceptflag @@ -74,7 +74,7 @@ namespace std using ::feupdateenv; } // namespace -#endif // _GLIBCXX_USE_C99_FENV_TR1 +#endif // _GLIBCXX_USE_C99_FENV #endif // C++11 diff --git a/libstdc++-v3/include/c_global/cctype b/libstdc++-v3/include/c_global/cctype index bd667fb..e6ff120 100644 --- a/libstdc++-v3/include/c_global/cctype +++ b/libstdc++-v3/include/c_global/cctype @@ -78,7 +78,7 @@ namespace std #if __cplusplus >= 201103L -#ifdef _GLIBCXX_USE_C99_CTYPE_TR1 +#ifdef _GLIBCXX_USE_C99_CTYPE #undef isblank @@ -87,7 +87,7 @@ namespace std using ::isblank; } // namespace std -#endif // _GLIBCXX_USE_C99_CTYPE_TR1 +#endif // _GLIBCXX_USE_C99_CTYPE #endif // C++11 diff --git a/libstdc++-v3/include/c_global/cfenv b/libstdc++-v3/include/c_global/cfenv index 6704dc5..3a1d9c4 100644 --- a/libstdc++-v3/include/c_global/cfenv +++ b/libstdc++-v3/include/c_global/cfenv @@ -41,7 +41,7 @@ # include #endif -#ifdef _GLIBCXX_USE_C99_FENV_TR1 +#ifdef _GLIBCXX_USE_C99_FENV #undef feclearexcept #undef fegetexceptflag @@ -77,7 +77,7 @@ namespace std using ::feupdateenv; } // namespace std -#endif // _GLIBCXX_USE_C99_FENV_TR1 +#endif // _GLIBCXX_USE_C99_FENV #endif // C++11 -- cgit v1.1 From 637edefc5863cf3b572c0c0bcd58fcc01ee60184 Mon Sep 17 00:00:00 2001 From: Ken Matsui Date: Thu, 23 Mar 2023 04:06:08 -0700 Subject: libstdc++: use __bool_constant instead of integral_constant In the type_traits header, both integral_constant and __bool_constant are used. This patch unifies those usages into __bool_constant. libstdc++-v3/ChangeLog: * include/std/type_traits: Use __bool_constant instead of integral_constant. Signed-off-by: Ken Matsui Reviewed-by: Jonathan Wakely Reviewed-by: Patrick Palka --- libstdc++-v3/include/std/type_traits | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 2bd607a..bc6982f 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -578,19 +578,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// is_enum template struct is_enum - : public integral_constant + : public __bool_constant<__is_enum(_Tp)> { }; /// is_union template struct is_union - : public integral_constant + : public __bool_constant<__is_union(_Tp)> { }; /// is_class template struct is_class - : public integral_constant + : public __bool_constant<__is_class(_Tp)> { }; /// is_function @@ -784,7 +784,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// is_trivial template struct is_trivial - : public integral_constant + : public __bool_constant<__is_trivial(_Tp)> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -793,7 +793,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// is_trivially_copyable template struct is_trivially_copyable - : public integral_constant + : public __bool_constant<__is_trivially_copyable(_Tp)> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -802,7 +802,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// is_standard_layout template struct is_standard_layout - : public integral_constant + : public __bool_constant<__is_standard_layout(_Tp)> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -817,7 +817,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct _GLIBCXX20_DEPRECATED_SUGGEST("is_standard_layout && is_trivial") is_pod - : public integral_constant + : public __bool_constant<__is_pod(_Tp)> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -831,7 +831,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct _GLIBCXX17_DEPRECATED is_literal_type - : public integral_constant + : public __bool_constant<__is_literal_type(_Tp)> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -840,13 +840,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// is_empty template struct is_empty - : public integral_constant + : public __bool_constant<__is_empty(_Tp)> { }; /// is_polymorphic template struct is_polymorphic - : public integral_constant + : public __bool_constant<__is_polymorphic(_Tp)> { }; #if __cplusplus >= 201402L @@ -855,14 +855,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// @since C++14 template struct is_final - : public integral_constant + : public __bool_constant<__is_final(_Tp)> { }; #endif /// is_abstract template struct is_abstract - : public integral_constant + : public __bool_constant<__is_abstract(_Tp)> { }; /// @cond undocumented @@ -873,7 +873,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct __is_signed_helper<_Tp, true> - : public integral_constant + : public __bool_constant<_Tp(-1) < _Tp(0)> { }; /// @endcond @@ -1333,7 +1333,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// has_virtual_destructor template struct has_virtual_destructor - : public integral_constant + : public __bool_constant<__has_virtual_destructor(_Tp)> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -1392,7 +1392,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct is_same #ifdef _GLIBCXX_HAVE_BUILTIN_IS_SAME - : public integral_constant + : public __bool_constant<__is_same(_Tp, _Up)> #else : public false_type #endif @@ -1408,7 +1408,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// is_base_of template struct is_base_of - : public integral_constant + : public __bool_constant<__is_base_of(_Base, _Derived)> { }; #if __has_builtin(__is_convertible) -- cgit v1.1 From ba490492e51834db645a3165d14f2ba0af62a8c7 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 16 May 2023 22:40:42 +0100 Subject: libstdc++: Implement LWG 3877 for std::expected monadic ops This was approved in Issaquah 2023. As well as fixing the value categories, this fixes the fact that we were incorrectly testing E instead of T in the or_else constraints. libstdc++-v3/ChangeLog: * include/std/expected (expected::and_then, expected::or_else) (expected::transform, expected::transform_error): Fix exception specifications as per LWG 3877. (expected::and_then, expected::transform): Likewise. * testsuite/20_util/expected/lwg3877.cc: New test. --- libstdc++-v3/include/std/expected | 48 +++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/std/expected b/libstdc++-v3/include/std/expected index c6d26b0..5ea0d6a 100644 --- a/libstdc++-v3/include/std/expected +++ b/libstdc++-v3/include/std/expected @@ -840,7 +840,7 @@ namespace __expected // monadic operations - template requires is_copy_constructible_v<_Er> + template requires is_constructible_v<_Er, _Er&> constexpr auto and_then(_Fn&& __f) & { @@ -854,7 +854,7 @@ namespace __expected return _Up(unexpect, error()); } - template requires is_copy_constructible_v<_Er> + template requires is_constructible_v<_Er, const _Er&> constexpr auto and_then(_Fn&& __f) const & { @@ -868,7 +868,7 @@ namespace __expected return _Up(unexpect, error()); } - template requires is_move_constructible_v<_Er> + template requires is_constructible_v<_Er, _Er> constexpr auto and_then(_Fn&& __f) && { @@ -883,7 +883,7 @@ namespace __expected } - template requires is_move_constructible_v<_Er> + template requires is_constructible_v<_Er, const _Er> constexpr auto and_then(_Fn&& __f) const && { @@ -897,7 +897,7 @@ namespace __expected return _Up(unexpect, std::move(error())); } - template requires is_copy_constructible_v<_Er> + template requires is_constructible_v<_Tp, _Tp&> constexpr auto or_else(_Fn&& __f) & { @@ -911,7 +911,7 @@ namespace __expected return std::__invoke(std::forward<_Fn>(__f), error()); } - template requires is_copy_constructible_v<_Er> + template requires is_constructible_v<_Tp, const _Tp&> constexpr auto or_else(_Fn&& __f) const & { @@ -926,7 +926,7 @@ namespace __expected } - template requires is_move_constructible_v<_Er> + template requires is_constructible_v<_Tp, _Tp> constexpr auto or_else(_Fn&& __f) && { @@ -940,7 +940,7 @@ namespace __expected return std::__invoke(std::forward<_Fn>(__f), std::move(error())); } - template requires is_move_constructible_v<_Er> + template requires is_constructible_v<_Tp, const _Tp> constexpr auto or_else(_Fn&& __f) const && { @@ -954,7 +954,7 @@ namespace __expected return std::__invoke(std::forward<_Fn>(__f), std::move(error())); } - template requires is_copy_constructible_v<_Er> + template requires is_constructible_v<_Er, _Er&> constexpr auto transform(_Fn&& __f) & { @@ -970,7 +970,7 @@ namespace __expected return _Res(unexpect, std::move(error())); } - template requires is_copy_constructible_v<_Er> + template requires is_constructible_v<_Er, const _Er&> constexpr auto transform(_Fn&& __f) const & { @@ -986,7 +986,7 @@ namespace __expected return _Res(unexpect, std::move(error())); } - template requires is_move_constructible_v<_Er> + template requires is_constructible_v<_Er, _Er> constexpr auto transform(_Fn&& __f) && { @@ -1002,7 +1002,7 @@ namespace __expected return _Res(unexpect, std::move(error())); } - template requires is_move_constructible_v<_Er> + template requires is_constructible_v<_Er, const _Er> constexpr auto transform(_Fn&& __f) const && { @@ -1018,7 +1018,7 @@ namespace __expected return _Res(unexpect, std::move(error())); } - template requires is_copy_constructible_v<_Tp> + template requires is_constructible_v<_Tp, _Tp&> constexpr auto transform_error(_Fn&& __f) & { @@ -1034,7 +1034,7 @@ namespace __expected }); } - template requires is_copy_constructible_v<_Tp> + template requires is_constructible_v<_Tp, const _Tp&> constexpr auto transform_error(_Fn&& __f) const & { @@ -1050,7 +1050,7 @@ namespace __expected }); } - template requires is_move_constructible_v<_Tp> + template requires is_constructible_v<_Tp, _Tp> constexpr auto transform_error(_Fn&& __f) && { @@ -1066,7 +1066,7 @@ namespace __expected }); } - template requires is_move_constructible_v<_Tp> + template requires is_constructible_v<_Tp, const _Tp> constexpr auto transform_error(_Fn&& __f) const && { @@ -1519,7 +1519,7 @@ namespace __expected // monadic operations - template requires is_copy_constructible_v<_Er> + template requires is_constructible_v<_Er, _Er&> constexpr auto and_then(_Fn&& __f) & { @@ -1533,7 +1533,7 @@ namespace __expected return _Up(unexpect, error()); } - template requires is_copy_constructible_v<_Er> + template requires is_constructible_v<_Er, const _Er&> constexpr auto and_then(_Fn&& __f) const & { @@ -1547,7 +1547,7 @@ namespace __expected return _Up(unexpect, error()); } - template requires is_move_constructible_v<_Er> + template requires is_constructible_v<_Er, _Er> constexpr auto and_then(_Fn&& __f) && { @@ -1561,7 +1561,7 @@ namespace __expected return _Up(unexpect, std::move(error())); } - template requires is_move_constructible_v<_Er> + template requires is_constructible_v<_Er, const _Er> constexpr auto and_then(_Fn&& __f) const && { @@ -1631,7 +1631,7 @@ namespace __expected return std::__invoke(std::forward<_Fn>(__f), std::move(error())); } - template requires is_copy_constructible_v<_Er> + template requires is_constructible_v<_Er, _Er&> constexpr auto transform(_Fn&& __f) & { @@ -1644,7 +1644,7 @@ namespace __expected return _Res(unexpect, error()); } - template requires is_copy_constructible_v<_Er> + template requires is_constructible_v<_Er, const _Er&> constexpr auto transform(_Fn&& __f) const & { @@ -1657,7 +1657,7 @@ namespace __expected return _Res(unexpect, error()); } - template requires is_move_constructible_v<_Er> + template requires is_constructible_v<_Er, _Er> constexpr auto transform(_Fn&& __f) && { @@ -1670,7 +1670,7 @@ namespace __expected return _Res(unexpect, std::move(error())); } - template requires is_move_constructible_v<_Er> + template requires is_constructible_v<_Er, const _Er> constexpr auto transform(_Fn&& __f) const && { -- cgit v1.1 From 98827c53ed38886795b1f479c1d997fd89011c38 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 17 May 2023 13:47:54 +0100 Subject: libstdc++: Add system_header pragma to Without this change many tests that depend on an effective-target will fail when compiled with -pedantic -std=c++98. This happens because the preprocessor check done by v3_check_preprocessor_condition uses -Werror and includes directly (rather than via another header like ). If is not a system header then this pedwarn is not suppressed, and the effective-target check fails: bits/c++config.h:220: error: anonymous variadic macros were introduced in C++11 [-Werror=variadic-macros] cc1plus: all warnings being treated as errors compiler exited with status 1 UNSUPPORTED: 18_support/headers/limits/synopsis.cc We could consider also changing proc v3_check_preprocessor_condition so that it includes a real header, rather than just , but that's not necessary for now. libstdc++-v3/ChangeLog: * include/bits/c++config: Add system_header pragma. --- libstdc++-v3/include/bits/c++config | 2 ++ 1 file changed, 2 insertions(+) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index 1389278..009a017 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -30,6 +30,8 @@ #ifndef _GLIBCXX_CXX_CONFIG_H #define _GLIBCXX_CXX_CONFIG_H 1 +#pragma GCC system_header + // The major release number for the GCC release the C++ library belongs to. #define _GLIBCXX_RELEASE -- cgit v1.1 From 883f1e25dc7907c9bb37f480b900336a050218f1 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 17 May 2023 21:21:23 +0200 Subject: libstdc++: Fix up some templates [PR109883] As can be seen on the following testcase, for std::{atan2,fmod,pow,copysign,fdim,fmax,fmin,hypot,nextafter,remainder,remquo,fma} if one operand type is std::float{16,32,64,128}_t or std::bfloat16_t and another one some integral type or some other floating point type which promotes to the other operand's type, we can end up with endless recursion. This is because of a declaration ordering problem in , where the float, double and long double overloads of those functions come before the templates which use __gnu_cxx::__promote_{2,3}, but the std::float{16,32,64,128}_t and std::bfloat16_t overloads come later in the file. If the result of those promotions is _Float{16,32,64,128} or __gnu_cxx::__bfloat16_t, say std::pow(_Float64, int) calls std::pow(_Float64, _Float64) and the latter calls itself. The following patch fixes that by moving those templates later in the file, so that the calls from those templates see also the other overloads. I think other templates in the file like e.g. isgreater etc. shouldn't be a problem, because those just use __builtin_isgreater etc. in their bodies. 2023-05-17 Jakub Jelinek PR libstdc++/109883 * include/c_global/cmath (atan2, fmod, pow): Move __gnu_cxx::__promote_2 using templates after _Float{16,32,64,128} and __gnu_cxx::__bfloat16_t overloads. (copysign, fdim, fmax, fmin, hypot, nextafter, remainder, remquo): Likewise. (fma): Move __gnu_cxx::__promote_3 using template after _Float{16,32,64,128} and __gnu_cxx::__bfloat16_t overloads. * testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc: New test. --- libstdc++-v3/include/c_global/cmath | 217 +++++++++++++++++------------------- 1 file changed, 100 insertions(+), 117 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/c_global/cmath b/libstdc++-v3/include/c_global/cmath index 568eb35..4dc029e 100644 --- a/libstdc++-v3/include/c_global/cmath +++ b/libstdc++-v3/include/c_global/cmath @@ -151,15 +151,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_atan2l(__y, __x); } #endif - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - atan2(_Tp __y, _Up __x) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return atan2(__type(__y), __type(__x)); - } - using ::ceil; #ifndef __CORRECT_ISO_CPP_MATH_H_PROTO @@ -286,15 +277,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_fmodl(__x, __y); } #endif - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - fmod(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return fmod(__type(__x), __type(__y)); - } - using ::frexp; #ifndef __CORRECT_ISO_CPP_MATH_H_PROTO @@ -411,15 +393,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif #endif - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - pow(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return pow(__type(__x), __type(__y)); - } - using ::sin; #ifndef __CORRECT_ISO_CPP_MATH_H_PROTO @@ -1073,6 +1046,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __gnu_cxx::__bfloat16_t(__builtin_tanhf(__x)); } #endif + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + atan2(_Tp __y, _Up __x) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return atan2(__type(__y), __type(__x)); + } + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + fmod(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return fmod(__type(__x), __type(__y)); + } + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + pow(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return pow(__type(__x), __type(__y)); + } + #if _GLIBCXX_USE_C99_MATH #if !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC @@ -2107,16 +2107,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_copysignl(__x, __y); } #endif -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - copysign(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return copysign(__type(__x), __type(__y)); - } -#endif - #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP constexpr float erf(float __x) @@ -2199,16 +2189,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_fdiml(__x, __y); } #endif -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - fdim(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return fdim(__type(__x), __type(__y)); - } -#endif - #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP constexpr float fma(float __x, float __y, float __z) @@ -2219,16 +2199,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_fmal(__x, __y, __z); } #endif -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type - fma(_Tp __x, _Up __y, _Vp __z) - { - typedef typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type __type; - return fma(__type(__x), __type(__y), __type(__z)); - } -#endif - #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP constexpr float fmax(float __x, float __y) @@ -2239,16 +2209,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_fmaxl(__x, __y); } #endif -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - fmax(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return fmax(__type(__x), __type(__y)); - } -#endif - #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP constexpr float fmin(float __x, float __y) @@ -2259,16 +2219,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_fminl(__x, __y); } #endif -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - fmin(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return fmin(__type(__x), __type(__y)); - } -#endif - #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP constexpr float hypot(float __x, float __y) @@ -2279,16 +2229,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_hypotl(__x, __y); } #endif -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - hypot(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return hypot(__type(__x), __type(__y)); - } -#endif - #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP constexpr int ilogb(float __x) @@ -2481,16 +2421,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_nextafterl(__x, __y); } #endif -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - nextafter(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return nextafter(__type(__x), __type(__y)); - } -#endif - #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP constexpr float nexttoward(float __x, long double __y) @@ -2519,16 +2449,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_remainderl(__x, __y); } #endif -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - remainder(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return remainder(__type(__x), __type(__y)); - } -#endif - #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP inline float remquo(float __x, float __y, int* __pquo) @@ -2539,16 +2459,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_remquol(__x, __y, __pquo); } #endif -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - remquo(_Tp __x, _Up __y, int* __pquo) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return remquo(__type(__x), __type(__y), __pquo); - } -#endif - #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP constexpr float rint(float __x) @@ -3555,6 +3465,79 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __gnu_cxx::__bfloat16_t(__builtin_truncf(__x)); } #endif +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + copysign(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return copysign(__type(__x), __type(__y)); + } + + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + fdim(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return fdim(__type(__x), __type(__y)); + } + + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + fmax(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return fmax(__type(__x), __type(__y)); + } + + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + fmin(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return fmin(__type(__x), __type(__y)); + } + + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + hypot(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return hypot(__type(__x), __type(__y)); + } + + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + nextafter(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return nextafter(__type(__x), __type(__y)); + } + + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + remainder(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return remainder(__type(__x), __type(__y)); + } + + template + inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + remquo(_Tp __x, _Up __y, int* __pquo) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return remquo(__type(__x), __type(__y), __pquo); + } + + template + constexpr typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type + fma(_Tp __x, _Up __y, _Vp __z) + { + typedef typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type __type; + return fma(__type(__x), __type(__y), __type(__z)); + } +#endif #endif // _GLIBCXX_USE_C99_MATH_TR1 #endif // C++11 -- cgit v1.1 From a7129e82bed1bd4f513fc3c3f401721e2c96a865 Mon Sep 17 00:00:00 2001 From: Matthias Kretz Date: Mon, 22 May 2023 16:58:30 +0200 Subject: libstdc++: Resolve -Wunused-variable warnings in stdx::simd and tests Signed-off-by: Matthias Kretz libstdc++-v3/ChangeLog: * include/experimental/bits/simd_builtin.h (_S_fpclassify): Move __infn into #ifdef'ed block. * testsuite/experimental/simd/tests/fpclassify.cc: Declare constants only when used. * testsuite/experimental/simd/tests/frexp.cc: Likewise. * testsuite/experimental/simd/tests/logarithm.cc: Likewise. * testsuite/experimental/simd/tests/trunc_ceil_floor.cc: Likewise. * testsuite/experimental/simd/tests/ldexp_scalbn_scalbln_modf.cc: Move totest and expect1 into #ifdef'ed block. --- libstdc++-v3/include/experimental/bits/simd_builtin.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/experimental/bits/simd_builtin.h b/libstdc++-v3/include/experimental/bits/simd_builtin.h index 4c008da..3d52bc6 100644 --- a/libstdc++-v3/include/experimental/bits/simd_builtin.h +++ b/libstdc++-v3/include/experimental/bits/simd_builtin.h @@ -2370,12 +2370,12 @@ template constexpr size_t _NI = sizeof(__xn) / sizeof(_I); _GLIBCXX_SIMD_USE_CONSTEXPR auto __minn = __vector_bitcast<_I>(__vector_broadcast<_NI>(__norm_min_v<_Tp>)); - _GLIBCXX_SIMD_USE_CONSTEXPR auto __infn - = __vector_bitcast<_I>(__vector_broadcast<_NI>(__infinity_v<_Tp>)); _GLIBCXX_SIMD_USE_CONSTEXPR auto __fp_normal = __vector_broadcast<_NI, _I>(FP_NORMAL); #if !__FINITE_MATH_ONLY__ + _GLIBCXX_SIMD_USE_CONSTEXPR auto __infn + = __vector_bitcast<_I>(__vector_broadcast<_NI>(__infinity_v<_Tp>)); _GLIBCXX_SIMD_USE_CONSTEXPR auto __fp_nan = __vector_broadcast<_NI, _I>(FP_NAN); _GLIBCXX_SIMD_USE_CONSTEXPR auto __fp_infinite -- cgit v1.1 From da579188807ede4ee9466d0b5bf51559c96a0b51 Mon Sep 17 00:00:00 2001 From: Matthias Kretz Date: Thu, 23 Mar 2023 09:32:58 +0100 Subject: libstdc++: Add missing constexpr to simd The constexpr API is only available with -std=gnu++XX (and proposed for C++26). The proposal is to have the complete simd API usable in constant expressions. This patch resolves several issues with using simd in constant expressions. Issues why constant_evaluated branches are necessary: * subscripting vector builtins is not allowed in constant expressions * if the implementation needs/uses memcpy * if the implementation would otherwise call SIMD intrinsics/builtins Signed-off-by: Matthias Kretz libstdc++-v3/ChangeLog: PR libstdc++/109261 * include/experimental/bits/simd.h (_SimdWrapper::_M_set): Avoid vector builtin subscripting in constant expressions. (resizing_simd_cast): Avoid memcpy if constant_evaluated. (const_where_expression, where_expression, where) (__extract_part, simd_mask, _SimdIntOperators, simd): Add either _GLIBCXX_SIMD_CONSTEXPR (on public APIs), or constexpr (on internal APIs). * include/experimental/bits/simd_builtin.h (__vector_permute) (__vector_shuffle, __extract_part, _GnuTraits::_SimdCastType1) (_GnuTraits::_SimdCastType2, _SimdImplBuiltin) (_MaskImplBuiltin::_S_store): Add constexpr. (_CommonImplBuiltin::_S_store_bool_array) (_SimdImplBuiltin::_S_load, _SimdImplBuiltin::_S_store) (_SimdImplBuiltin::_S_reduce, _MaskImplBuiltin::_S_load): Add constant_evaluated case. * include/experimental/bits/simd_fixed_size.h (_S_masked_load): Reword comment. (__tuple_element_meta, __make_meta, _SimdTuple::_M_apply_r) (_SimdTuple::_M_subscript_read, _SimdTuple::_M_subscript_write) (__make_simd_tuple, __optimize_simd_tuple, __extract_part) (__autocvt_to_simd, _Fixed::__traits::_SimdBase) (_Fixed::__traits::_SimdCastType, _SimdImplFixedSize): Add constexpr. (_SimdTuple::operator[], _M_set): Add constexpr and add constant_evaluated case. (_MaskImplFixedSize::_S_load): Add constant_evaluated case. * include/experimental/bits/simd_scalar.h: Add constexpr. * include/experimental/bits/simd_x86.h (_CommonImplX86): Add constexpr and add constant_evaluated case. (_SimdImplX86::_S_equal_to, _S_not_equal_to, _S_less) (_S_less_equal): Value-initialize to satisfy constexpr evaluation. (_MaskImplX86::_S_load): Add constant_evaluated case. (_MaskImplX86::_S_store): Add constexpr and constant_evaluated case. Value-initialize local variables. (_MaskImplX86::_S_logical_and, _S_logical_or, _S_bit_not) (_S_bit_and, _S_bit_or, _S_bit_xor): Add constant_evaluated case. * testsuite/experimental/simd/pr109261_constexpr_simd.cc: New test. --- libstdc++-v3/include/experimental/bits/simd.h | 153 ++++++++++-------- .../include/experimental/bits/simd_builtin.h | 100 +++++++----- .../include/experimental/bits/simd_fixed_size.h | 177 +++++++++++---------- .../include/experimental/bits/simd_scalar.h | 78 ++++----- libstdc++-v3/include/experimental/bits/simd_x86.h | 68 +++++--- 5 files changed, 326 insertions(+), 250 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/experimental/bits/simd.h b/libstdc++-v3/include/experimental/bits/simd.h index 224153f..b0571ca2 100644 --- a/libstdc++-v3/include/experimental/bits/simd.h +++ b/libstdc++-v3/include/experimental/bits/simd.h @@ -2675,7 +2675,14 @@ template _GLIBCXX_SIMD_INTRINSIC constexpr void _M_set(size_t __i, _Tp __x) - { _M_data[__i] = __x; } + { + if (__builtin_is_constant_evaluated()) + _M_data = __generate_from_n_evaluations<_Width, _BuiltinType>([&](auto __j) { + return __j == __i ? __x : _M_data[__j()]; + }); + else + _M_data[__i] = __x; + } _GLIBCXX_SIMD_INTRINSIC constexpr bool @@ -3186,6 +3193,10 @@ template { if constexpr (is_same_v) return __x; + else if (__builtin_is_constant_evaluated()) + return _Tp([&](auto __i) constexpr { + return __i < simd_size_v<_Up, _Ap> ? __x[__i] : _Up(); + }); else if constexpr (simd_size_v<_Up, _Ap> == 1) { _Tp __r{}; @@ -3321,10 +3332,11 @@ template const_where_expression& operator=(const const_where_expression&) = delete; - _GLIBCXX_SIMD_INTRINSIC const_where_expression(const _M& __kk, const _Tp& dd) - : _M_k(__kk), _M_value(const_cast<_Tp&>(dd)) {} + _GLIBCXX_SIMD_INTRINSIC constexpr + const_where_expression(const _M& __kk, const _Tp& dd) + : _M_k(__kk), _M_value(const_cast<_Tp&>(dd)) {} - _GLIBCXX_SIMD_INTRINSIC _V + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR _V operator-() const&& { return {__private_init, @@ -3333,7 +3345,7 @@ template } template - [[nodiscard]] _GLIBCXX_SIMD_INTRINSIC _V + [[nodiscard]] _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR _V copy_from(const _LoadStorePtr<_Up, value_type>* __mem, _IsSimdFlagType<_Flags>) const&& { return {__private_init, @@ -3342,7 +3354,7 @@ template } template - _GLIBCXX_SIMD_INTRINSIC void + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR void copy_to(_LoadStorePtr<_Up, value_type>* __mem, _IsSimdFlagType<_Flags>) const&& { _Impl::_S_masked_store(__data(_M_value), @@ -3381,19 +3393,21 @@ template const_where_expression(const const_where_expression&) = delete; const_where_expression& operator=(const const_where_expression&) = delete; - _GLIBCXX_SIMD_INTRINSIC const_where_expression(const bool __kk, const _Tp& dd) - : _M_k(__kk), _M_value(const_cast<_Tp&>(dd)) {} + _GLIBCXX_SIMD_INTRINSIC constexpr + const_where_expression(const bool __kk, const _Tp& dd) + : _M_k(__kk), _M_value(const_cast<_Tp&>(dd)) {} - _GLIBCXX_SIMD_INTRINSIC _V operator-() const&& + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR _V + operator-() const&& { return _M_k ? -_M_value : _M_value; } template - [[nodiscard]] _GLIBCXX_SIMD_INTRINSIC _V + [[nodiscard]] _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR _V copy_from(const _LoadStorePtr<_Up, value_type>* __mem, _IsSimdFlagType<_Flags>) const&& { return _M_k ? static_cast<_V>(__mem[0]) : _M_value; } template - _GLIBCXX_SIMD_INTRINSIC void + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR void copy_to(_LoadStorePtr<_Up, value_type>* __mem, _IsSimdFlagType<_Flags>) const&& { if (_M_k) @@ -3419,18 +3433,21 @@ template is_same::value, ""); static_assert(_M::size() == _Tp::size(), ""); - _GLIBCXX_SIMD_INTRINSIC friend _Tp& __get_lvalue(where_expression& __x) + _GLIBCXX_SIMD_INTRINSIC friend constexpr _Tp& + __get_lvalue(where_expression& __x) { return __x._M_value; } public: where_expression(const where_expression&) = delete; where_expression& operator=(const where_expression&) = delete; - _GLIBCXX_SIMD_INTRINSIC where_expression(const _M& __kk, _Tp& dd) - : const_where_expression<_M, _Tp>(__kk, dd) {} + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR + where_expression(const _M& __kk, _Tp& dd) + : const_where_expression<_M, _Tp>(__kk, dd) {} template - _GLIBCXX_SIMD_INTRINSIC void operator=(_Up&& __x) && + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR void + operator=(_Up&& __x) && { _Impl::_S_masked_assign(__data(_M_k), __data(_M_value), __to_value_type_or_member_type<_Tp>( @@ -3439,7 +3456,8 @@ template #define _GLIBCXX_SIMD_OP_(__op, __name) \ template \ - _GLIBCXX_SIMD_INTRINSIC void operator __op##=(_Up&& __x)&& \ + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR void \ + operator __op##=(_Up&& __x)&& \ { \ _Impl::template _S_masked_cassign( \ __data(_M_k), __data(_M_value), \ @@ -3461,28 +3479,28 @@ template _GLIBCXX_SIMD_OP_(>>, _S_shift_right); #undef _GLIBCXX_SIMD_OP_ - _GLIBCXX_SIMD_INTRINSIC void + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR void operator++() && { __data(_M_value) = _Impl::template _S_masked_unary<__increment>(__data(_M_k), __data(_M_value)); } - _GLIBCXX_SIMD_INTRINSIC void + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR void operator++(int) && { __data(_M_value) = _Impl::template _S_masked_unary<__increment>(__data(_M_k), __data(_M_value)); } - _GLIBCXX_SIMD_INTRINSIC void + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR void operator--() && { __data(_M_value) = _Impl::template _S_masked_unary<__decrement>(__data(_M_k), __data(_M_value)); } - _GLIBCXX_SIMD_INTRINSIC void + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR void operator--(int) && { __data(_M_value) @@ -3491,7 +3509,7 @@ template // intentionally hides const_where_expression::copy_from template - _GLIBCXX_SIMD_INTRINSIC void + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR void copy_from(const _LoadStorePtr<_Up, value_type>* __mem, _IsSimdFlagType<_Flags>) && { __data(_M_value) = _Impl::_S_masked_load(__data(_M_value), __data(_M_k), @@ -3513,13 +3531,13 @@ template where_expression(const where_expression&) = delete; where_expression& operator=(const where_expression&) = delete; - _GLIBCXX_SIMD_INTRINSIC + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR where_expression(const _M& __kk, _Tp& dd) : const_where_expression<_M, _Tp>(__kk, dd) {} #define _GLIBCXX_SIMD_OP_(__op) \ template \ - _GLIBCXX_SIMD_INTRINSIC void \ + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR void \ operator __op(_Up&& __x)&& \ { if (_M_k) _M_value __op static_cast<_Up&&>(__x); } @@ -3536,68 +3554,71 @@ template _GLIBCXX_SIMD_OP_(>>=) #undef _GLIBCXX_SIMD_OP_ - _GLIBCXX_SIMD_INTRINSIC void + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR void operator++() && { if (_M_k) ++_M_value; } - _GLIBCXX_SIMD_INTRINSIC void + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR void operator++(int) && { if (_M_k) ++_M_value; } - _GLIBCXX_SIMD_INTRINSIC void + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR void operator--() && { if (_M_k) --_M_value; } - _GLIBCXX_SIMD_INTRINSIC void + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR void operator--(int) && { if (_M_k) --_M_value; } // intentionally hides const_where_expression::copy_from template - _GLIBCXX_SIMD_INTRINSIC void + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR void copy_from(const _LoadStorePtr<_Up, value_type>* __mem, _IsSimdFlagType<_Flags>) && { if (_M_k) _M_value = __mem[0]; } }; // where {{{1 template - _GLIBCXX_SIMD_INTRINSIC where_expression, simd<_Tp, _Ap>> + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR + where_expression, simd<_Tp, _Ap>> where(const typename simd<_Tp, _Ap>::mask_type& __k, simd<_Tp, _Ap>& __value) { return {__k, __value}; } template - _GLIBCXX_SIMD_INTRINSIC + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR const_where_expression, simd<_Tp, _Ap>> where(const typename simd<_Tp, _Ap>::mask_type& __k, const simd<_Tp, _Ap>& __value) { return {__k, __value}; } template - _GLIBCXX_SIMD_INTRINSIC + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR where_expression, simd_mask<_Tp, _Ap>> where(const remove_const_t>& __k, simd_mask<_Tp, _Ap>& __value) { return {__k, __value}; } template - _GLIBCXX_SIMD_INTRINSIC + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR const_where_expression, simd_mask<_Tp, _Ap>> where(const remove_const_t>& __k, const simd_mask<_Tp, _Ap>& __value) { return {__k, __value}; } template - _GLIBCXX_SIMD_INTRINSIC where_expression + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR where_expression where(_ExactBool __k, _Tp& __value) { return {__k, __value}; } template - _GLIBCXX_SIMD_INTRINSIC const_where_expression + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR const_where_expression where(_ExactBool __k, const _Tp& __value) { return {__k, __value}; } template - void where(bool __k, simd<_Tp, _Ap>& __value) = delete; + _GLIBCXX_SIMD_CONSTEXPR void + where(bool __k, simd<_Tp, _Ap>& __value) = delete; template - void where(bool __k, const simd<_Tp, _Ap>& __value) = delete; + _GLIBCXX_SIMD_CONSTEXPR void + where(bool __k, const simd<_Tp, _Ap>& __value) = delete; // proposed mask iterations {{{1 namespace __proposed { @@ -3820,12 +3841,12 @@ template - _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_CONST + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_CONST constexpr _SimdWrapper<_Tp, _Np / _Total * _Combine> __extract_part(const _SimdWrapper<_Tp, _Np> __x); template - _GLIBCXX_SIMD_INTRINSIC auto + _GLIBCXX_SIMD_INTRINSIC constexpr auto __extract_part(const _SimdTuple<_Tp, _A0, _As...>& __x); // }}} @@ -4551,7 +4572,7 @@ template // }}} // access to internal representation (optional feature) {{{ - _GLIBCXX_SIMD_ALWAYS_INLINE explicit + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR explicit simd_mask(typename _Traits::_MaskCastType __init) : _M_data{__init} {} // conversions to internal type is done in _MaskBase @@ -4562,11 +4583,11 @@ template // Conversion of simd_mask to and from bitset makes it much easier to // interface with other facilities. I suggest adding `static // simd_mask::from_bitset` and `simd_mask::to_bitset`. - _GLIBCXX_SIMD_ALWAYS_INLINE static simd_mask + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR static simd_mask __from_bitset(bitset bs) { return {__bitset_init, bs}; } - _GLIBCXX_SIMD_ALWAYS_INLINE bitset + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR bitset __to_bitset() const { return _Impl::_S_to_bits(_M_data)._M_to_bitset(); } @@ -4591,7 +4612,7 @@ template template >, is_same<_Up, _Up>>::value>> - _GLIBCXX_SIMD_ALWAYS_INLINE + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR simd_mask(const simd_mask<_Up, simd_abi::fixed_size>& __x) : _M_data(_Impl::_S_from_bitmask(__data(__x), _S_type_tag)) {} #endif @@ -4599,12 +4620,12 @@ template // }}} // load constructor {{{ template - _GLIBCXX_SIMD_ALWAYS_INLINE + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR simd_mask(const value_type* __mem, _IsSimdFlagType<_Flags>) : _M_data(_Impl::template _S_load<_Ip>(_Flags::template _S_apply(__mem))) {} template - _GLIBCXX_SIMD_ALWAYS_INLINE + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR simd_mask(const value_type* __mem, simd_mask __k, _IsSimdFlagType<_Flags>) : _M_data{} { @@ -4615,20 +4636,20 @@ template // }}} // loads [simd_mask.load] {{{ template - _GLIBCXX_SIMD_ALWAYS_INLINE void + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR void copy_from(const value_type* __mem, _IsSimdFlagType<_Flags>) { _M_data = _Impl::template _S_load<_Ip>(_Flags::template _S_apply(__mem)); } // }}} // stores [simd_mask.store] {{{ template - _GLIBCXX_SIMD_ALWAYS_INLINE void + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR void copy_to(value_type* __mem, _IsSimdFlagType<_Flags>) const { _Impl::_S_store(_M_data, _Flags::template _S_apply(__mem)); } // }}} // scalar access {{{ - _GLIBCXX_SIMD_ALWAYS_INLINE reference + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR reference operator[](size_t __i) { if (__i >= size()) @@ -4636,7 +4657,7 @@ template return {_M_data, int(__i)}; } - _GLIBCXX_SIMD_ALWAYS_INLINE value_type + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR value_type operator[](size_t __i) const { if (__i >= size()) @@ -4649,7 +4670,7 @@ template // }}} // negation {{{ - _GLIBCXX_SIMD_ALWAYS_INLINE simd_mask + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR simd_mask operator!() const { return {__private_init, _Impl::_S_bit_not(_M_data)}; } @@ -4659,7 +4680,7 @@ template // simd_mask && simd_mask needs disambiguation template , simd_mask>>> - _GLIBCXX_SIMD_ALWAYS_INLINE friend simd_mask + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR friend simd_mask operator&&(const simd_mask& __x, const simd_mask<_Up, _A2>& __y) { return {__private_init, @@ -4668,7 +4689,7 @@ template template , simd_mask>>> - _GLIBCXX_SIMD_ALWAYS_INLINE friend simd_mask + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR friend simd_mask operator||(const simd_mask& __x, const simd_mask<_Up, _A2>& __y) { return {__private_init, @@ -4676,41 +4697,41 @@ template } #endif // _GLIBCXX_SIMD_ENABLE_IMPLICIT_MASK_CAST - _GLIBCXX_SIMD_ALWAYS_INLINE friend simd_mask + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR friend simd_mask operator&&(const simd_mask& __x, const simd_mask& __y) { return {__private_init, _Impl::_S_logical_and(__x._M_data, __y._M_data)}; } - _GLIBCXX_SIMD_ALWAYS_INLINE friend simd_mask + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR friend simd_mask operator||(const simd_mask& __x, const simd_mask& __y) { return {__private_init, _Impl::_S_logical_or(__x._M_data, __y._M_data)}; } - _GLIBCXX_SIMD_ALWAYS_INLINE friend simd_mask + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR friend simd_mask operator&(const simd_mask& __x, const simd_mask& __y) { return {__private_init, _Impl::_S_bit_and(__x._M_data, __y._M_data)}; } - _GLIBCXX_SIMD_ALWAYS_INLINE friend simd_mask + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR friend simd_mask operator|(const simd_mask& __x, const simd_mask& __y) { return {__private_init, _Impl::_S_bit_or(__x._M_data, __y._M_data)}; } - _GLIBCXX_SIMD_ALWAYS_INLINE friend simd_mask + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR friend simd_mask operator^(const simd_mask& __x, const simd_mask& __y) { return {__private_init, _Impl::_S_bit_xor(__x._M_data, __y._M_data)}; } - _GLIBCXX_SIMD_ALWAYS_INLINE friend simd_mask& + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR friend simd_mask& operator&=(simd_mask& __x, const simd_mask& __y) { __x._M_data = _Impl::_S_bit_and(__x._M_data, __y._M_data); return __x; } - _GLIBCXX_SIMD_ALWAYS_INLINE friend simd_mask& + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR friend simd_mask& operator|=(simd_mask& __x, const simd_mask& __y) { __x._M_data = _Impl::_S_bit_or(__x._M_data, __y._M_data); return __x; } - _GLIBCXX_SIMD_ALWAYS_INLINE friend simd_mask& + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR friend simd_mask& operator^=(simd_mask& __x, const simd_mask& __y) { __x._M_data = _Impl::_S_bit_xor(__x._M_data, __y._M_data); @@ -4747,7 +4768,8 @@ template // }}} // bitset_init ctor {{{ - _GLIBCXX_SIMD_INTRINSIC simd_mask(_BitsetInit, bitset __init) + _GLIBCXX_SIMD_INTRINSIC constexpr + simd_mask(_BitsetInit, bitset __init) : _M_data(_Impl::_S_from_bitmask(_SanitizedBitMask(__init), _S_type_tag)) {} @@ -5015,7 +5037,8 @@ template { using _Impl = typename _SimdTraits<_Tp, _Abi>::_SimdImpl; - _GLIBCXX_SIMD_INTRINSIC const _V& __derived() const + _GLIBCXX_SIMD_INTRINSIC constexpr const _V& + __derived() const { return *static_cast(this); } template @@ -5235,7 +5258,7 @@ template // load constructor template - _GLIBCXX_SIMD_ALWAYS_INLINE + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR simd(const _Up* __mem, _IsSimdFlagType<_Flags>) : _M_data( _Impl::_S_load(_Flags::template _S_apply(__mem), _S_type_tag)) @@ -5243,7 +5266,7 @@ template // loads [simd.load] template - _GLIBCXX_SIMD_ALWAYS_INLINE void + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR void copy_from(const _Vectorizable<_Up>* __mem, _IsSimdFlagType<_Flags>) { _M_data = static_cast( @@ -5252,7 +5275,7 @@ template // stores [simd.store] template - _GLIBCXX_SIMD_ALWAYS_INLINE void + _GLIBCXX_SIMD_ALWAYS_INLINE _GLIBCXX_SIMD_CONSTEXPR void copy_to(_Vectorizable<_Up>* __mem, _IsSimdFlagType<_Flags>) const { _Impl::_S_store(_M_data, _Flags::template _S_apply(__mem), @@ -5424,7 +5447,7 @@ template } private: - _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR static mask_type + _GLIBCXX_SIMD_INTRINSIC static constexpr mask_type _S_make_mask(typename mask_type::_MemberType __k) { return {__private_init, __k}; } diff --git a/libstdc++-v3/include/experimental/bits/simd_builtin.h b/libstdc++-v3/include/experimental/bits/simd_builtin.h index 3d52bc6..8337fa2 100644 --- a/libstdc++-v3/include/experimental/bits/simd_builtin.h +++ b/libstdc++-v3/include/experimental/bits/simd_builtin.h @@ -52,7 +52,7 @@ template > // Index == -1 requests zeroing of the output element template , typename = __detail::__odr_helper> - _Tp + constexpr _Tp __vector_permute(_Tp __x) { static_assert(sizeof...(_Indices) == _TVT::_S_full_size); @@ -65,7 +65,7 @@ template , // Index == -1 requests zeroing of the output element template , typename = __detail::__odr_helper> - _Tp + constexpr _Tp __vector_shuffle(_Tp __x, _Tp __y) { return _Tp{(_Indices == -1 ? 0 @@ -205,7 +205,7 @@ template > // }}} // __extract_part(_SimdWrapper<_Tp, _Np>) {{{ template - _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_CONST + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_CONST constexpr _SimdWrapper<_Tp, _Np / _Total * _Combine> __extract_part(const _SimdWrapper<_Tp, _Np> __x) { @@ -905,10 +905,10 @@ template _SimdMember _M_data; public: - _GLIBCXX_SIMD_ALWAYS_INLINE + _GLIBCXX_SIMD_ALWAYS_INLINE constexpr _SimdCastType1(_Ap __a) : _M_data(__vector_bitcast<_Tp>(__a)) {} - _GLIBCXX_SIMD_ALWAYS_INLINE + _GLIBCXX_SIMD_ALWAYS_INLINE constexpr operator _SimdMember() const { return _M_data; } }; @@ -919,13 +919,13 @@ template _SimdMember _M_data; public: - _GLIBCXX_SIMD_ALWAYS_INLINE + _GLIBCXX_SIMD_ALWAYS_INLINE constexpr _SimdCastType2(_Ap __a) : _M_data(__vector_bitcast<_Tp>(__a)) {} - _GLIBCXX_SIMD_ALWAYS_INLINE + _GLIBCXX_SIMD_ALWAYS_INLINE constexpr _SimdCastType2(_Bp __b) : _M_data(__b) {} - _GLIBCXX_SIMD_ALWAYS_INLINE + _GLIBCXX_SIMD_ALWAYS_INLINE constexpr operator _SimdMember() const { return _M_data; } }; @@ -1345,6 +1345,11 @@ struct _CommonImplBuiltin { if constexpr (_Np == 1) __mem[0] = __x[0]; + else if (__builtin_is_constant_evaluated()) + { + for (size_t __i = 0; __i < _Np; ++__i) + __mem[__i] = __x[__i]; + } else if constexpr (_Np == 2) { short __bool2 = (__x._M_to_bits() * 0x81) & 0x0101; @@ -1424,12 +1429,12 @@ template // _M_make_simd(_SimdWrapper/__intrinsic_type_t) {{{2 template - _GLIBCXX_SIMD_INTRINSIC static simd<_Tp, _Abi> + _GLIBCXX_SIMD_INTRINSIC static constexpr simd<_Tp, _Abi> _M_make_simd(_SimdWrapper<_Tp, _Np> __x) { return {__private_init, __x}; } template - _GLIBCXX_SIMD_INTRINSIC static simd<_Tp, _Abi> + _GLIBCXX_SIMD_INTRINSIC static constexpr simd<_Tp, _Abi> _M_make_simd(__intrinsic_type_t<_Tp, _Np> __x) { return {__private_init, __vector_bitcast<_Tp>(__x)}; } @@ -1455,7 +1460,7 @@ template // _S_load {{{2 template - _GLIBCXX_SIMD_INTRINSIC static _SimdMember<_Tp> + _GLIBCXX_SIMD_INTRINSIC static constexpr _SimdMember<_Tp> _S_load(const _Up* __mem, _TypeTag<_Tp>) noexcept { constexpr size_t _Np = _S_size<_Tp>; @@ -1464,7 +1469,12 @@ template : (is_floating_point_v<_Up> && __have_avx) || __have_avx2 ? 32 : 16; constexpr size_t __bytes_to_load = sizeof(_Up) * _Np; - if constexpr (sizeof(_Up) > 8) + if (__builtin_is_constant_evaluated()) + return __generate_vector<_Tp, _S_full_size<_Tp>>( + [&](auto __i) constexpr { + return static_cast<_Tp>(__i < _Np ? __mem[__i] : 0); + }); + else if constexpr (sizeof(_Up) > 8) return __generate_vector<_Tp, _SimdMember<_Tp>::_S_full_size>( [&](auto __i) constexpr _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA { return static_cast<_Tp>(__i < _Np ? __mem[__i] : 0); @@ -1511,7 +1521,7 @@ template // _S_masked_load {{{2 template - static inline _SimdWrapper<_Tp, _Np> + static constexpr inline _SimdWrapper<_Tp, _Np> _S_masked_load(_SimdWrapper<_Tp, _Np> __merge, _MaskMember<_Tp> __k, const _Up* __mem) noexcept { @@ -1524,14 +1534,19 @@ template // _S_store {{{2 template - _GLIBCXX_SIMD_INTRINSIC static void + _GLIBCXX_SIMD_INTRINSIC static constexpr void _S_store(_SimdMember<_Tp> __v, _Up* __mem, _TypeTag<_Tp>) noexcept { // TODO: converting int -> "smaller int" can be optimized with AVX512 constexpr size_t _Np = _S_size<_Tp>; constexpr size_t __max_store_size = _SuperImpl::template _S_max_store_size<_Up>; - if constexpr (sizeof(_Up) > 8) + if (__builtin_is_constant_evaluated()) + { + for (size_t __i = 0; __i < _Np; ++__i) + __mem[__i] = __v[__i]; + } + else if constexpr (sizeof(_Up) > 8) __execute_n_times<_Np>([&](auto __i) constexpr _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA { __mem[__i] = __v[__i]; }); @@ -1562,7 +1577,7 @@ template // _S_masked_store_nocvt {{{2 template - _GLIBCXX_SIMD_INTRINSIC static void + _GLIBCXX_SIMD_INTRINSIC static constexpr void _S_masked_store_nocvt(_SimdWrapper<_Tp, _Np> __v, _Tp* __mem, _MaskMember<_Tp> __k) { _BitOps::_S_bit_iteration( @@ -1575,7 +1590,7 @@ template // _S_masked_store {{{2 template , typename _Tp = typename _TVT::value_type, typename _Up> - static inline void + static constexpr inline void _S_masked_store(const _TW __v, _Up* __mem, const _MaskMember<_Tp> __k) noexcept { constexpr size_t _TV_size = _S_size<_Tp>; @@ -1803,7 +1818,7 @@ template // reductions {{{2 template - _GLIBCXX_SIMD_INTRINSIC static _Tp + _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp _S_reduce_partial(index_sequence<_Is...>, index_sequence<_Zeros...>, simd<_Tp, _Abi> __x, _BinaryOperation&& __binary_op) { @@ -1833,6 +1848,13 @@ template else if constexpr (_Np == 2) return __binary_op(simd<_Tp, simd_abi::scalar>(__x[0]), simd<_Tp, simd_abi::scalar>(__x[1]))[0]; + else if (__builtin_is_constant_evaluated()) + { + simd<_Tp, simd_abi::scalar> __acc = __x[0]; + for (size_t __i = 1; __i < _Np; ++__i) + __acc = __binary_op(__acc, simd<_Tp, simd_abi::scalar>(__x[__i])); + return __acc[0]; + } else if constexpr (_Abi::template _S_is_partial<_Tp>) //{{{ { [[maybe_unused]] constexpr auto __full_size @@ -2445,24 +2467,24 @@ template // _S_increment & _S_decrement{{{2 template - _GLIBCXX_SIMD_INTRINSIC static void + _GLIBCXX_SIMD_INTRINSIC static constexpr void _S_increment(_SimdWrapper<_Tp, _Np>& __x) { __x = __x._M_data + 1; } template - _GLIBCXX_SIMD_INTRINSIC static void + _GLIBCXX_SIMD_INTRINSIC static constexpr void _S_decrement(_SimdWrapper<_Tp, _Np>& __x) { __x = __x._M_data - 1; } // smart_reference access {{{2 template - _GLIBCXX_SIMD_INTRINSIC constexpr static void + _GLIBCXX_SIMD_INTRINSIC static constexpr void _S_set(_SimdWrapper<_Tp, _Np>& __v, int __i, _Up&& __x) noexcept { __v._M_set(__i, static_cast<_Up&&>(__x)); } // _S_masked_assign{{{2 template - _GLIBCXX_SIMD_INTRINSIC static void + _GLIBCXX_SIMD_INTRINSIC static constexpr void _S_masked_assign(_SimdWrapper<_K, _Np> __k, _SimdWrapper<_Tp, _Np>& __lhs, __type_identity_t<_SimdWrapper<_Tp, _Np>> __rhs) { @@ -2475,7 +2497,7 @@ template } template - _GLIBCXX_SIMD_INTRINSIC static void + _GLIBCXX_SIMD_INTRINSIC static constexpr void _S_masked_assign(_SimdWrapper<_K, _Np> __k, _SimdWrapper<_Tp, _Np>& __lhs, __type_identity_t<_Tp> __rhs) { @@ -2503,7 +2525,7 @@ template // _S_masked_cassign {{{2 template - _GLIBCXX_SIMD_INTRINSIC static void + _GLIBCXX_SIMD_INTRINSIC static constexpr void _S_masked_cassign(const _SimdWrapper<_K, _Np> __k, _SimdWrapper<_Tp, _Np>& __lhs, const __type_identity_t<_SimdWrapper<_Tp, _Np>> __rhs, @@ -2519,7 +2541,7 @@ template } template - _GLIBCXX_SIMD_INTRINSIC static void + _GLIBCXX_SIMD_INTRINSIC static constexpr void _S_masked_cassign(const _SimdWrapper<_K, _Np> __k, _SimdWrapper<_Tp, _Np>& __lhs, const __type_identity_t<_Tp> __rhs, _Op __op) @@ -2528,7 +2550,7 @@ template // _S_masked_unary {{{2 template