libstdc++ Simplify definition of net::socket_base constants
authorJonathan Wakely <jwakely@redhat.com>
Fri, 23 Apr 2021 12:25:56 +0000 (13:25 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Fri, 23 Apr 2021 12:54:34 +0000 (13:54 +0100)
libstdc++-v3/ChangeLog:

* include/experimental/socket (socket_base::shutdown_type):
(socket_base::wait_type, socket_base::message_flags):
Remove enumerators. Initialize constants directly with desired
values.
(socket_base::message_flags): Make all operators constexpr and
noexcept.
* testsuite/util/testsuite_common_types.h (test_bitmask_values):
New test utility.
* testsuite/experimental/net/socket/socket_base.cc: New test.

libstdc++-v3/include/experimental/socket
libstdc++-v3/testsuite/experimental/net/socket/socket_base.cc [new file with mode: 0644]
libstdc++-v3/testsuite/util/testsuite_common_types.h

index a5a23ed..ec4ed9d 100644 (file)
@@ -250,37 +250,29 @@ inline namespace v1
       static const int _S_name = SO_SNDLOWAT;
     };
 
-    enum shutdown_type : int
-    {
-      __shutdown_receive       = SHUT_RD,
-      __shutdown_send          = SHUT_WR,
-      __shutdown_both          = SHUT_RDWR
-    };
-    static constexpr shutdown_type shutdown_receive    = __shutdown_receive;
-    static constexpr shutdown_type shutdown_send       = __shutdown_send;
-    static constexpr shutdown_type shutdown_both       = __shutdown_both;
+    enum shutdown_type : int { };
+    static constexpr shutdown_type shutdown_receive = (shutdown_type)SHUT_RD;
+    static constexpr shutdown_type shutdown_send    = (shutdown_type)SHUT_WR;
+    static constexpr shutdown_type shutdown_both    = (shutdown_type)SHUT_RDWR;
 
+    enum wait_type : int { };
 #ifdef _GLIBCXX_HAVE_POLL_H
-    enum wait_type : int
-    {
-      __wait_read              = POLLIN,
-      __wait_write             = POLLOUT,
-      __wait_error             = POLLERR
-    };
-    static constexpr wait_type wait_read               = __wait_read;
-    static constexpr wait_type wait_write              = __wait_write;
-    static constexpr wait_type wait_error              = __wait_error;
+    static constexpr wait_type wait_read  = (wait_type)POLLIN;
+    static constexpr wait_type wait_write = (wait_type)POLLOUT;
+    static constexpr wait_type wait_error = (wait_type)POLLERR;
+#else
+    static constexpr wait_type wait_read  = (wait_type)1;
+    static constexpr wait_type wait_write = (wait_type)2;
+    static constexpr wait_type wait_error = (wait_type)4;
 #endif
 
-    enum message_flags : int
-    {
-      __message_peek           = MSG_PEEK,
-      __message_oob            = MSG_OOB,
-      __message_dontroute      = MSG_DONTROUTE
-    };
-    static constexpr message_flags message_peek                = __message_peek;
-    static constexpr message_flags message_out_of_band = __message_oob;
-    static constexpr message_flags message_do_not_route        = __message_dontroute;
+    enum message_flags : int { };
+    static constexpr message_flags message_peek
+      = (message_flags)MSG_PEEK;
+    static constexpr message_flags message_out_of_band
+      = (message_flags)MSG_OOB;
+    static constexpr message_flags message_do_not_route
+      = (message_flags)MSG_DONTROUTE;
 
     static const int max_listen_connections = SOMAXCONN;
 #endif
@@ -350,30 +342,37 @@ inline namespace v1
 
   constexpr socket_base::message_flags
   operator&(socket_base::message_flags __f1, socket_base::message_flags __f2)
+    noexcept
   { return socket_base::message_flags( int(__f1) & int(__f2) ); }
 
   constexpr socket_base::message_flags
   operator|(socket_base::message_flags __f1, socket_base::message_flags __f2)
+    noexcept
   { return socket_base::message_flags( int(__f1) | int(__f2) ); }
 
   constexpr socket_base::message_flags
   operator^(socket_base::message_flags __f1, socket_base::message_flags __f2)
+    noexcept
   { return socket_base::message_flags( int(__f1) ^ int(__f2) ); }
 
   constexpr socket_base::message_flags
   operator~(socket_base::message_flags __f)
+    noexcept
   { return socket_base::message_flags( ~int(__f) ); }
 
-  inline socket_base::message_flags&
+  constexpr socket_base::message_flags&
   operator&=(socket_base::message_flags& __f1, socket_base::message_flags __f2)
+    noexcept
   { return __f1 = (__f1 & __f2); }
 
-  inline socket_base::message_flags&
+  constexpr socket_base::message_flags&
   operator|=(socket_base::message_flags& __f1, socket_base::message_flags __f2)
+    noexcept
   { return __f1 = (__f1 | __f2); }
 
-  inline socket_base::message_flags&
+  constexpr socket_base::message_flags&
   operator^=(socket_base::message_flags& __f1, socket_base::message_flags __f2)
+    noexcept
   { return __f1 = (__f1 ^ __f2); }
 
 #if _GLIBCXX_HAVE_UNISTD_H
diff --git a/libstdc++-v3/testsuite/experimental/net/socket/socket_base.cc b/libstdc++-v3/testsuite/experimental/net/socket/socket_base.cc
new file mode 100644 (file)
index 0000000..b0b02b4
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright (C) 2020-2021 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++14 } }
+
+#include <experimental/socket>
+#include <testsuite_common_types.h>
+
+using S = std::experimental::net::socket_base;
+using namespace std;
+
+void test_constants()
+{
+  static_assert( is_enum<S::shutdown_type>::value, "" );
+  static_assert( S::shutdown_receive != S::shutdown_send, "" );
+  static_assert( S::shutdown_receive != S::shutdown_both, "" );
+  static_assert( S::shutdown_send != S::shutdown_both, "" );
+
+  static_assert( is_enum<S::wait_type>::value, "" );
+  static_assert( S::wait_read != S::wait_write, "");
+  static_assert( S::wait_read != S::wait_error, "");
+  static_assert( S::wait_write != S::wait_error, "");
+
+  static_assert( __gnu_test::test_bitmask_values(
+       {S::message_peek, S::message_out_of_band, S::message_do_not_route}
+       ), "each bitmask element is distinct" );
+
+  auto m = &S::max_listen_connections;
+  static_assert( is_same<decltype(m), const int*>::value, "" );
+}
+
index a87aa0f..a9a44df 100644 (file)
@@ -952,5 +952,104 @@ namespace __gnu_test
       }
   };
 #endif
+
+#if __cplusplus >= 201402L
+  // Check that bitmask type T supports all the required operators,
+  // with the required semantics. Check that each bitmask element
+  // has a distinct, nonzero value, and that each bitmask constant
+  // has no bits set which do not correspond to a bitmask element.
+  template<typename T>
+    constexpr bool
+    test_bitmask_values(std::initializer_list<T> elements,
+                       std::initializer_list<T> constants = {})
+    {
+      const T t0{};
+
+      if (!(t0 == t0))
+       return false;
+      if (t0 != t0)
+       return false;
+
+      if (t0 & t0)
+       return false;
+      if (t0 | t0)
+       return false;
+      if (t0 ^ t0)
+       return false;
+
+      T all = t0;
+
+      for (auto t : elements)
+       {
+         // Each bitmask element has a distinct value.
+         if (t & all)
+           return false;
+
+         // Each bitmask element has a nonzero value.
+         if (!bool(t))
+           return false;
+
+         // Check operators
+
+         if (!(t == t))
+           return false;
+         if (t != t)
+           return false;
+         if (t == t0)
+           return false;
+         if (t == all)
+           return false;
+
+         if (t & t0)
+           return false;
+         if ((t | t0) != t)
+           return false;
+         if ((t ^ t0) != t)
+           return false;
+
+         if ((t & t) != t)
+           return false;
+         if ((t | t) != t)
+           return false;
+         if (t ^ t)
+           return false;
+
+         T t1 = t;
+         if ((t1 &= t) != t)
+           return false;
+         if ((t1 |= t) != t)
+           return false;
+         if (t1 ^= t)
+           return false;
+
+         t1 = all;
+         if ((t1 &= t) != (all & t))
+           return false;
+         t1 = all;
+         if ((t1 |= t) != (all | t))
+           return false;
+         t1 = all;
+         if ((t1 ^= t) != (all ^ t))
+           return false;
+
+         all |= t;
+         if (!(all & t))
+           return false;
+       }
+
+      for (auto t : constants)
+       {
+         // Check that bitmask constants are composed of the bitmask elements.
+         if ((t & all) != t)
+           return false;
+         if ((t | all) != all)
+           return false;
+       }
+
+      return true;
+    }
+#endif // C++14
+
+
 } // namespace __gnu_test
 #endif