From patchwork Sat Jun 10 01:38:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ville Voutilainen X-Patchwork-Id: 774182 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3wl1yx2Zm3z9s8V for ; Sat, 10 Jun 2017 11:38:48 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="B9c3LWlM"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=oaTDBsrHN4VLRlspKlY50Vrbf8NQ7ZDtomRYnoCH7V/ePu gwyRNgxW9Y3KZNUbvF26Xa9WQXOUHp/ajWeT+J7rGeJLtaSYvdbvS3bTy3taDGOL 9QnqF30zaYOcd3EIYkc0RbB4/mdAqfWkstgrd8eOSJ9u9CylKBeYnXNcKvUnE= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=H+yHhBfGqAtY2G45dUQFGc1TdwQ=; b=B9c3LWlMYhhM9OKht6ao HPJ+lpg6YpjZe6YwNwo+rc/edeDKB/focM9kklSU2a5C7Tu4Gm668zU4w/dH+Dv3 RDaE0ZQ4qv+lqOEjKVt1xAW6y835TTyPr/qb33w1reCRcGaYwlsaC5QZ/O5Z2yny acA4YZ9KlbLY6CSwz1SGuxk= Received: (qmail 94303 invoked by alias); 10 Jun 2017 01:38:31 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 94273 invoked by uid 89); 10 Jun 2017 01:38:30 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.4 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=2464, perfect X-Spam-User: qpsmtpd, 2 recipients X-HELO: mail-ot0-f179.google.com Received: from mail-ot0-f179.google.com (HELO mail-ot0-f179.google.com) (74.125.82.179) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 10 Jun 2017 01:38:28 +0000 Received: by mail-ot0-f179.google.com with SMTP id i31so46490212ota.3; Fri, 09 Jun 2017 18:38:32 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=yabbCjDNtDw8cBTbr6j3t0jrV6GNpzlADTC89woVYuU=; b=ZMHgJux2BnvKlkw9G9dNiegVMXPeVFOyET0HkXYSR5UkBPJusZU2P2iyaPUicoODCL WxBPjpw/6yfAWb/gSK9W5mr6j7iWFX8MtaSZaguOKez08cuAi9gRs7+sxErVRPnUULgo Jzr0kKe275YCWfDPTGBlaGOaFZKv9oQUpkJeb1sXb9WkO070PiZ+zVR/kVCrTD67wS/B wbKKYJ6HJwV8AC6p4U0dkwbl5/aqeSoqqIUJpTQhC7yEiGy2mUyuG7F9tMwzOzTy0zeo 9qotlB0XK/NIw+PZrn88It33L8f2aHjRZdhofbaddsZ8rglTMEFs9s+JBHZ8jrBF8nL9 6drQ== X-Gm-Message-State: AODbwcDo/utSyJvgSxkCPIxRqzWmREa0Wfap0rZVRn5WWkPOmv9Sa1PW XPLIkTgmDx/0rB5cBSAoabIy6QpJ90FA X-Received: by 10.157.52.98 with SMTP id v89mr21553737otb.160.1497058711109; Fri, 09 Jun 2017 18:38:31 -0700 (PDT) MIME-Version: 1.0 Received: by 10.157.11.237 with HTTP; Fri, 9 Jun 2017 18:38:30 -0700 (PDT) From: Ville Voutilainen Date: Sat, 10 Jun 2017 04:38:30 +0300 Message-ID: Subject: [v3 PATCH] PR libstdc++/80675, PR libstdc++/80940 To: "libstdc++" , "gcc-patches@gcc.gnu.org" Tested on Linux-x64. 2017-06-10 Ville Voutilainen PR libstdc++/80675 PR libstdc++/80940 * include/std/istream: (__is_convertible_to_basic_istream_test(basic_istream<_Ch, _Up>*)): New. (__do_is_convertible_to_basic_istream_impl): Likewise. (__is_convertible_to_basic_istream_impl): Likewise. (__is_convertible_to_basic_istream): Use the new base. (__rvalue_istream_type): New. (operator>>(_Istream&&, _Tp&&)): Use the new helper alias for the SFINAE check, convert to the helper alias type before doing the actual extraction. * include/std/ostream: (__is_convertible_to_basic_ostream_test(basic_ostream<_Ch, _Up>*)): New. (__do_is_convertible_to_basic_ostream_impl): Likewise. (__is_convertible_to_basic_ostream_impl): Likewise. (__is_convertible_to_basic_ostream): Use the new base. (__rvalue_ostream_type): New. (operator<<(_Ostream&&, const _Tp&)): Use the new helper alias for the SFINAE check, convert to the helper alias type before doing the actual insertion. * testsuite/27_io/rvalue_streams-2.cc: Add new tests. diff --git a/libstdc++-v3/include/std/istream b/libstdc++-v3/include/std/istream index 85c0a5a..86a5d03 100644 --- a/libstdc++-v3/include/std/istream +++ b/libstdc++-v3/include/std/istream @@ -908,20 +908,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ws(basic_istream<_CharT, _Traits>& __is); #if __cplusplus >= 201103L + template + basic_istream<_Ch, _Up>& + __is_convertible_to_basic_istream_test(basic_istream<_Ch, _Up>*); + + template + struct __is_convertible_to_basic_istream_impl + { + using __istream_type = void; + }; template - struct __is_convertible_to_basic_istream + using __do_is_convertible_to_basic_istream_impl = + decltype(__is_convertible_to_basic_istream_test + (declval::type*>())); + + template + struct __is_convertible_to_basic_istream_impl + <_Tp, + __void_t<__do_is_convertible_to_basic_istream_impl<_Tp>>> { - template - static basic_istream<_Ch, _Up>& __check(basic_istream<_Ch, _Up>*); + using __istream_type = + __do_is_convertible_to_basic_istream_impl<_Tp>; + }; - static void __check(...); + template + struct __is_convertible_to_basic_istream + : __is_convertible_to_basic_istream_impl<_Tp> + { public: - using istream_type = - decltype(__check(declval::type*>())); - using type = __not_>; + using type = __not_::__istream_type>>; constexpr static bool value = type::value; - }; + }; template struct __is_extractable : false_type {}; @@ -932,6 +951,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> declval<_Tp>())>> : true_type {}; + template + using __rvalue_istream_type = + typename __is_convertible_to_basic_istream< + _Istream>::__istream_type; + // [27.7.1.6] Rvalue stream extraction // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2328. Rvalue stream extraction should use perfect forwarding @@ -949,13 +973,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline typename enable_if<__and_<__not_>, __is_convertible_to_basic_istream<_Istream>, - __is_extractable<_Istream&, _Tp&&>>::value, - typename __is_convertible_to_basic_istream< - _Istream>::istream_type>::type + __is_extractable< + __rvalue_istream_type<_Istream>, + _Tp&&>>::value, + __rvalue_istream_type<_Istream>>::type operator>>(_Istream&& __is, _Tp&& __x) { - __is >> std::forward<_Tp>(__x); - return __is; + __rvalue_istream_type<_Istream> __ret_is = __is; + __ret_is >> std::forward<_Tp>(__x); + return __ret_is; } #endif // C++11 diff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream index 50b70a5..cffcd06 100644 --- a/libstdc++-v3/include/std/ostream +++ b/libstdc++-v3/include/std/ostream @@ -613,19 +613,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __os.flush(); } #if __cplusplus >= 201103L + template + basic_ostream<_Ch, _Up>& + __is_convertible_to_basic_ostream_test(basic_ostream<_Ch, _Up>*); + + template + struct __is_convertible_to_basic_ostream_impl + { + using __ostream_type = void; + }; + + template + using __do_is_convertible_to_basic_ostream_impl = + decltype(__is_convertible_to_basic_ostream_test + (declval::type*>())); + + template + struct __is_convertible_to_basic_ostream_impl + <_Tp, + __void_t<__do_is_convertible_to_basic_ostream_impl<_Tp>>> + { + using __ostream_type = + __do_is_convertible_to_basic_ostream_impl<_Tp>; + }; + template struct __is_convertible_to_basic_ostream - { - template - static basic_ostream<_Ch, _Up>& __check(basic_ostream<_Ch, _Up>*); - - static void __check(...); - public: - using ostream_type = - decltype(__check(declval::type*>())); - using type = __not_>; - constexpr static bool value = type::value; - }; + : __is_convertible_to_basic_ostream_impl<_Tp> + { + public: + using type = __not_::__ostream_type>>; + constexpr static bool value = type::value; + }; template struct __is_insertable : false_type {}; @@ -636,6 +656,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION << declval())>> : true_type {}; + template + using __rvalue_ostream_type = + typename __is_convertible_to_basic_ostream< + _Ostream>::__ostream_type; + /** * @brief Generic inserter for rvalue stream * @param __os An input stream. @@ -650,13 +675,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline typename enable_if<__and_<__not_>, __is_convertible_to_basic_ostream<_Ostream>, - __is_insertable<_Ostream&, const _Tp&>>::value, - typename __is_convertible_to_basic_ostream< - _Ostream>::ostream_type>::type + __is_insertable< + __rvalue_ostream_type<_Ostream>, + const _Tp&>>::value, + __rvalue_ostream_type<_Ostream>>::type operator<<(_Ostream&& __os, const _Tp& __x) { - __os << __x; - return __os; + __rvalue_ostream_type<_Ostream> __ret_os = __os; + __ret_os << __x; + return __ret_os; } #endif // C++11 diff --git a/libstdc++-v3/testsuite/27_io/rvalue_streams-2.cc b/libstdc++-v3/testsuite/27_io/rvalue_streams-2.cc index 2b46aa1..9c20274 100644 --- a/libstdc++-v3/testsuite/27_io/rvalue_streams-2.cc +++ b/libstdc++-v3/testsuite/27_io/rvalue_streams-2.cc @@ -24,11 +24,64 @@ struct A {}; void operator<<(std::ostream&, const A&) { } void operator>>(std::istream&, A&) { } +class MyStream : private std::ostream, private std::istream +{ +public: + MyStream& operator <<(const char*) + { + return *this; + } + MyStream& operator >>(int&) + { + return *this; + } +}; + +class MyStream2 +{ +public: + MyStream2& operator <<(const char*) + { + return *this; + } + MyStream2& operator >>(int&) + { + return *this; + } +private: + operator std::ostream&(); + operator std::istream&(); +}; + +struct X { }; + +std::ostream& operator<<(std::ostream& os, const X&) { return os; } +std::istream& operator>>(std::istream& is, X&&) { return is; } + +struct O : std::ostream { }; + +void operator<<(O&, X) = delete; + +struct I : std::istream { }; + +void operator>>(I&, X) = delete; + // PR libstdc++/65543 +// PR libstdc++/80675 +// PR libstdc++/80940 int main() { A a; std::ostringstream() << a; std::istringstream() >> a; + MyStream stream{}; + stream << "aaa"; + int msi; + stream >> msi; + MyStream2 stream2{}; + stream2 << "aaa"; + stream2 >> msi; + O{} << X{}; + I{} >> X{}; }