public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jonathan Wakely <jwakely@redhat.com>
To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org
Subject: [committed 2/5] libstdc++: Fix conversion to/from net::ip::address_v4::bytes_type
Date: Fri, 24 Feb 2023 14:28:05 +0000	[thread overview]
Message-ID: <20230224142808.714075-2-jwakely@redhat.com> (raw)
In-Reply-To: <20230224142808.714075-1-jwakely@redhat.com>

Tested x86_64-linux. Pushed to trunk.

-- >8 --

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.
---
 libstdc++-v3/include/experimental/internet    | 20 ++++++++---
 .../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
+#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()
 {
-  bool test __attribute__((unused)) = false;
-
   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<address_v4::bytes_type>::value,
+    "net::ip::address_v4::bytes_type is a standard layout type");
+
 constexpr bool
 test01()
 {
-- 
2.39.2


  reply	other threads:[~2023-02-24 14:28 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-24 14:28 [committed 1/5] libstdc++: Optimize net::ip::address_v4::to_string() Jonathan Wakely
2023-02-24 14:28 ` Jonathan Wakely [this message]
2023-02-24 14:28 ` [committed 3/5] libstdc++: Fix members of net::ip::network_v4 Jonathan Wakely
2023-02-24 14:28 ` [committed 4/5] libstdc++: Make net::ip::basic_endpoint comparisons constexpr Jonathan Wakely
2023-02-24 14:28 ` [committed 5/5] libstdc++: Constrain net::executor constructors Jonathan Wakely

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230224142808.714075-2-jwakely@redhat.com \
    --to=jwakely@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=libstdc++@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).