public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-7149] libstdc++: Initialize all members of basic_endpoint union [PR109482]
@ 2023-04-12 12:27 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2023-04-12 12:27 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:9f10b4957ca6058d1a801c5e4bfe11bf159da809

commit r13-7149-g9f10b4957ca6058d1a801c5e4bfe11bf159da809
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Apr 12 11:55:24 2023 +0100

    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.

Diff:
---
 libstdc++-v3/include/experimental/internet         | 22 ++++++++++++++----
 .../experimental/net/internet/endpoint/cons.cc     | 27 +++++++++++-----------
 .../net/internet/endpoint/extensible.cc            |  4 ++++
 3 files changed, 35 insertions(+), 18 deletions(-)

diff --git a/libstdc++-v3/include/experimental/internet b/libstdc++-v3/include/experimental/internet
index eb23ae21cdc..1f63c61ce85 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];
diff --git a/libstdc++-v3/testsuite/experimental/net/internet/endpoint/cons.cc b/libstdc++-v3/testsuite/experimental/net/internet/endpoint/cons.cc
index b4bef88b4a3..d54b0c9550b 100644
--- a/libstdc++-v3/testsuite/experimental/net/internet/endpoint/cons.cc
+++ b/libstdc++-v3/testsuite/experimental/net/internet/endpoint/cons.cc
@@ -7,7 +7,10 @@
 
 using namespace std::experimental::net;
 
-constexpr void
+#if __cplusplus >= 202002
+constexpr
+#endif
+void
 test_default()
 {
   ip::tcp::endpoint t1;
@@ -57,23 +60,19 @@ test_addr()
   VERIFY( t2.port() == 80 );
 }
 
-constexpr bool
-test_constexpr()
-{
-  test_default();
-#if __cplusplus >= 202002
-  // Non-default basic_endpoint constructors are only constexpr in C++20.
-  test_proto();
-  test_addr();
-#endif
-  return true;
-}
-
 int main()
 {
   test_default();
   test_proto();
   test_addr();
 
-  static_assert( test_constexpr(), "valid in constant expressions" );
+#if __cplusplus >= 202002
+  // basic_endpoint constructors are only constexpr in C++20.
+  constexpr bool b = []{
+    test_default();
+    test_proto();
+    test_addr();
+    return true;
+  }();
+#endif
 }
diff --git a/libstdc++-v3/testsuite/experimental/net/internet/endpoint/extensible.cc b/libstdc++-v3/testsuite/experimental/net/internet/endpoint/extensible.cc
index d205024c799..ffc43cf17b6 100644
--- a/libstdc++-v3/testsuite/experimental/net/internet/endpoint/extensible.cc
+++ b/libstdc++-v3/testsuite/experimental/net/internet/endpoint/extensible.cc
@@ -11,8 +11,12 @@ using namespace std::experimental::net;
 void
 test_extensible()
 {
+#if __cplusplus >= 202002L
   static_assert(ip::tcp::endpoint().capacity() == sizeof(sockaddr_in6),
 		"ip::tcp::endpoint::capacity() can store a sockaddr_in6");
+#else
+  VERIFY( ip::tcp::endpoint().capacity() == sizeof(sockaddr_in6) );
+#endif
 
   ip::tcp::endpoint t1(ip::tcp::v4(), 22);
   VERIFY(t1.size() == sizeof(sockaddr_in));

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-04-12 12:27 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-12 12:27 [gcc r13-7149] libstdc++: Initialize all members of basic_endpoint union [PR109482] Jonathan Wakely

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).