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.
This commit is contained in:
Jonathan Wakely 2021-04-23 13:25:56 +01:00
parent 87fc34a461
commit a752a43073
3 changed files with 173 additions and 30 deletions

View 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

View File

@ -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, "" );
}

View 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