From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2181) id 5B0D5385021B; Fri, 24 Feb 2023 14:26:14 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 5B0D5385021B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1677248774; bh=QmFawF6DAVISskN13PwrFMLRxG9JZ4WlurouAVDQaZ4=; h=From:To:Subject:Date:From; b=ox7hOaG7LdIUX5PjQULg9xw+QpYQqHDdT9rqyBUTsZvQknmJiMNxUBWvFGJnwOx05 uuUC+FlDl4PbkHX9XKufFtl60ROUlrIrVOSoMtnur3MjO24E1Z4G68JEzBDiONh7xU kj/eYMvbfVt48UmAooKCbjTivyjA50U17Drm6dXg= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jonathan Wakely To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r13-6325] libstdc++: Fix conversion to/from net::ip::address_v4::bytes_type X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/heads/master X-Git-Oldrev: 363f0ef50bd143fce77a1c7905b0ed707f4a9358 X-Git-Newrev: 36ecfb75e053d54dd36dd3900d3096004f6d9aae Message-Id: <20230224142614.5B0D5385021B@sourceware.org> Date: Fri, 24 Feb 2023 14:26:14 +0000 (GMT) List-Id: https://gcc.gnu.org/g:36ecfb75e053d54dd36dd3900d3096004f6d9aae commit r13-6325-g36ecfb75e053d54dd36dd3900d3096004f6d9aae Author: Jonathan Wakely Date: Fri Feb 24 10:08:26 2023 +0000 libstdc++: Fix conversion to/from net::ip::address_v4::bytes_type I messed up the endianness of the address_v4::bytes_type array, which should always be in network byte order. We can just use bit_cast to convert the _M_addr member to/from bytes_type. libstdc++-v3/ChangeLog: * include/experimental/internet (address_4(const bytes_type&)): Use __builtin_bit_cast if available, otherwise convert to network byte order. (address_v4::to_bytes()): Likewise, but convert from network byte order. * testsuite/experimental/net/internet/address/v4/cons.cc: Fix incorrect tests. Check for constexpr too. * testsuite/experimental/net/internet/address/v4/creation.cc: Likewise. * testsuite/experimental/net/internet/address/v4/members.cc: Check that bytes_type is a standard-layout type. Diff: --- libstdc++-v3/include/experimental/internet | 20 +++++++++---- .../experimental/net/internet/address/v4/cons.cc | 33 ++++++++++++++-------- .../net/internet/address/v4/creation.cc | 24 +++++++++++++--- .../net/internet/address/v4/members.cc | 3 ++ 4 files changed, 60 insertions(+), 20 deletions(-) diff --git a/libstdc++-v3/include/experimental/internet b/libstdc++-v3/include/experimental/internet index 08bd0db4bb2..3fd200251fa 100644 --- a/libstdc++-v3/include/experimental/internet +++ b/libstdc++-v3/include/experimental/internet @@ -198,7 +198,12 @@ namespace ip constexpr address_v4(const bytes_type& __b) - : _M_addr((__b[0] << 24) | (__b[1] << 16) | (__b[2] << 8) | __b[3]) +#if __has_builtin(__builtin_bit_cast) + : _M_addr(__builtin_bit_cast(uint_type, __b)) +#else + : _M_addr(_S_hton_32((__b[0] << 24) | (__b[1] << 16) + | (__b[2] << 8) | __b[3])) +#endif { } explicit constexpr @@ -227,12 +232,17 @@ namespace ip constexpr bytes_type to_bytes() const noexcept { +#if __has_builtin(__builtin_bit_cast) + return __builtin_bit_cast(bytes_type, _M_addr); +#else + auto __host = to_uint(); return bytes_type{ - (_M_addr >> 24) & 0xFF, - (_M_addr >> 16) & 0xFF, - (_M_addr >> 8) & 0xFF, - _M_addr & 0xFF + (__host >> 24) & 0xFF, + (__host >> 16) & 0xFF, + (__host >> 8) & 0xFF, + __host & 0xFF }; +#endif } constexpr uint_type diff --git a/libstdc++-v3/testsuite/experimental/net/internet/address/v4/cons.cc b/libstdc++-v3/testsuite/experimental/net/internet/address/v4/cons.cc index 65f23642de4..af9fef2215e 100644 --- a/libstdc++-v3/testsuite/experimental/net/internet/address/v4/cons.cc +++ b/libstdc++-v3/testsuite/experimental/net/internet/address/v4/cons.cc @@ -24,41 +24,45 @@ using std::experimental::net::ip::address_v4; -void -test01() +#if __cplusplus < 202002L +// Naughty, but operator== for std::array is not constexpr until C++20. +constexpr bool +operator==(const address_v4::bytes_type& lhs, const address_v4::bytes_type& rhs) { - bool test __attribute__((unused)) = false; + return lhs[0] == rhs[0] && lhs[1] == rhs[1] + && lhs[2] == rhs[2] && lhs[3] == rhs[3]; +} +#endif +constexpr void +test01() +{ address_v4 a0; VERIFY( a0.to_uint() == 0 ); VERIFY( a0.to_bytes() == address_v4::bytes_type{} ); } -void +constexpr void test02() { - bool test __attribute__((unused)) = false; - address_v4 a0{ address_v4::bytes_type{} }; VERIFY( a0.to_uint() == 0 ); VERIFY( a0.to_bytes() == address_v4::bytes_type{} ); address_v4::bytes_type b1{ 1, 2, 3, 4 }; address_v4 a1{ b1 }; - VERIFY( a1.to_uint() == ntohl((1 << 24) | (2 << 16) | (3 << 8) | 4) ); + VERIFY( a1.to_uint() == ((1 << 24) | (2 << 16) | (3 << 8) | 4) ); VERIFY( a1.to_bytes() == b1 ); } -void +constexpr void test03() { - bool test __attribute__((unused)) = false; - address_v4 a0{ 0u }; VERIFY( a0.to_uint() == 0 ); VERIFY( a0.to_bytes() == address_v4::bytes_type{} ); - address_v4::uint_type u1 = ntohl((5 << 24) | (6 << 16) | (7 << 8) | 8); + address_v4::uint_type u1 = (5 << 24) | (6 << 16) | (7 << 8) | 8; address_v4 a1{ u1 }; VERIFY( a1.to_uint() == u1 ); VERIFY( a1.to_bytes() == address_v4::bytes_type( 5, 6, 7, 8 ) ); @@ -70,4 +74,11 @@ main() test01(); test02(); test03(); + + constexpr bool c = []{ + test01(); + test02(); + test03(); + return true; + }; } diff --git a/libstdc++-v3/testsuite/experimental/net/internet/address/v4/creation.cc b/libstdc++-v3/testsuite/experimental/net/internet/address/v4/creation.cc index 441c832bf54..84aebbb7adc 100644 --- a/libstdc++-v3/testsuite/experimental/net/internet/address/v4/creation.cc +++ b/libstdc++-v3/testsuite/experimental/net/internet/address/v4/creation.cc @@ -25,7 +25,17 @@ namespace net = std::experimental::net; using net::ip::address_v4; -void +#if __cplusplus < 202002L +// Naughty, but operator== for std::array is not constexpr until C++20. +constexpr bool +operator==(const address_v4::bytes_type& lhs, const address_v4::bytes_type& rhs) +{ + return lhs[0] == rhs[0] && lhs[1] == rhs[1] + && lhs[2] == rhs[2] && lhs[3] == rhs[3]; +} +#endif + +constexpr void test01() { auto a0 = make_address_v4( address_v4::bytes_type{} ); @@ -34,18 +44,18 @@ test01() address_v4::bytes_type b1{ 1, 2, 3, 4 }; auto a1 = make_address_v4( b1 ); - VERIFY( a1.to_uint() == ntohl((1 << 24) | (2 << 16) | (3 << 8) | 4) ); + VERIFY( a1.to_uint() == ((1 << 24) | (2 << 16) | (3 << 8) | 4) ); VERIFY( a1.to_bytes() == b1 ); } -void +constexpr void test02() { auto a0 = net::ip::make_address_v4(0u); VERIFY( a0.to_uint() == 0 ); VERIFY( a0.to_bytes() == address_v4::bytes_type{} ); - address_v4::uint_type u1 = ntohl((5 << 24) | (6 << 16) | (7 << 8) | 8); + address_v4::uint_type u1 = ((5 << 24) | (6 << 16) | (7 << 8) | 8); auto a1 = net::ip::make_address_v4( u1 ); VERIFY( a1.to_uint() == u1 ); VERIFY( a1.to_bytes() == address_v4::bytes_type( 5, 6, 7, 8 ) ); @@ -84,4 +94,10 @@ main() test01(); test02(); test03(); + + constexpr bool c = []{ + test01(); + test02(); + return true; + }; } diff --git a/libstdc++-v3/testsuite/experimental/net/internet/address/v4/members.cc b/libstdc++-v3/testsuite/experimental/net/internet/address/v4/members.cc index c40a8103664..ac59405c599 100644 --- a/libstdc++-v3/testsuite/experimental/net/internet/address/v4/members.cc +++ b/libstdc++-v3/testsuite/experimental/net/internet/address/v4/members.cc @@ -26,6 +26,9 @@ using std::experimental::net::ip::address_v4; +static_assert(std::is_standard_layout::value, + "net::ip::address_v4::bytes_type is a standard layout type"); + constexpr bool test01() {