From: Jonathan Wakely Date: Fri, 24 Feb 2023 10:08:26 +0000 (+0000) Subject: libstdc++: Fix conversion to/from net::ip::address_v4::bytes_type X-Git-Tag: basepoints/gcc-14~882 X-Git-Url: https://gcc.gnu.org/git/?a=commitdiff_plain;h=36ecfb75e053d54dd36dd3900d3096004f6d9aae;p=gcc.git 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 --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() {