From patchwork Tue Apr 27 13:10:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 1470690 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=NpvZoAZ8; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FV2F928GKz9sPf for ; Tue, 27 Apr 2021 23:10:37 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9C861398B865; Tue, 27 Apr 2021 13:10:26 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9C861398B865 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1619529026; bh=amwpgq8gDpxFQQ5Iicn4bNXMWnUZ8/he+XgR8TJ/Dgk=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=NpvZoAZ8beensJwdCZ60AUR+WgOEDRSTYVooo0cTYXKGwBovn5P3pwCuTnM4G+sX4 ZDt031asOu73A/txM8B1Tk5yidAyd8E7T7wY9R4cFuVCIejLTghyobFZ9+sKoZOBep gpgDHWfmnxp5Ps5MGkzhFaL96rQn53FztHx384z4= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by sourceware.org (Postfix) with ESMTP id 029C8398B426 for ; Tue, 27 Apr 2021 13:10:23 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 029C8398B426 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-467-TR-1q-9SO1yjWpsM-mQi_g-1; Tue, 27 Apr 2021 09:10:21 -0400 X-MC-Unique: TR-1q-9SO1yjWpsM-mQi_g-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 389C419253C0; Tue, 27 Apr 2021 13:10:20 +0000 (UTC) Received: from localhost (unknown [10.33.36.164]) by smtp.corp.redhat.com (Postfix) with ESMTP id DB3566267F; Tue, 27 Apr 2021 13:10:19 +0000 (UTC) Date: Tue, 27 Apr 2021 14:10:19 +0100 To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Better preprocessor conditions in net::ip [PR 100286] Message-ID: MIME-Version: 1.0 X-Clacks-Overhead: GNU Terry Pratchett X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-14.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jonathan Wakely via Gcc-patches From: Jonathan Wakely Reply-To: Jonathan Wakely Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" This improves the use of preprocessor conditionas to enable/disable members of namespace net::ip according to what is supported by the target. This fixes PR 100286 by ensuring that the to_string member functions are always defined for the address_v4 and address_v6 classes. On the other hand, the IP protocol classes and internet socket option classes aren't useful at all if the corresponding constants (such as IPPROTO_TCP or IPV6_MULTICAST_HOPS) aren't define. So those types are not defined at all if they can't be used. The net/internet/socket/opt.cc test uses __has_include to check whether or not to expect the types to be available. libstdc++-v3/ChangeLog: PR libstdc++/100286 * include/experimental/internet (resolver_errc, resolver_category()) (make_error_code, make_error_condition): Define unconditionally, only make enumerators and use of gai_strerror depend on the availability of . (address_v4::to_string): Use correct constant for string length. (address_v4::to_string, address_v6::to_string): Define unconditionally, throw if unsupported. (make_address_v4, make_address_v6): Define unconditionally. Return an error if unsupported. (tcp, udp, v6_only, unicast::hops, multicast::*): Define conditionally, * testsuite/experimental/net/internet/socket/opt.cc: Check for and before using types from namespace net::ip. Tested x86_64-linux. Committed to trunk. commit 9ee35a8685ee174c6914059143aceb7009d3e920 Author: Jonathan Wakely Date: Tue Apr 27 13:06:43 2021 libstdc++: Better preprocessor conditions in net::ip [PR 100286] This improves the use of preprocessor conditionas to enable/disable members of namespace net::ip according to what is supported by the target. This fixes PR 100286 by ensuring that the to_string member functions are always defined for the address_v4 and address_v6 classes. On the other hand, the IP protocol classes and internet socket option classes aren't useful at all if the corresponding constants (such as IPPROTO_TCP or IPV6_MULTICAST_HOPS) aren't define. So those types are not defined at all if they can't be used. The net/internet/socket/opt.cc test uses __has_include to check whether or not to expect the types to be available. libstdc++-v3/ChangeLog: PR libstdc++/100286 * include/experimental/internet (resolver_errc, resolver_category()) (make_error_code, make_error_condition): Define unconditionally, only make enumerators and use of gai_strerror depend on the availability of . (address_v4::to_string): Use correct constant for string length. (address_v4::to_string, address_v6::to_string): Define unconditionally, throw if unsupported. (make_address_v4, make_address_v6): Define unconditionally. Return an error if unsupported. (tcp, udp, v6_only, unicast::hops, multicast::*): Define conditionally, * testsuite/experimental/net/internet/socket/opt.cc: Check for and before using types from namespace net::ip. diff --git a/libstdc++-v3/include/experimental/internet b/libstdc++-v3/include/experimental/internet index 11961762880..6c3fad6d2aa 100644 --- a/libstdc++-v3/include/experimental/internet +++ b/libstdc++-v3/include/experimental/internet @@ -72,20 +72,20 @@ inline namespace v1 { namespace ip { - /** @addtogroup networking-ts * @{ */ -#ifdef _GLIBCXX_HAVE_NETDB_H /** Error codes for resolver errors. * @{ */ enum class resolver_errc : int { +#ifdef _GLIBCXX_HAVE_NETDB_H host_not_found = EAI_NONAME, host_not_found_try_again = EAI_AGAIN, service_not_found = EAI_SERVICE +#endif }; /// Error category for resolver errors. @@ -94,7 +94,13 @@ namespace ip struct __cat : error_category { const char* name() const noexcept { return "resolver"; } - std::string message(int __e) const { return ::gai_strerror(__e); } + std::string message(int __e) const { +#ifdef _GLIBCXX_HAVE_NETDB_H + return ::gai_strerror(__e); +#else + return "name resolution requires "; +#endif + } virtual void __message(int) { } // TODO dual ABI XXX }; static __cat __c; @@ -108,7 +114,6 @@ namespace ip { return error_condition(static_cast(__e), resolver_category()); } /// @} -#endif using port_type = uint_least16_t; ///< Type used for port numbers. using scope_id_type = uint_least32_t; ///< Type used for IPv6 scope IDs. @@ -119,6 +124,16 @@ namespace ip = enable_if_t::value, std::basic_string, _Alloc>>; + constexpr errc + __unsupported_err() noexcept + { +#if defined EAFNOSUPPORT + return std::errc::address_family_not_supported; +#else + return std::errc::operation_not_supported; +#endif + } + /** Tag indicating conversion between IPv4 and IPv4-mapped IPv6 addresses. * @{ */ @@ -197,20 +212,22 @@ namespace ip constexpr uint_type to_uint() const noexcept { return _S_ntoh_32(_M_addr); } -#ifdef _GLIBCXX_HAVE_ARPA_INET_H template> __string_with<_Allocator> to_string(const _Allocator& __a = _Allocator()) const { +#ifdef _GLIBCXX_HAVE_ARPA_INET_H __string_with<_Allocator> __str(__a); - __str.resize(INET6_ADDRSTRLEN); + __str.resize(INET_ADDRSTRLEN); if (inet_ntop(AF_INET, &_M_addr, &__str.front(), __str.size())) __str.erase(__str.find('\0')); else __str.resize(0); return __str; - } +#else + std::__throw_system_error((int)__unsupported_err()); #endif + } // static members: static constexpr address_v4 any() noexcept { return address_v4{}; } @@ -338,11 +355,11 @@ namespace ip constexpr bytes_type to_bytes() const noexcept { return _M_bytes; } -#ifdef _GLIBCXX_HAVE_ARPA_INET_H template> __string_with<_Allocator> to_string(const _Allocator& __a = _Allocator()) const { +#ifdef _GLIBCXX_HAVE_ARPA_INET_H __string_with<_Allocator> __str(__a); __str.resize(INET6_ADDRSTRLEN + (_M_scope_id ? 11 : 0)); char* const __p = &__str.front(); @@ -364,8 +381,10 @@ namespace ip else __str.resize(0); return __str; - } +#else + std::__throw_system_error((int)__unsupported_err()); #endif + } // static members: @@ -650,6 +669,7 @@ namespace ip inline address_v4 make_address_v4(const char* __str, error_code& __ec) noexcept { +#ifdef _GLIBCXX_HAVE_ARPA_INET_H address_v4 __a; const int __res = ::inet_pton(AF_INET, __str, &__a._M_addr); if (__res == 1) @@ -661,6 +681,9 @@ namespace ip __ec = std::make_error_code(std::errc::invalid_argument); else __ec.assign(errno, generic_category()); +#else + __ec = std::make_error_code(__unsupported_err()); +#endif return {}; } @@ -718,8 +741,9 @@ namespace ip inline address_v6 __make_address_v6(const char* __addr, const char* __scope, error_code& __ec) { +#ifdef _GLIBCXX_HAVE_ARPA_INET_H address_v6::bytes_type __b; - int __res = ::inet_pton(AF_INET6, __addr, __b.data()); + const int __res = ::inet_pton(AF_INET6, __addr, __b.data()); if (__res == 1) { __ec.clear(); @@ -741,6 +765,9 @@ namespace ip __ec = std::make_error_code(std::errc::invalid_argument); else __ec.assign(errno, generic_category()); +#else + __ec = std::make_error_code(__unsupported_err()); +#endif return {}; } @@ -2062,6 +2089,7 @@ namespace ip /// @} +#ifdef IPPROTO_TCP /// The TCP byte-stream protocol. class tcp { @@ -2073,7 +2101,7 @@ namespace ip using acceptor = basic_socket_acceptor; ///< A TCP acceptor. using iostream = basic_socket_iostream; /// A TCP iostream. -#ifdef _GLIBCXX_HAVE_NETINET_TCP_H +#ifdef TCP_NODELAY /// Disable coalescing of small segments (i.e. the Nagle algorithm). struct no_delay : __sockopt_crtp { @@ -2117,7 +2145,9 @@ namespace ip { return !(__a == __b); } /// @} +#endif // IPPROTO_TCP +#ifdef IPPROTO_UDP /// The UDP datagram protocol. class udp { @@ -2156,6 +2186,9 @@ namespace ip { return !(__a == __b); } /// @} +#endif // IPPROTO_UDP + +#if defined IPPROTO_IP && defined IPPROTO_IPV6 /// Restrict a socket created for an IPv6 protocol to IPv6 only. class v6_only : public __sockopt_crtp @@ -2371,6 +2404,8 @@ namespace ip } // namespace multicast +#endif // IPPROTO_IP && IPPROTO_IPV6 + /// @} } // namespace ip diff --git a/libstdc++-v3/testsuite/experimental/net/internet/socket/opt.cc b/libstdc++-v3/testsuite/experimental/net/internet/socket/opt.cc index 68bac84a8b1..cfbc00f9da8 100644 --- a/libstdc++-v3/testsuite/experimental/net/internet/socket/opt.cc +++ b/libstdc++-v3/testsuite/experimental/net/internet/socket/opt.cc @@ -49,8 +49,10 @@ template void check_boolean_sockopt() { namespace ip = std::experimental::net::ip; +#if __has_include() check_gettable_sockopt(ip::tcp::v4()); check_settable_sockopt(ip::tcp::v4()); +#endif static_assert( is_destructible(), "" ); static_assert( is_nothrow_default_constructible(), "" ); @@ -74,8 +76,10 @@ template void check_integer_sockopt() { namespace ip = std::experimental::net::ip; +#if __has_include() check_gettable_sockopt(ip::tcp::v4()); check_settable_sockopt(ip::tcp::v4()); +#endif static_assert( is_destructible(), "" ); static_assert( is_nothrow_default_constructible(), "" ); @@ -97,8 +101,10 @@ void check_mcast_sockopt(C& c) static_assert( is_copy_constructible(), "" ); static_assert( is_copy_assignable(), "" ); +#if __has_include() check_settable_sockopt(ip::tcp::v6(), c); check_settable_sockopt(ip::tcp::v4(), c); +#endif static_assert( is_nothrow_constructible(), "" ); static_assert( ! is_convertible(), "explicit" ); @@ -113,8 +119,11 @@ void check_mcast_sockopt(C& c) void test_option_types() { namespace ip = std::experimental::net::ip; + #if __has_include() +#if __has_include() check_boolean_sockopt(); +#endif check_boolean_sockopt();