From a752a43073dc49909c017fd52feacd7526ed31c0 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 23 Apr 2021 13:25:56 +0100 Subject: [PATCH] libstdc++ Simplify definition of net::socket_base constants 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 | 59 +++++++------ .../experimental/net/socket/socket_base.cc | 45 ++++++++++ .../testsuite/util/testsuite_common_types.h | 99 ++++++++++++++++++++++ 3 files changed, 173 insertions(+), 30 deletions(-) create mode 100644 libstdc++-v3/testsuite/experimental/net/socket/socket_base.cc diff --git a/libstdc++-v3/include/experimental/socket b/libstdc++-v3/include/experimental/socket index a5a23ed..ec4ed9d 100644 --- a/libstdc++-v3/include/experimental/socket +++ b/libstdc++-v3/include/experimental/socket @@ -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 index 0000000..b0b02b4 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/net/socket/socket_base.cc @@ -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 +// . + +// { dg-do compile { target c++14 } } + +#include +#include + +using S = std::experimental::net::socket_base; +using namespace std; + +void test_constants() +{ + static_assert( is_enum::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::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::value, "" ); +} + diff --git a/libstdc++-v3/testsuite/util/testsuite_common_types.h b/libstdc++-v3/testsuite/util/testsuite_common_types.h index a87aa0f..a9a44df 100644 --- a/libstdc++-v3/testsuite/util/testsuite_common_types.h +++ b/libstdc++-v3/testsuite/util/testsuite_common_types.h @@ -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 + constexpr bool + test_bitmask_values(std::initializer_list elements, + std::initializer_list 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 -- 2.7.4