From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2181) id 96803388A035; Fri, 7 May 2021 22:46:12 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 96803388A035 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jonathan Wakely To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r12-631] libstdc++: Fix constraints for rvalue stream insertion/extraction X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/heads/master X-Git-Oldrev: 7c4c9fcc0de865876fb25fe75f4ed6e143bd48c0 X-Git-Newrev: a87ceadf17b4a899f3e74e2da8b6b209461d2742 Message-Id: <20210507224612.96803388A035@sourceware.org> Date: Fri, 7 May 2021 22:46:12 +0000 (GMT) X-BeenThere: libstdc++-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 07 May 2021 22:46:12 -0000 https://gcc.gnu.org/g:a87ceadf17b4a899f3e74e2da8b6b209461d2742 commit r12-631-ga87ceadf17b4a899f3e74e2da8b6b209461d2742 Author: Jonathan Wakely Date: Thu May 6 19:14:42 2021 +0100 libstdc++: Fix constraints for rvalue stream insertion/extraction The __rval_streamable() function was an attempt to test for convertibility cheaply and without confusing diagnostics. It doesn't work with Clang though, and is probably ill-formed. Replace that helper function with a check for derivation from ios_base, and use that in the alias templates __rvalue_stream_insertion_t and __rvalue_stream_extraction_t. Use concepts for the constraints when available. libstdc++-v3/ChangeLog: * include/std/istream (__rvalue_stream_extraction_t): Replace use of __rval_streamable. * include/std/ostream (__rvalue_stream_insertion_t): Likewise. (__rval_streamable): Remove. (_Require_derived_from_ios_base, __derived_from_ios_base): New helper for checking constraints. * testsuite/27_io/basic_istream/extractors_other/char/4.cc: Fix reference to the wrong subclause of the standard. * testsuite/27_io/basic_istream/extractors_other/wchar_t/4.cc: Likewise. * testsuite/27_io/basic_ostream/inserters_other/char/6.cc: Likewise. * testsuite/27_io/basic_ostream/inserters_other/wchar_t/6.cc: Likewise. * testsuite/27_io/basic_ostream/inserters_other/char/99692.cc: New test. * testsuite/27_io/filesystem/path/io/dr2989.cc: Adjust pruned errors. Diff: --- libstdc++-v3/include/std/istream | 13 +++++--- libstdc++-v3/include/std/ostream | 36 ++++++++++------------ .../27_io/basic_istream/extractors_other/char/4.cc | 2 +- .../basic_istream/extractors_other/wchar_t/4.cc | 2 +- .../27_io/basic_ostream/inserters_other/char/6.cc | 2 +- .../basic_ostream/inserters_other/char/99692.cc | 34 ++++++++++++++++++++ .../basic_ostream/inserters_other/wchar_t/6.cc | 2 +- .../testsuite/27_io/filesystem/path/io/dr2989.cc | 1 - 8 files changed, 64 insertions(+), 28 deletions(-) diff --git a/libstdc++-v3/include/std/istream b/libstdc++-v3/include/std/istream index ea34cce6298..5ad60dbd709 100644 --- a/libstdc++-v3/include/std/istream +++ b/libstdc++-v3/include/std/istream @@ -958,12 +958,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // 2328. Rvalue stream extraction should use perfect forwarding // 1203. More useful rvalue stream insertion - // SFINAE helper to check constraints for operator>>(Istream&&, T&&). - // If the constraints are satisfied, it is an alias for Istream&&. +#if __cpp_lib_concepts + template + requires __derived_from_ios_base<_Is> + && requires (_Is& __is, _Tp&& __t) { __is >> std::forward<_Tp>(__t); } + using __rvalue_stream_extraction_t = _Is&&; +#else template() - >> std::declval<_Tp>())> + typename = _Require_derived_from_ios_base<_Is>, + typename = decltype(std::declval<_Is&>() >> std::declval<_Tp>())> using __rvalue_stream_extraction_t = _Is&&; +#endif /** * @brief Generic extractor for rvalue stream diff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream index fdd2a87665c..981697324c9 100644 --- a/libstdc++-v3/include/std/ostream +++ b/libstdc++-v3/include/std/ostream @@ -708,31 +708,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // _GLIBCXX_RESOLVE_LIB_DEFECTS // 1203. More useful rvalue stream insertion - // SFINAE helper to check constraints for operator<<(Ostream&&, const T&). - // If Ostream is publicly and unambiguously derived from ios_base, then - // __rval_streamable() is equivalent to declval(). - // Otherwise, it results in a substitution failure. Specifically, it will - // fail if Ostream is an lvalue reference or the same type as ios_base. - // Use concepts if possible because they're cheaper to evaluate. #if __cpp_lib_concepts + // Use concepts if possible because they're cheaper to evaluate. template - requires (!is_same_v<_Tp, ios_base>) - && requires (_Tp* __t, ios_base* __b) { __b = __t; } - _Tp& - __rval_streamable(); + concept __derived_from_ios_base = is_class_v<_Tp> + && (!is_same_v<_Tp, ios_base>) + && requires (_Tp* __t, ios_base* __b) { __b = __t; }; + + template + requires __derived_from_ios_base<_Os> + && requires (_Os& __os, const _Tp& __t) { __os << __t; } + using __rvalue_stream_insertion_t = _Os&&; #else - template>>> - _Tp& - __rval_streamable(ios_base* = (_Tp*)nullptr); -#endif + template + using _Require_derived_from_ios_base + = _Require, __not_>, + is_convertible::type, ios_base*>>; - // SFINAE helper to check constraints for operator<<(Ostream&&, const T&). - // If the constraints are satisfied, it is an alias for Ostream&&. template() - << std::declval())> + typename = _Require_derived_from_ios_base<_Os>, + typename + = decltype(std::declval<_Os&>() << std::declval())> using __rvalue_stream_insertion_t = _Os&&; +#endif /** * @brief Generic inserter for rvalue stream diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/char/4.cc b/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/char/4.cc index 9f1e293474f..94e41a17e82 100644 --- a/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/char/4.cc +++ b/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/char/4.cc @@ -17,7 +17,7 @@ // with this library; see the file COPYING3. If not see // . -// 27.6.2.5.3 basic_ostream manipulator inserters +// C++11 27.7.2.6 Rvalue stream extraction [istream.rvalue] #include diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/wchar_t/4.cc b/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/wchar_t/4.cc index fc7f5505bf4..b182be7ee3d 100644 --- a/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/wchar_t/4.cc +++ b/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/wchar_t/4.cc @@ -17,7 +17,7 @@ // with this library; see the file COPYING3. If not see // . -// 27.6.2.5.3 basic_ostream manipulator inserters +// C++11 27.7.2.6 Rvalue stream extraction [istream.rvalue] #include diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/char/6.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/char/6.cc index 4801afcba6c..3a748cd630b 100644 --- a/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/char/6.cc +++ b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/char/6.cc @@ -17,7 +17,7 @@ // with this library; see the file COPYING3. If not see // . -// 27.6.2.5.3 basic_ostream manipulator inserters +// C++11 27.7.3.9 Rvalue stream insertion [ostream.rvalue] #include diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/char/99692.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/char/99692.cc new file mode 100644 index 00000000000..e41399a1bf1 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/char/99692.cc @@ -0,0 +1,34 @@ +// { dg-do compile { target c++11 } } + +#include + +struct CustomStream : std::ostream {}; + +namespace N { + class A{}; +} + +std::ostream& operator<<(std::ostream& s, const N::A&) +{ + return s; +} + +CustomStream&& operator<<(CustomStream&& s, const N::A& v) +{ + static_cast(s) << v; + return std::move(s); +} + +void test_pr99692() +{ + // PR libstdc++/99692 + CustomStream() << N::A{}; +} + +int test_shift_ios_enum() +{ + // https://gcc.gnu.org/pipermail/libstdc++/2021-May/052507.html + int i = 1 << std::ios::erase_event; + + return i; +} diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/wchar_t/6.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/wchar_t/6.cc index 3efeb804b00..8fc0694dddc 100644 --- a/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/wchar_t/6.cc +++ b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/wchar_t/6.cc @@ -17,7 +17,7 @@ // with this library; see the file COPYING3. If not see // . -// 27.6.2.5.3 basic_ostream manipulator inserters +// C++11 27.7.3.9 Rvalue stream insertion [ostream.rvalue] #include diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/io/dr2989.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/io/dr2989.cc index 609f1c32a0e..c5cda776477 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/io/dr2989.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/io/dr2989.cc @@ -33,4 +33,3 @@ void foo(std::iostream& s) { s >> p; // { dg-error "no match" } } // { dg-prune-output "no type .*enable_if" } -// { dg-prune-output "no matching function for call to '__rval_streamable" }