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.
This commit is contained in:
parent
b838641bb0
commit
e5c422b7d8
@ -245,6 +245,10 @@
|
||||
</p></dd><dt><a id="manual.bugs.dr409"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#409" target="_top">409</a>:
|
||||
<span class="emphasis"><em>Closing an fstream should clear the error state</em></span>
|
||||
</span></dt><dd><p>Have <code class="code">open</code> clear the error flags.
|
||||
</p></dd><dt><a id="manual.bugs.dr415"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#415" target="_top">415</a>:
|
||||
<span class="emphasis"><em>Behavior of std::ws</em></span>
|
||||
</span></dt><dd><p>Change it to be an unformatted input function
|
||||
(i.e. construct a sentry and catch exceptions).
|
||||
</p></dd><dt><span class="term"><a class="link" href="../ext/lwg-closed.html#431" target="_top">431</a>:
|
||||
<span class="emphasis"><em>Swapping containers with unequal allocators</em></span>
|
||||
</span></dt><dd><p>Implement Option 3, as per N1599.
|
||||
|
@ -634,6 +634,13 @@ requirements of the license of GCC.
|
||||
<listitem><para>Have <code>open</code> clear the error flags.
|
||||
</para></listitem></varlistentry>
|
||||
|
||||
<varlistentry xml:id="manual.bugs.dr415"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#415">415</link>:
|
||||
<emphasis>Behavior of std::ws</emphasis>
|
||||
</term>
|
||||
<listitem><para>Change it to be an unformatted input function
|
||||
(i.e. construct a sentry and catch exceptions).
|
||||
</para></listitem></varlistentry>
|
||||
|
||||
<varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-closed.html#431">431</link>:
|
||||
<emphasis>Swapping containers with unequal allocators</emphasis>
|
||||
</term>
|
||||
|
@ -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();
|
||||
// _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();
|
||||
|
||||
while (!_Traits::eq_int_type(__c, __eof)
|
||||
&& __ct.is(ctype_base::space, _Traits::to_char_type(__c)))
|
||||
__c = __sb->snextc();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
77
libstdc++-v3/testsuite/27_io/basic_istream/ws/char/lwg415.cc
Normal file
77
libstdc++-v3/testsuite/27_io/basic_istream/ws/char/lwg415.cc
Normal file
@ -0,0 +1,77 @@
|
||||
#include <istream>
|
||||
|
||||
// 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 <istream>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <testsuite_io.h>
|
||||
|
||||
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();
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
#include <istream>
|
||||
|
||||
// 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 <istream>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <testsuite_io.h>
|
||||
|
||||
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();
|
||||
}
|
Loading…
Reference in New Issue
Block a user