From mboxrd@z Thu Jan 1 00:00:00 1970
Return-Path:
Received: by sourceware.org (Postfix, from userid 2181)
id D0D5B3855037; Mon, 28 Jun 2021 13:23:32 +0000 (GMT)
DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D0D5B3855037
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-1843] libstdc++: Implement LWG 415 for std::ws
X-Act-Checkin: gcc
X-Git-Author: Jonathan Wakely
X-Git-Refname: refs/heads/master
X-Git-Oldrev: b838641bb0d4de5b25128b54012155ab46f452d0
X-Git-Newrev: e5c422b7d8af6f42f8ab230133210742b7ac5661
Message-Id: <20210628132332.D0D5B3855037@sourceware.org>
Date: Mon, 28 Jun 2021 13:23:32 +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: Mon, 28 Jun 2021 13:23:32 -0000
https://gcc.gnu.org/g:e5c422b7d8af6f42f8ab230133210742b7ac5661
commit r12-1843-ge5c422b7d8af6f42f8ab230133210742b7ac5661
Author: Jonathan Wakely
Date: Fri Jun 25 21:33:02 2021 +0100
libstdc++: Implement LWG 415 for std::ws
For C++11 std::ws changed to be an unformatted input function, meaning
it constructs a sentry and sets badbit on exceptions.
libstdc++-v3/ChangeLog:
* doc/xml/manual/intro.xml: Document LWG 415 change.
* doc/html/manual/bugs.html: Regenerate.
* include/bits/istream.tcc (ws): Create sentry and catch
exceptions.
* testsuite/27_io/basic_istream/ws/char/lwg415.cc: New test.
* testsuite/27_io/basic_istream/ws/wchar_t/lwg415.cc: New test.
Diff:
---
libstdc++-v3/doc/html/manual/bugs.html | 4 ++
libstdc++-v3/doc/xml/manual/intro.xml | 7 ++
libstdc++-v3/include/bits/istream.tcc | 46 ++++++++++---
.../27_io/basic_istream/ws/char/lwg415.cc | 77 ++++++++++++++++++++++
.../27_io/basic_istream/ws/wchar_t/lwg415.cc | 77 ++++++++++++++++++++++
5 files changed, 201 insertions(+), 10 deletions(-)
diff --git a/libstdc++-v3/doc/html/manual/bugs.html b/libstdc++-v3/doc/html/manual/bugs.html
index 7b49e4ab87c..38594a9b75a 100644
--- a/libstdc++-v3/doc/html/manual/bugs.html
+++ b/libstdc++-v3/doc/html/manual/bugs.html
@@ -245,6 +245,10 @@
409:
Closing an fstream should clear the error state
Have open
clear the error flags.
+
415:
+ Behavior of std::ws
+ Change it to be an unformatted input function
+ (i.e. construct a sentry and catch exceptions).
431:
Swapping containers with unequal allocators
Implement Option 3, as per N1599.
diff --git a/libstdc++-v3/doc/xml/manual/intro.xml b/libstdc++-v3/doc/xml/manual/intro.xml
index 45762caa711..86ed6964b6a 100644
--- a/libstdc++-v3/doc/xml/manual/intro.xml
+++ b/libstdc++-v3/doc/xml/manual/intro.xml
@@ -634,6 +634,13 @@ requirements of the license of GCC.
Have open
clear the error flags.
+ 415:
+ Behavior of std::ws
+
+ Change it to be an unformatted input function
+ (i.e. construct a sentry and catch exceptions).
+
+
431:
Swapping containers with unequal allocators
diff --git a/libstdc++-v3/include/bits/istream.tcc b/libstdc++-v3/include/bits/istream.tcc
index 1b046bec937..2a153c2e140 100644
--- a/libstdc++-v3/include/bits/istream.tcc
+++ b/libstdc++-v3/include/bits/istream.tcc
@@ -1057,17 +1057,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef typename __istream_type::int_type __int_type;
typedef ctype<_CharT> __ctype_type;
- const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
- const __int_type __eof = _Traits::eof();
- __streambuf_type* __sb = __in.rdbuf();
- __int_type __c = __sb->sgetc();
-
- while (!_Traits::eq_int_type(__c, __eof)
- && __ct.is(ctype_base::space, _Traits::to_char_type(__c)))
- __c = __sb->snextc();
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 451. behavior of std::ws
+ typename __istream_type::sentry __cerb(__in, true);
+ if (__cerb)
+ {
+ ios_base::iostate __err = ios_base::goodbit;
+ __try
+ {
+ const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
+ const __int_type __eof = _Traits::eof();
+ __streambuf_type* __sb = __in.rdbuf();
+ __int_type __c = __sb->sgetc();
- if (_Traits::eq_int_type(__c, __eof))
- __in.setstate(ios_base::eofbit);
+ while (true)
+ {
+ if (_Traits::eq_int_type(__c, __eof))
+ {
+ __err = ios_base::eofbit;
+ break;
+ }
+ if (!__ct.is(ctype_base::space, _Traits::to_char_type(__c)))
+ break;
+ __c = __sb->snextc();
+ }
+ }
+ __catch (const __cxxabiv1::__forced_unwind&)
+ {
+ __in._M_setstate(ios_base::badbit);
+ __throw_exception_again;
+ }
+ __catch (...)
+ {
+ __in._M_setstate(ios_base::badbit);
+ }
+ if (__err)
+ __in.setstate(__err);
+ }
return __in;
}
diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/ws/char/lwg415.cc b/libstdc++-v3/testsuite/27_io/basic_istream/ws/char/lwg415.cc
new file mode 100644
index 00000000000..fe6980dff29
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_istream/ws/char/lwg415.cc
@@ -0,0 +1,77 @@
+#include
+
+// C++11 27.7.2.4 Standard basic_istream manipulators [istream.manip]
+//
+// LWG 415. behavior of std::ws
+// std::ws is an unformatted input function.
+
+#include
+#include
+#include
+
+void
+test01()
+{
+ std::istream is(0);
+ VERIFY( is.rdstate() == std::ios_base::badbit );
+
+ is >> std::ws; // sentry should set failbit
+ VERIFY( is.rdstate() & std::ios_base::failbit );
+}
+
+void
+test02()
+{
+ __gnu_test::sync_streambuf buf;
+ std::istream is(&buf);
+
+ __gnu_test::sync_streambuf buf_tie;
+ std::ostream os_tie(&buf_tie);
+
+ // A sentry should be constructed so is.tie()->flush() should be called.
+ // The standard allows the flush to be deferred because the put area of
+ // is_tie is empty, but libstdc++ doesn't defer it.
+ is.tie(&os_tie);
+
+ is >> std::ws;
+
+ VERIFY( is.eof() );
+ VERIFY( !is.fail() );
+ VERIFY( ! buf.sync_called() );
+ VERIFY( buf_tie.sync_called() );
+}
+
+void
+test03()
+{
+ __gnu_test::fail_streambuf buf;
+ std::istream is(&buf);
+
+ char c;
+ is >> c >> std::ws;
+ VERIFY( is.rdstate() == std::ios_base::badbit );
+
+ is.clear();
+ is.exceptions(std::ios_base::badbit);
+
+ try
+ {
+ is >> std::ws;
+ VERIFY( false );
+ }
+ catch (const __gnu_test::underflow_error&)
+ {
+ VERIFY( is.rdstate() == std::ios_base::badbit );
+ }
+ catch (...)
+ {
+ VERIFY( false );
+ }
+}
+
+int main()
+{
+ test01();
+ test02();
+ test03();
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/ws/wchar_t/lwg415.cc b/libstdc++-v3/testsuite/27_io/basic_istream/ws/wchar_t/lwg415.cc
new file mode 100644
index 00000000000..fd040098b40
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_istream/ws/wchar_t/lwg415.cc
@@ -0,0 +1,77 @@
+#include
+
+// C++11 27.7.2.4 Standard basic_istream manipulators [istream.manip]
+//
+// LWG 415. behavior of std::ws
+// std::ws is an unformatted input function.
+
+#include
+#include
+#include
+
+void
+test01()
+{
+ std::wistream is(0);
+ VERIFY( is.rdstate() == std::ios_base::badbit );
+
+ is >> std::ws; // sentry should set failbit
+ VERIFY( is.rdstate() & std::ios_base::failbit );
+}
+
+void
+test02()
+{
+ __gnu_test::sync_wstreambuf buf;
+ std::wistream is(&buf);
+
+ __gnu_test::sync_wstreambuf buf_tie;
+ std::wostream os_tie(&buf_tie);
+
+ // A sentry should be constructed so is.tie()->flush() should be called.
+ // The standard allows the flush to be deferred because the put area of
+ // is_tie is empty, but libstdc++ doesn't defer it.
+ is.tie(&os_tie);
+
+ is >> std::ws;
+
+ VERIFY( is.eof() );
+ VERIFY( !is.fail() );
+ VERIFY( ! buf.sync_called() );
+ VERIFY( buf_tie.sync_called() );
+}
+
+void
+test03()
+{
+ __gnu_test::fail_wstreambuf buf;
+ std::wistream is(&buf);
+
+ wchar_t c;
+ is >> c >> std::ws;
+ VERIFY( is.rdstate() == std::ios_base::badbit );
+
+ is.clear();
+ is.exceptions(std::ios_base::badbit);
+
+ try
+ {
+ is >> std::ws;
+ VERIFY( false );
+ }
+ catch (const __gnu_test::underflow_error&)
+ {
+ VERIFY( is.rdstate() == std::ios_base::badbit );
+ }
+ catch (...)
+ {
+ VERIFY( false );
+ }
+}
+
+int main()
+{
+ test01();
+ test02();
+ test03();
+}