aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetur Runolfsson <peturr02@ru.is>2003-11-04 05:27:41 +0000
committerBenjamin Kosnik <bkoz@gcc.gnu.org>2003-11-04 05:27:41 +0000
commit5e93f39f64234c07447aca0d466c8ae989306669 (patch)
treedbeb51f2111e74f88fe23facb07d9567776a19a5
parent99f8b2501d1ba3247656c37cd820222c366d6a31 (diff)
downloadgcc-5e93f39f64234c07447aca0d466c8ae989306669.zip
gcc-5e93f39f64234c07447aca0d466c8ae989306669.tar.gz
gcc-5e93f39f64234c07447aca0d466c8ae989306669.tar.bz2
re PR libstdc++/12790 (basic_filebuf doesn't handle stateful encodings)
2003-11-03 Petur Runolfsson <peturr02@ru.is> PR libstdc++/12790 * include/bits/fstream.tcc: Delete _M_last_overflowed. (basic_filebuf::basic_filebuf): Initialize _M_state_last. (basic_filebuf::open, basic_filebuf::close): Assign _M_state_beg to _M_state_cur and _M_state_last. (basic_filebuf::close): Call _M_terminate_output to handle unshift and flushing. (basic_filebuf::underflow): Assign _M_state_last, throw exception instead of calling abort when codecvt::max_length() is bad. (basic_filebuf::seekoff): Use _M_state_last when calling codecvt::length(), pass correct state to _M_seek. (basic_filebuf::seekpos): Pass __pos.state() to _M_seek. (basic_filebuf::_M_seek): Add __state_type parameter, set _M_state_cur correctly, store the resulting state in the return value and use _M_terminate_output to handle flushing and unshift. (basic_filebuf::_M_terminate_output): Flush contents of output buffer, if any, then call codecvt::unshift as needed and output the result. (basic_filebuf::sync): Move here, don't modify _M_writing or _M_reading. * include/std/std_fstream.h (basic_filebuf::_M_state_last): Declare it. (basic_filebuf::_M_last_overflowed): Delete. (basic_filebuf::_M_seek): Add __state_type parameter. (basic_filebuf::sync): Declare only. (basic_filebuf::_M_output_unshift): Delete. (basic_filebuf::_M_terminate_output): Declare it. * testsuite/testsuite_character.h: Define character class and state class plus char_traits and codecvt specializations for same for testing support for stateful encodings. * testsuite/27_io/basic_filebuf/close/12790-1.cc, * testsuite/27_io/basic_filebuf/close/char/12790-1.cc, * testsuite/27_io/basic_filebuf/close/char/12790-2.cc, * testsuite/27_io/basic_filebuf/close/char/12790-3.cc, * testsuite/27_io/basic_filebuf/close/char/12790-4.cc, * testsuite/27_io/basic_filebuf/close/wchar_t/12790-1.cc, * testsuite/27_io/basic_filebuf/close/wchar_t/12790-2.cc, * testsuite/27_io/basic_filebuf/close/wchar_t/12790-3.cc, * testsuite/27_io/basic_filebuf/close/wchar_t/12790-4.cc, * testsuite/27_io/basic_filebuf/open/12790-1.cc, * testsuite/27_io/basic_filebuf/seekoff/12790-1.cc, * testsuite/27_io/basic_filebuf/seekoff/12790-2.cc, * testsuite/27_io/basic_filebuf/seekoff/12790-3.cc, * testsuite/27_io/basic_filebuf/seekoff/12790-4.cc, * testsuite/27_io/basic_filebuf/seekoff/char/12790-1.cc, * testsuite/27_io/basic_filebuf/seekoff/char/12790-2.cc, * testsuite/27_io/basic_filebuf/seekoff/char/12790-3.cc, * testsuite/27_io/basic_filebuf/seekoff/char/12790-4.cc, * testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-1.cc, * testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-2.cc, * testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-3.cc, * testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-4.cc, * testsuite/27_io/basic_filebuf/seekoff/wchar_t/3.cc, * testsuite/27_io/basic_filebuf/seekpos/12790-1.cc, * testsuite/27_io/basic_filebuf/seekpos/12790-2.cc, * testsuite/27_io/basic_filebuf/seekpos/12790-3.cc, * testsuite/27_io/basic_filebuf/seekpos/char/12790-1.cc, * testsuite/27_io/basic_filebuf/seekpos/char/12790-2.cc, * testsuite/27_io/basic_filebuf/seekpos/char/12790-3.cc, * testsuite/27_io/basic_filebuf/seekpos/char/12790-4.cc, * testsuite/27_io/basic_filebuf/seekpos/wchar_t/1.cc, * testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-1.cc, * testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-2.cc, * testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-3.cc, * testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-4.cc, * testsuite/27_io/basic_filebuf/sync/char/1.cc, * testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc: New tests. * testsuite/27_io/basic_filebuf/3.cc, * testsuite/27_io/basic_filebuf/seekoff/10132-2.cc, * testsuite/27_io/basic_filebuf/seekpos/10132-3.cc, * testsuite/27_io/basic_fstream/3.cc, * testsuite/27_io/basic_ifstream/3.cc, * testsuite/27_io/basic_ofstream/3.cc: Use streamoff as off_type and fpos<state_type> as pos_type. * testsuite/27_io/basic_filebuf/seekpos/char/1-io.cc, * testsuite/27_io/basic_filebuf/seekpos/char/1-out.cc: Check that sync does *not* set _M_writing to false. From-SVN: r73245
-rw-r--r--libstdc++-v3/ChangeLog89
-rw-r--r--libstdc++-v3/include/bits/fstream.tcc179
-rw-r--r--libstdc++-v3/include/std/std_fstream.h61
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/3.cc4
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/close/12790-1.cc78
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-1.cc79
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-2.cc81
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-3.cc80
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-4.cc80
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-1.cc79
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-2.cc81
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-3.cc80
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-4.cc80
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/open/12790-1.cc60
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/10132-2.cc4
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-1.cc82
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-2.cc85
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-3.cc80
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-4.cc71
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-1.cc79
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-2.cc80
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-3.cc79
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-4.cc80
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-1.cc79
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-2.cc80
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-3.cc79
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-4.cc80
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/3.cc46
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/10132-3.cc4
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-1.cc66
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-2.cc81
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-3.cc79
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/1-io.cc2
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/1-out.cc2
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-1.cc80
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-2.cc81
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-3.cc80
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-4.cc81
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/1.cc46
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-1.cc80
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-2.cc81
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-3.cc80
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-4.cc81
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/sync/char/1.cc52
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc52
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_fstream/3.cc4
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_ifstream/3.cc4
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_ofstream/3.cc4
-rw-r--r--libstdc++-v3/testsuite/testsuite_character.h415
49 files changed, 3473 insertions, 97 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index d8242e9..9124c8d 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,92 @@
+2003-11-03 Petur Runolfsson <peturr02@ru.is>
+
+ PR libstdc++/12790
+ * include/bits/fstream.tcc: Delete _M_last_overflowed.
+ (basic_filebuf::basic_filebuf): Initialize _M_state_last.
+ (basic_filebuf::open, basic_filebuf::close): Assign
+ _M_state_beg to _M_state_cur and _M_state_last.
+ (basic_filebuf::close): Call _M_terminate_output to handle
+ unshift and flushing.
+ (basic_filebuf::underflow): Assign _M_state_last, throw
+ exception instead of calling abort when codecvt::max_length()
+ is bad.
+ (basic_filebuf::seekoff): Use _M_state_last when calling
+ codecvt::length(), pass correct state to _M_seek.
+ (basic_filebuf::seekpos): Pass __pos.state() to _M_seek.
+ (basic_filebuf::_M_seek): Add __state_type parameter,
+ set _M_state_cur correctly, store the resulting state in
+ the return value and use _M_terminate_output to handle
+ flushing and unshift.
+ (basic_filebuf::_M_terminate_output): Flush contents of
+ output buffer, if any, then call codecvt::unshift as
+ needed and output the result.
+ (basic_filebuf::sync): Move here, don't modify _M_writing
+ or _M_reading.
+
+ * include/std/std_fstream.h
+ (basic_filebuf::_M_state_last): Declare it.
+ (basic_filebuf::_M_last_overflowed): Delete.
+ (basic_filebuf::_M_seek): Add __state_type parameter.
+ (basic_filebuf::sync): Declare only.
+ (basic_filebuf::_M_output_unshift): Delete.
+ (basic_filebuf::_M_terminate_output): Declare it.
+
+ * testsuite/testsuite_character.h:
+ Define character class and state class plus char_traits and
+ codecvt specializations for same for testing support for
+ stateful encodings.
+
+ * testsuite/27_io/basic_filebuf/close/12790-1.cc,
+ * testsuite/27_io/basic_filebuf/close/char/12790-1.cc,
+ * testsuite/27_io/basic_filebuf/close/char/12790-2.cc,
+ * testsuite/27_io/basic_filebuf/close/char/12790-3.cc,
+ * testsuite/27_io/basic_filebuf/close/char/12790-4.cc,
+ * testsuite/27_io/basic_filebuf/close/wchar_t/12790-1.cc,
+ * testsuite/27_io/basic_filebuf/close/wchar_t/12790-2.cc,
+ * testsuite/27_io/basic_filebuf/close/wchar_t/12790-3.cc,
+ * testsuite/27_io/basic_filebuf/close/wchar_t/12790-4.cc,
+ * testsuite/27_io/basic_filebuf/open/12790-1.cc,
+ * testsuite/27_io/basic_filebuf/seekoff/12790-1.cc,
+ * testsuite/27_io/basic_filebuf/seekoff/12790-2.cc,
+ * testsuite/27_io/basic_filebuf/seekoff/12790-3.cc,
+ * testsuite/27_io/basic_filebuf/seekoff/12790-4.cc,
+ * testsuite/27_io/basic_filebuf/seekoff/char/12790-1.cc,
+ * testsuite/27_io/basic_filebuf/seekoff/char/12790-2.cc,
+ * testsuite/27_io/basic_filebuf/seekoff/char/12790-3.cc,
+ * testsuite/27_io/basic_filebuf/seekoff/char/12790-4.cc,
+ * testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-1.cc,
+ * testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-2.cc,
+ * testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-3.cc,
+ * testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-4.cc,
+ * testsuite/27_io/basic_filebuf/seekoff/wchar_t/3.cc,
+ * testsuite/27_io/basic_filebuf/seekpos/12790-1.cc,
+ * testsuite/27_io/basic_filebuf/seekpos/12790-2.cc,
+ * testsuite/27_io/basic_filebuf/seekpos/12790-3.cc,
+ * testsuite/27_io/basic_filebuf/seekpos/char/12790-1.cc,
+ * testsuite/27_io/basic_filebuf/seekpos/char/12790-2.cc,
+ * testsuite/27_io/basic_filebuf/seekpos/char/12790-3.cc,
+ * testsuite/27_io/basic_filebuf/seekpos/char/12790-4.cc,
+ * testsuite/27_io/basic_filebuf/seekpos/wchar_t/1.cc,
+ * testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-1.cc,
+ * testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-2.cc,
+ * testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-3.cc,
+ * testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-4.cc,
+ * testsuite/27_io/basic_filebuf/sync/char/1.cc,
+ * testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc:
+ New tests.
+
+ * testsuite/27_io/basic_filebuf/3.cc,
+ * testsuite/27_io/basic_filebuf/seekoff/10132-2.cc,
+ * testsuite/27_io/basic_filebuf/seekpos/10132-3.cc,
+ * testsuite/27_io/basic_fstream/3.cc,
+ * testsuite/27_io/basic_ifstream/3.cc,
+ * testsuite/27_io/basic_ofstream/3.cc:
+ Use streamoff as off_type and fpos<state_type> as pos_type.
+
+ * testsuite/27_io/basic_filebuf/seekpos/char/1-io.cc,
+ * testsuite/27_io/basic_filebuf/seekpos/char/1-out.cc:
+ Check that sync does *not* set _M_writing to false.
+
2003-11-03 Anthony Green <green@redhat.com>
* libmath/stubs.c (sqrtf, sqrtl): Reorder so they appear before
diff --git a/libstdc++-v3/include/bits/fstream.tcc b/libstdc++-v3/include/bits/fstream.tcc
index 29fe0e8..5649741 100644
--- a/libstdc++-v3/include/bits/fstream.tcc
+++ b/libstdc++-v3/include/bits/fstream.tcc
@@ -74,12 +74,12 @@ namespace std
template<typename _CharT, typename _Traits>
basic_filebuf<_CharT, _Traits>::
basic_filebuf() : __streambuf_type(), _M_file(&_M_lock),
- _M_mode(ios_base::openmode(0)), _M_state_cur(__state_type()),
- _M_state_beg(__state_type()), _M_buf(NULL), _M_buf_size(BUFSIZ),
+ _M_mode(ios_base::openmode(0)), _M_state_beg(), _M_state_cur(),
+ _M_state_last(), _M_buf(NULL), _M_buf_size(BUFSIZ),
_M_buf_allocated(false), _M_reading(false), _M_writing(false),
- _M_last_overflowed(false), _M_pback_cur_save(0), _M_pback_end_save(0),
- _M_pback_init(false), _M_codecvt(0), _M_ext_buf(0), _M_ext_buf_size(0),
- _M_ext_next(0), _M_ext_end(0)
+ _M_pback_cur_save(0), _M_pback_end_save(0), _M_pback_init(false),
+ _M_codecvt(0), _M_ext_buf(0), _M_ext_buf_size(0), _M_ext_next(0),
+ _M_ext_end(0)
{
if (has_facet<__codecvt_type>(this->_M_buf_locale))
_M_codecvt = &use_facet<__codecvt_type>(this->_M_buf_locale);
@@ -104,9 +104,12 @@ namespace std
_M_writing = false;
_M_set_buffer(-1);
+ // Reset to initial state.
+ _M_state_last = _M_state_cur = _M_state_beg;
+
// 27.8.1.3,4
if ((__mode & ios_base::ate)
- && this->seekoff(0, ios_base::end, __mode)
+ && this->seekoff(0, ios_base::end, __mode)
== pos_type(off_type(-1)))
this->close();
else
@@ -127,18 +130,8 @@ namespace std
bool __testfail = false;
try
{
- if (this->pbase() < this->pptr()
- && traits_type::eq_int_type(this->overflow(),
- traits_type::eof()))
+ if (!_M_terminate_output())
__testfail = true;
-#if 0
- // XXX not done
- if (_M_last_overflowed)
- {
- _M_output_unshift();
- this->overflow();
- }
-#endif
}
catch(...)
{
@@ -152,6 +145,7 @@ namespace std
_M_reading = false;
_M_writing = false;
_M_set_buffer(-1);
+ _M_state_last = _M_state_cur = _M_state_beg;
if (!_M_file.close())
__testfail = true;
@@ -159,7 +153,6 @@ namespace std
if (!__testfail)
__ret = this;
}
- _M_last_overflowed = false;
return __ret;
}
@@ -180,7 +173,6 @@ namespace std
__ret += _M_file.showmanyc() / _M_codecvt->max_length();
}
- _M_last_overflowed = false;
return __ret;
}
@@ -252,6 +244,7 @@ namespace std
_M_ext_next = _M_ext_buf;
_M_ext_end = _M_ext_buf + __remainder;
+ _M_state_last = _M_state_cur;
do
{
@@ -261,7 +254,10 @@ namespace std
// This may fail if the return value of
// codecvt::max_length() is bogus.
if (_M_ext_end - _M_ext_buf + __rlen > _M_ext_buf_size)
- std::abort();
+ {
+ __throw_ios_failure("codecvt::max_length() "
+ "is not valid");
+ }
streamsize __elen = _M_file.xsgetn(_M_ext_end, __rlen);
if (__elen == 0)
__got_eof = true;
@@ -280,8 +276,7 @@ namespace std
size_t __avail = _M_ext_end - _M_ext_buf;
__ilen = std::min(__avail, __buflen);
traits_type::copy(this->eback(),
- reinterpret_cast<char_type*>(_M_ext_buf),
- __ilen);
+ reinterpret_cast<char_type*>(_M_ext_buf), __ilen);
_M_ext_next = _M_ext_buf + __ilen;
}
else
@@ -309,7 +304,6 @@ namespace std
_M_reading = false;
}
}
- _M_last_overflowed = false;
return __ret;
}
@@ -364,7 +358,6 @@ namespace std
__ret = __i;
}
}
- _M_last_overflowed = false;
return __ret;
}
@@ -423,7 +416,6 @@ namespace std
}
}
}
- _M_last_overflowed = true;
return __ret;
}
@@ -521,7 +513,8 @@ namespace std
const streamsize __buffill = this->pptr() - this->pbase();
const char* __buf = reinterpret_cast<const char*>(this->pbase());
__ret = _M_file.xsputn_2(__buf, __buffill,
- reinterpret_cast<const char*>(__s), __n);
+ reinterpret_cast<const char*>(__s),
+ __n);
if (__ret == __buffill + __n)
{
_M_set_buffer(0);
@@ -569,7 +562,6 @@ namespace std
_M_writing = false;
_M_set_buffer(-1);
}
- _M_last_overflowed = false;
return this;
}
@@ -589,12 +581,18 @@ namespace std
if (__width < 0)
__width = 0;
- const bool __testfail = __off != 0 && __width <= 0;
+ const bool __testfail = __off != 0 && __width <= 0;
if (this->is_open() && !__testfail)
{
// Ditch any pback buffers to avoid confusion.
_M_destroy_pback();
+ // Correct state at destination. Note that this is the correct
+ // state for the current position during output, because
+ // codecvt::unshift() returns the state to the initial state.
+ // This is also the correct state at the end of the file because
+ // an unshift sequence should have been written at the end.
+ __state_type __state = _M_state_beg;
off_type __computed_off = __off * __width;
if (_M_reading && __way == ios_base::cur)
{
@@ -603,16 +601,20 @@ namespace std
else
{
// Calculate offset from _M_ext_buf that corresponds
- // to gptr().
+ // to gptr(). Note: uses _M_state_last, which
+ // corresponds to eback().
const int __gptr_off =
- _M_codecvt->length(_M_state_cur, _M_ext_buf, _M_ext_next,
+ _M_codecvt->length(_M_state_last, _M_ext_buf, _M_ext_next,
this->gptr() - this->eback());
__computed_off += _M_ext_buf + __gptr_off - _M_ext_end;
+
+ // _M_state_last is modified by codecvt::length() so
+ // it now corresponds to gptr().
+ __state = _M_state_last;
}
}
- __ret = _M_seek(__computed_off, __way);
+ __ret = _M_seek(__computed_off, __way, __state);
}
- _M_last_overflowed = false;
return __ret;
}
@@ -632,41 +634,115 @@ namespace std
// Ditch any pback buffers to avoid confusion.
_M_destroy_pback();
- __ret = _M_seek(off_type(__pos), ios_base::beg);
+ __ret = _M_seek(off_type(__pos), ios_base::beg, __pos.state());
}
- _M_last_overflowed = false;
return __ret;
}
template<typename _CharT, typename _Traits>
typename basic_filebuf<_CharT, _Traits>::pos_type
basic_filebuf<_CharT, _Traits>::
- _M_seek(off_type __off, ios_base::seekdir __way)
+ _M_seek(off_type __off, ios_base::seekdir __way, __state_type __state)
+ {
+ pos_type __ret = pos_type(off_type(-1));
+ if (_M_terminate_output())
+ {
+ // Returns pos_type(off_type(-1)) in case of failure.
+ __ret = pos_type(_M_file.seekoff(__off, __way));
+
+ _M_reading = false;
+ _M_writing = false;
+ _M_ext_next = _M_ext_end = _M_ext_buf;
+ _M_set_buffer(-1);
+ _M_state_cur = __state;
+ __ret.state(_M_state_cur);
+ }
+ return __ret;
+ }
+
+ template<typename _CharT, typename _Traits>
+ bool
+ basic_filebuf<_CharT, _Traits>::
+ _M_terminate_output()
{
+ bool __testvalid = true;
+
+ // Part one: update the output sequence.
if (this->pbase() < this->pptr())
{
- // Part one: update the output sequence.
- this->sync();
+ const int_type __tmp = this->overflow();
+ if (traits_type::eq_int_type(__tmp, traits_type::eof()))
+ __testvalid = false;
+ }
- // Part two: output unshift sequence.
- _M_output_unshift();
+ // Part two: output unshift sequence.
+ if (_M_writing && !__check_facet(_M_codecvt).always_noconv()
+ && __testvalid)
+ {
+ // Note: this value is arbitrary, since there is no way to
+ // get the length of the unshift sequence from codecvt,
+ // without calling unshift.
+ const size_t __blen = 128;
+
+ char __buf[__blen];
+ codecvt_base::result __r;
+ streamsize __ilen = 0;
+
+ do
+ {
+ char* __next;
+ __r = _M_codecvt->unshift(_M_state_cur, __buf,
+ __buf + __blen, __next);
+ if (__r == codecvt_base::error)
+ __testvalid = false;
+ else if (__r == codecvt_base::ok ||
+ __r == codecvt_base::partial)
+ {
+ __ilen = __next - __buf;
+
+ if (__ilen > 0)
+ {
+ const streamsize __elen = _M_file.xsputn(__buf, __ilen);
+ if (__elen != __ilen)
+ __testvalid = false;
+ }
+ }
+ }
+ while (__r == codecvt_base::partial && __ilen > 0 && __testvalid);
+
+ if (__testvalid)
+ {
+ // This second call to overflow() is required by the standard,
+ // but it's not clear why it's needed, since the output buffer
+ // should be empty by this point (it should have been emptied
+ // in the first call to overflow()).
+ const int_type __tmp = this->overflow();
+ if (traits_type::eq_int_type(__tmp, traits_type::eof()))
+ __testvalid = false;
+ }
}
-
- // Returns pos_type(off_type(-1)) in case of failure.
- pos_type __ret (_M_file.seekoff(__off, __way));
-
- _M_reading = false;
- _M_writing = false;
- _M_ext_next = _M_ext_end = _M_ext_buf;
- _M_set_buffer(-1);
- return __ret;
+ return __testvalid;
}
template<typename _CharT, typename _Traits>
- void
+ int
basic_filebuf<_CharT, _Traits>::
- _M_output_unshift()
- { }
+ sync()
+ {
+ int __ret = 0;
+
+ // Make sure that the internal buffer resyncs its idea of
+ // the file position with the external file.
+ // NB: _M_file.sync() will be called within.
+ if (this->pbase() < this->pptr())
+ {
+ const int_type __tmp = this->overflow();
+ if (traits_type::eq_int_type(__tmp, traits_type::eof()))
+ __ret = -1;
+ }
+
+ return __ret;
+ }
template<typename _CharT, typename _Traits>
void
@@ -703,7 +779,6 @@ namespace std
// encoding, or that the filebuf be closed. Opinions may differ.
}
}
- _M_last_overflowed = false;
}
// Inhibit implicit instantiations for required instantiations,
diff --git a/libstdc++-v3/include/std/std_fstream.h b/libstdc++-v3/include/std/std_fstream.h
index dd19ccc..9bfa677 100644
--- a/libstdc++-v3/include/std/std_fstream.h
+++ b/libstdc++-v3/include/std/std_fstream.h
@@ -60,6 +60,11 @@ namespace std
* sequences. Many of its sematics are described in terms of similar
* behavior in the Standard C Library's @c FILE streams.
*/
+ // Requirements on traits_type, specific to this class:
+ // traits_type::pos_type must be fpos<traits_type::state_type>
+ // traits_type::off_type must be streamoff
+ // traits_type::state_type must be Assignable and DefaultConstructable,
+ // and traits_type::state_type() must be the initial state for codecvt.
template<typename _CharT, typename _Traits>
class basic_filebuf : public basic_streambuf<_CharT, _Traits>
{
@@ -111,15 +116,33 @@ namespace std
*/
ios_base::openmode _M_mode;
- // Current and beginning state type for codecvt.
+ // Beginning state type for codecvt.
/**
* @if maint
* @doctodo
* @endif
*/
- __state_type _M_state_cur;
__state_type _M_state_beg;
+ // During output, the state that corresponds to pptr(),
+ // during input, the state that corresponds to egptr() and
+ // _M_ext_next.
+ /**
+ * @if maint
+ * @doctodo
+ * @endif
+ */
+ __state_type _M_state_cur;
+
+ // Not used for output. During input, the state that corresponds
+ // to eback() and _M_ext_buf.
+ /**
+ * @if maint
+ * @doctodo
+ * @endif
+ */
+ __state_type _M_state_last;
+
/**
* @if maint
* Pointer to the beginning of internally-allocated space.
@@ -156,9 +179,6 @@ namespace std
bool _M_reading;
bool _M_writing;
- // XXX Needed?
- bool _M_last_overflowed;
-
//@{
/**
* @if maint
@@ -386,33 +406,11 @@ namespace std
* @endif
*/
pos_type
- _M_seek(off_type __off, ios_base::seekdir __way);
+ _M_seek(off_type __off, ios_base::seekdir __way, __state_type __state);
// [documentation is inherited]
virtual int
- sync()
- {
- int __ret = 0;
-
- // Make sure that the internal buffer resyncs its idea of
- // the file position with the external file.
- // NB: _M_file.sync() will be called within.
- if (this->pbase() < this->pptr())
- {
- const int_type __tmp = this->overflow();
- if (traits_type::eq_int_type(__tmp, traits_type::eof()))
- __ret = -1;
- else
- {
- _M_set_buffer(-1);
- _M_reading = false;
- _M_writing = false;
- }
- }
-
- _M_last_overflowed = false;
- return __ret;
- }
+ sync();
// [documentation is inherited]
virtual void
@@ -443,13 +441,14 @@ namespace std
virtual streamsize
xsputn(const char_type* __s, streamsize __n);
+ // Flushes output buffer, then writes unshift sequence.
/**
* @if maint
* @doctodo
* @endif
*/
- void
- _M_output_unshift();
+ bool
+ _M_terminate_output();
/**
* @if maint
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/3.cc
index 6cb9e6e..6523af7 100644
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/3.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/3.cc
@@ -56,9 +56,9 @@ struct gnu_char_traits
{
typedef gnu_char_type char_type;
typedef long int_type;
- typedef long pos_type;
- typedef unsigned long off_type;
+ typedef std::streamoff off_type;
typedef long state_type;
+ typedef std::fpos<state_type> pos_type;
static void
assign(char_type& __c1, const char_type& __c2) { }
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/12790-1.cc
new file mode 100644
index 0000000..a6c2700
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/12790-1.cc
@@ -0,0 +1,78 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+#include <testsuite_character.h>
+
+// libstdc++/12790
+void test01()
+{
+ using namespace std;
+ using __gnu_test::character;
+ typedef basic_filebuf<character>::traits_type traits_type;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_close_12790";
+
+ locale loc(locale::classic(),
+ new codecvt<traits_type::char_type, char,
+ traits_type::state_type>);
+
+ basic_filebuf<character> fb;
+ fb.pubsetbuf(0, 0);
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out | ios_base::trunc);
+ fb.sputc(character::from_char('b'));
+ fb.sputc(character::from_char(0xff));
+ fb.sputc(character::from_char(0));
+
+ // Check that close() writes unshift sequence
+ fb.close();
+
+ fb.open(name, ios_base::in | ios_base::out | ios_base::ate);
+
+ fb.sputc(character::from_char('a'));
+ fb.sputc(character::from_char(0xff));
+ fb.sputc(character::from_char(0));
+
+ fb.close();
+
+ fb.open(name, ios_base::in);
+
+ fb.sbumpc();
+ fb.sbumpc();
+ fb.sbumpc();
+
+ traits_type::int_type c = fb.sbumpc();
+ VERIFY( c != traits_type::eof() );
+ VERIFY( traits_type::eq(traits_type::to_char_type(c),
+ character::from_char('a')) );
+
+ fb.close();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-1.cc
new file mode 100644
index 0000000..cc68efb
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-1.cc
@@ -0,0 +1,79 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::close() should call codecvt::unshift()
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_close_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ filebuf fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ fb.sputc('a');
+
+ VERIFY( !cvt->unshift_called );
+ fb.close();
+ VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-2.cc
new file mode 100644
index 0000000..2e16682
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-2.cc
@@ -0,0 +1,81 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::close() should call codecvt::unshift()
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_close_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ filebuf fb;
+ fb.pubsetbuf(0, 0);
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ fb.sputc('a');
+ fb.in_avail(); // showmanyc() should have no effect on close().
+
+ VERIFY( !cvt->unshift_called );
+ fb.close();
+ VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-3.cc
new file mode 100644
index 0000000..0e3629a
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-3.cc
@@ -0,0 +1,80 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return codecvt_base::error;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::close() should fail if codecvt::unshift() fails
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_close_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ filebuf fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ fb.sputc('a');
+
+ VERIFY( !cvt->unshift_called );
+ filebuf* ret = fb.close();
+ VERIFY( cvt->unshift_called );
+ VERIFY( ret == NULL );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-4.cc
new file mode 100644
index 0000000..c0efd7f
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-4.cc
@@ -0,0 +1,80 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::close() should call codecvt::unshift()
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_close_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ filebuf fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ fb.sputc('a');
+ fb.pubsync(); // Does not call unshift()
+
+ VERIFY( !cvt->unshift_called );
+ fb.close();
+ VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-1.cc
new file mode 100644
index 0000000..c0588a3
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-1.cc
@@ -0,0 +1,79 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::close() should call codecvt::unshift()
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_close_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ wfilebuf fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ fb.sputc(L'a');
+
+ VERIFY( !cvt->unshift_called );
+ fb.close();
+ VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-2.cc
new file mode 100644
index 0000000..edabea9
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-2.cc
@@ -0,0 +1,81 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::close() should call codecvt::unshift()
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_close_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ wfilebuf fb;
+ fb.pubsetbuf(0, 0);
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ fb.sputc(L'a');
+ fb.in_avail(); // showmanyc() should have no effect on close().
+
+ VERIFY( !cvt->unshift_called );
+ fb.close();
+ VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-3.cc
new file mode 100644
index 0000000..8c7e2c2
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-3.cc
@@ -0,0 +1,80 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return codecvt_base::error;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::close() should fail if codecvt::unshift() fails
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_close_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ wfilebuf fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ fb.sputc('a');
+
+ VERIFY( !cvt->unshift_called );
+ wfilebuf* ret = fb.close();
+ VERIFY( cvt->unshift_called );
+ VERIFY( ret == NULL );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-4.cc
new file mode 100644
index 0000000..f6acb49
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-4.cc
@@ -0,0 +1,80 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::close() should call codecvt::unshift()
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_close_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ wfilebuf fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ fb.sputc(L'a');
+ fb.pubsync(); // Does not call unshift()
+
+ VERIFY( !cvt->unshift_called );
+ fb.close();
+ VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/open/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/open/12790-1.cc
new file mode 100644
index 0000000..d37972b
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/open/12790-1.cc
@@ -0,0 +1,60 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+#include <testsuite_character.h>
+
+// libstdc++/12790
+void test01()
+{
+ using namespace std;
+ using __gnu_test::character;
+ typedef basic_filebuf<character>::traits_type traits_type;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_open_12790";
+
+ locale loc(locale::classic(),
+ new codecvt<traits_type::char_type, char,
+ traits_type::state_type>);
+
+ basic_filebuf<character> fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ fb.sputc(character::from_char('b'));
+ fb.close();
+
+ // Check that reopened basic_filebuf begins in the initial state.
+ fb.open(name, ios_base::in);
+ traits_type::int_type c = fb.sbumpc();
+ VERIFY( c != traits_type::eof() );
+ VERIFY( traits_type::eq(traits_type::to_char_type(c),
+ character::from_char('b')) );
+ fb.close();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/10132-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/10132-2.cc
index 0d218a6..14f0870 100644
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/10132-2.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/10132-2.cc
@@ -54,9 +54,9 @@ struct gnu_char_traits
{
typedef gnu_char_type char_type;
typedef long int_type;
- typedef long pos_type;
- typedef unsigned long off_type;
+ typedef std::streamoff off_type;
typedef long state_type;
+ typedef std::fpos<state_type> pos_type;
static void
assign(char_type& __c1, const char_type& __c2) { }
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-1.cc
new file mode 100644
index 0000000..79a6251
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-1.cc
@@ -0,0 +1,82 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+#include <testsuite_character.h>
+
+// libstdc++/12790
+void test01()
+{
+ using namespace std;
+ using __gnu_test::character;
+ typedef basic_filebuf<character>::traits_type traits_type;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekoff_12790";
+
+ locale loc(locale::classic(),
+ new codecvt<traits_type::char_type, char,
+ traits_type::state_type>);
+
+ basic_filebuf<character> fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ fb.sputc(character::from_char(0xff));
+ fb.sputc(character::from_char(0));
+ fb.sputc(character::from_char(0));
+ fb.sputc(character::from_char('a'));
+ fb.sputc(character::from_char('a'));
+ fb.sputc(character::from_char('a'));
+ fb.sputc(character::from_char('a'));
+ fb.close();
+
+ fb.open(name, ios_base::in);
+ fb.sbumpc();
+ fb.sbumpc();
+ fb.sbumpc();
+
+ // Check that seekoff calls codecvt::length with the correct state.
+ traits_type::pos_type pos = fb.pubseekoff(0, ios_base::cur);
+ VERIFY( pos != traits_type::pos_type(traits_type::off_type(-1)) );
+
+ traits_type::int_type c = fb.sbumpc();
+ VERIFY( c != traits_type::eof() );
+ VERIFY( traits_type::eq(traits_type::to_char_type(c),
+ character::from_char('a')) );
+ fb.sbumpc();
+ fb.sbumpc();
+ c = fb.sbumpc();
+ VERIFY( c != traits_type::eof() );
+ VERIFY( traits_type::eq(traits_type::to_char_type(c),
+ character::from_char('a')) );
+ c = fb.sbumpc();
+ VERIFY( c == traits_type::eof() );
+
+ fb.close();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-2.cc
new file mode 100644
index 0000000..5966e17
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-2.cc
@@ -0,0 +1,85 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+#include <testsuite_character.h>
+
+// libstdc++/12790
+void test01()
+{
+ using namespace std;
+ using __gnu_test::character;
+ typedef basic_filebuf<character>::traits_type traits_type;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekoff_12790";
+
+ locale loc(locale::classic(),
+ new codecvt<traits_type::char_type, char,
+ traits_type::state_type>);
+
+ basic_filebuf<character> fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ fb.sputc(character::from_char(0xff));
+ fb.sputc(character::from_char(0));
+ fb.sputc(character::from_char(0));
+ fb.sputc(character::from_char('a'));
+ fb.sputc(character::from_char('a'));
+ fb.sputc(character::from_char('a'));
+ fb.sputc(character::from_char('a'));
+ fb.close();
+
+ fb.open(name, ios_base::in);
+ fb.sbumpc();
+ fb.sbumpc();
+ fb.sbumpc();
+
+ // Check that seekoff resets the state when seeking to beginning.
+ traits_type::pos_type pos = fb.pubseekoff(0, ios_base::beg);
+ VERIFY( pos != traits_type::pos_type(traits_type::off_type(-1)) );
+
+ traits_type::int_type c = fb.sbumpc();
+ VERIFY( c != traits_type::eof() );
+ VERIFY( traits_type::eq(traits_type::to_char_type(c),
+ character::from_char(0xff)) );
+ fb.sbumpc();
+ fb.sbumpc();
+ fb.sbumpc();
+ fb.sbumpc();
+ fb.sbumpc();
+ c = fb.sbumpc();
+ VERIFY( c != traits_type::eof() );
+ VERIFY( traits_type::eq(traits_type::to_char_type(c),
+ character::from_char('a')) );
+ c = fb.sbumpc();
+ VERIFY( c == traits_type::eof() );
+
+ fb.close();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-3.cc
new file mode 100644
index 0000000..42a1795
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-3.cc
@@ -0,0 +1,80 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+#include <testsuite_character.h>
+
+// libstdc++/12790
+void test01()
+{
+ using namespace std;
+ using __gnu_test::character;
+ typedef basic_filebuf<character>::traits_type traits_type;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekoff_12790";
+
+ locale loc(locale::classic(),
+ new codecvt<traits_type::char_type, char,
+ traits_type::state_type>);
+
+ basic_filebuf<character> fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out | ios_base::trunc);
+ fb.sputc(character::from_char('b'));
+ fb.sputc(character::from_char(0xff));
+ fb.sputc(character::from_char('a'));
+ fb.sputc(character::from_char(0xfc));
+ fb.sputc(character::from_char(0));
+ fb.sputc(character::from_char(0));
+
+ fb.close();
+ fb.open(name, ios_base::in);
+
+ fb.sbumpc();
+ fb.sbumpc();
+
+ // Check that seekoff returns the correct state
+ traits_type::pos_type pos = fb.pubseekoff(0, ios_base::cur);
+
+ traits_type::int_type c = fb.sbumpc();
+ VERIFY( c != traits_type::eof() );
+ VERIFY( traits_type::eq(traits_type::to_char_type(c),
+ character::from_char('a')) );
+ fb.sbumpc();
+
+ fb.pubseekpos(pos);
+
+ c = fb.sbumpc();
+ VERIFY( c != traits_type::eof() );
+ VERIFY( traits_type::eq(traits_type::to_char_type(c),
+ character::from_char('a')) );
+
+ fb.close();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-4.cc
new file mode 100644
index 0000000..d246657
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-4.cc
@@ -0,0 +1,71 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+#include <testsuite_character.h>
+
+// libstdc++/12790
+void test01()
+{
+ using namespace std;
+ using __gnu_test::character;
+ typedef basic_filebuf<character>::traits_type traits_type;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekoff_12790";
+
+ locale loc(locale::classic(),
+ new codecvt<traits_type::char_type, char,
+ traits_type::state_type>);
+
+ basic_filebuf<character> fb;
+ fb.pubsetbuf(0, 0);
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::in | ios_base::out | ios_base::trunc);
+ fb.sputc(character::from_char('b'));
+ fb.sputc(character::from_char(0xff));
+
+ // Check that seekoff sets the current state during output
+ traits_type::pos_type pos = fb.pubseekoff(0, ios_base::cur);
+ fb.sputc(character::from_char('a'));
+ fb.sputc(character::from_char(0xff));
+ fb.sputc(character::from_char(0));
+ fb.sputc(character::from_char(0));
+
+ fb.pubseekoff(0, ios_base::beg);
+ fb.sbumpc();
+ fb.sbumpc();
+
+ traits_type::int_type c = fb.sbumpc();
+ VERIFY( c != traits_type::eof() );
+ VERIFY( traits_type::eq(traits_type::to_char_type(c),
+ character::from_char('a')) );
+
+ fb.close();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-1.cc
new file mode 100644
index 0000000..a634023
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-1.cc
@@ -0,0 +1,79 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekoff() should call codecvt::unshift()
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekoff_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ filebuf fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ fb.sputc('a');
+
+ VERIFY( !cvt->unshift_called );
+ fb.pubseekoff(0, ios_base::cur);
+ VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-2.cc
new file mode 100644
index 0000000..006078a
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-2.cc
@@ -0,0 +1,80 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekoff() should call codecvt::unshift()
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekoff_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ filebuf fb;
+ fb.pubsetbuf(0, 0);
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ fb.sputc('a');
+
+ VERIFY( !cvt->unshift_called );
+ fb.pubseekoff(0, ios_base::cur);
+ VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-3.cc
new file mode 100644
index 0000000..b56a5e9
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-3.cc
@@ -0,0 +1,79 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekoff() should call codecvt::unshift(),
+// but only if writing
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekoff_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ filebuf fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+
+ VERIFY( !cvt->unshift_called );
+ fb.pubseekoff(0, ios_base::cur);
+ VERIFY( !cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-4.cc
new file mode 100644
index 0000000..69752b2
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-4.cc
@@ -0,0 +1,80 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekoff() should call codecvt::unshift()
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekoff_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ filebuf fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ fb.sputc('a');
+ fb.pubsync(); // Does not call unshift()
+
+ VERIFY( !cvt->unshift_called );
+ fb.pubseekoff(0, ios_base::cur);
+ VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-1.cc
new file mode 100644
index 0000000..bf70ecd
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-1.cc
@@ -0,0 +1,79 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekoff() should call codecvt::unshift()
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekoff_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ wfilebuf fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ fb.sputc(L'a');
+
+ VERIFY( !cvt->unshift_called );
+ fb.pubseekoff(0, ios_base::cur);
+ VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-2.cc
new file mode 100644
index 0000000..748ae3a
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-2.cc
@@ -0,0 +1,80 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekoff() should call codecvt::unshift()
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekoff_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ wfilebuf fb;
+ fb.pubsetbuf(0, 0);
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ fb.sputc(L'a');
+
+ VERIFY( !cvt->unshift_called );
+ fb.pubseekoff(0, ios_base::cur);
+ VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-3.cc
new file mode 100644
index 0000000..6db1648
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-3.cc
@@ -0,0 +1,79 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekoff() should call codecvt::unshift(),
+// but only if writing
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekoff_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ wfilebuf fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+
+ VERIFY( !cvt->unshift_called );
+ fb.pubseekoff(0, ios_base::cur);
+ VERIFY( !cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-4.cc
new file mode 100644
index 0000000..b6af7fb
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-4.cc
@@ -0,0 +1,80 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekoff() should call codecvt::unshift()
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekoff_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ wfilebuf fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ fb.sputc(L'a');
+ fb.pubsync(); // Does not call unshift()
+
+ VERIFY( !cvt->unshift_called );
+ fb.pubseekoff(0, ios_base::cur);
+ VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/3.cc
new file mode 100644
index 0000000..3088e5f
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/3.cc
@@ -0,0 +1,46 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <fstream>
+#include <testsuite_hooks.h>
+
+void test03()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekoff_3";
+
+ wfilebuf fb;
+
+ fb.open(name, ios_base::out);
+ fb.sputc(0xf001);
+
+ // seekoff should flush the output sequence, which will fail
+ // if the output buffer contains illegal characters.
+ streampos ret = fb.pubseekoff(0, ios_base::cur);
+ VERIFY( ret == streampos(streamoff(-1)) );
+}
+
+int main()
+{
+ test03();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/10132-3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/10132-3.cc
index fdb817d..85b80a1 100644
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/10132-3.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/10132-3.cc
@@ -54,9 +54,9 @@ struct gnu_char_traits
{
typedef gnu_char_type char_type;
typedef long int_type;
- typedef long pos_type;
- typedef unsigned long off_type;
+ typedef std::streamoff off_type;
typedef long state_type;
+ typedef std::fpos<state_type> pos_type;
static void
assign(char_type& __c1, const char_type& __c2) { }
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-1.cc
new file mode 100644
index 0000000..3201da8
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-1.cc
@@ -0,0 +1,66 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+#include <testsuite_character.h>
+
+// libstdc++/12790
+void test01()
+{
+ using namespace std;
+ using __gnu_test::character;
+ typedef basic_filebuf<character>::traits_type traits_type;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekpos_12790";
+
+ locale loc(locale::classic(),
+ new codecvt<traits_type::char_type, char,
+ traits_type::state_type>);
+
+ basic_filebuf<character> fb;
+ fb.pubsetbuf(0, 0);
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::in | ios_base::out | ios_base::trunc);
+ traits_type::pos_type pos = fb.pubseekoff(0, ios_base::cur);
+ fb.sputc(character::from_char('a'));
+ fb.sputc(character::from_char(0xff));
+ fb.sputc(character::from_char(0));
+ fb.sputc(character::from_char(0));
+
+ // Check that seekpos restores the state correctly
+ fb.pubseekpos(pos);
+
+ traits_type::int_type c = fb.sbumpc();
+ VERIFY( c != traits_type::eof() );
+ VERIFY( traits_type::eq(traits_type::to_char_type(c),
+ character::from_char('a')) );
+
+ fb.close();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-2.cc
new file mode 100644
index 0000000..b5198e5
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-2.cc
@@ -0,0 +1,81 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+#include <testsuite_character.h>
+
+// libstdc++/12790
+void test01()
+{
+ using namespace std;
+ using __gnu_test::character;
+ typedef basic_filebuf<character>::traits_type traits_type;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekpos_12790";
+
+ locale loc(locale::classic(),
+ new codecvt<traits_type::char_type, char,
+ traits_type::state_type>);
+
+ basic_filebuf<character> fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out | ios_base::trunc);
+ fb.sputc(character::from_char('b'));
+ fb.sputc(character::from_char(0xff));
+ fb.sputc(character::from_char('a'));
+ fb.sputc(character::from_char(0xfc));
+ fb.sputc(character::from_char(0));
+ fb.sputc(character::from_char(0));
+
+ fb.close();
+ fb.open(name, ios_base::in);
+
+ fb.sbumpc();
+ fb.sbumpc();
+ traits_type::pos_type pos1 = fb.pubseekoff(0, ios_base::cur);
+ fb.sbumpc();
+ fb.sbumpc();
+
+ // Check that seekpos returns the correct state
+ traits_type::pos_type pos2 = fb.pubseekpos(pos1);
+ traits_type::int_type c = fb.sbumpc();
+ VERIFY( c != traits_type::eof() );
+ VERIFY( traits_type::eq(traits_type::to_char_type(c),
+ character::from_char('a')) );
+ fb.sbumpc();
+
+ fb.pubseekpos(pos2);
+ c = fb.sbumpc();
+ VERIFY( c != traits_type::eof() );
+ VERIFY( traits_type::eq(traits_type::to_char_type(c),
+ character::from_char('a')) );
+
+ fb.close();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-3.cc
new file mode 100644
index 0000000..1d0535c
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-3.cc
@@ -0,0 +1,79 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+#include <testsuite_character.h>
+
+// libstdc++/12790
+void test01()
+{
+ using namespace std;
+ using __gnu_test::character;
+ typedef basic_filebuf<character>::traits_type traits_type;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekpos_12790";
+
+ locale loc(locale::classic(),
+ new codecvt<traits_type::char_type, char,
+ traits_type::state_type>);
+
+ basic_filebuf<character> fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::in | ios_base::out | ios_base::trunc);
+ fb.sputc(character::from_char('b'));
+ fb.sputc(character::from_char(0xff));
+ fb.sputc(character::from_char('c'));
+ fb.sputc(character::from_char(0xff));
+
+ fb.pubseekoff(0, ios_base::beg);
+ fb.sbumpc();
+ fb.sbumpc();
+ traits_type::pos_type pos = fb.pubseekoff(0, ios_base::cur);
+ fb.sbumpc();
+ fb.sbumpc();
+
+ // Check that seekoff sets the current state for output
+ fb.pubseekpos(pos);
+
+ fb.sputc(character::from_char('a'));
+ fb.sputc(character::from_char(0));
+ fb.sputc(character::from_char(0));
+ fb.sputc(character::from_char(0));
+ fb.sputc(character::from_char(0));
+
+ fb.pubseekpos(pos);
+
+ traits_type::int_type c = fb.sbumpc();
+ VERIFY( c != traits_type::eof() );
+ VERIFY( traits_type::eq(traits_type::to_char_type(c),
+ character::from_char('a')) );
+
+ fb.close();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/1-io.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/1-io.cc
index eea3be8..588a1b2 100644
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/1-io.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/1-io.cc
@@ -88,7 +88,7 @@ void test05()
VERIFY( off_1 > off_2 );
fb.sputn("\nof the wonderful things he does!!\nok", 37);
fb.pubsync();
- VERIFY( !fb.write_position() );
+ VERIFY( fb.write_position() );
VERIFY( !fb.read_position() );
fb.close();
VERIFY( !fb.is_open() );
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/1-out.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/1-out.cc
index cc29a27..c684786 100644
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/1-out.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/1-out.cc
@@ -90,7 +90,7 @@ void test05()
VERIFY( off_1 > off_2 );
fb.sputn("\nof the wonderful things he does!!\nok", 37);
fb.pubsync();
- VERIFY( !fb.write_position() );
+ VERIFY( fb.write_position() );
VERIFY( !fb.read_position() );
fb.close();
VERIFY( !fb.is_open() );
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-1.cc
new file mode 100644
index 0000000..2c31c8a
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-1.cc
@@ -0,0 +1,80 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekpos() should call codecvt::unshift()
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekpos_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ filebuf fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ streampos pos = fb.pubseekoff(0, ios_base::beg);
+ fb.sputc('a');
+
+ VERIFY( !cvt->unshift_called );
+ fb.pubseekpos(pos);
+ VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-2.cc
new file mode 100644
index 0000000..42b1023
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-2.cc
@@ -0,0 +1,81 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekpos() should call codecvt::unshift()
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekpos_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ filebuf fb;
+ fb.pubsetbuf(0, 0);
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ streampos pos = fb.pubseekoff(0, ios_base::beg);
+ fb.sputc('a');
+
+ VERIFY( !cvt->unshift_called );
+ fb.pubseekpos(pos);
+ VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-3.cc
new file mode 100644
index 0000000..e168c94
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-3.cc
@@ -0,0 +1,80 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekpos() should call codecvt::unshift(),
+// but only if writing
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekpos_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ filebuf fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ streampos pos = fb.pubseekoff(0, ios_base::beg);
+
+ VERIFY( !cvt->unshift_called );
+ fb.pubseekpos(pos);
+ VERIFY( !cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-4.cc
new file mode 100644
index 0000000..0bf84cb
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-4.cc
@@ -0,0 +1,81 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekpos() should call codecvt::unshift()
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekpos_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ filebuf fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ streampos pos = fb.pubseekoff(0, ios_base::beg);
+ fb.sputc('a');
+ fb.pubsync(); // Does not call unshift()
+
+ VERIFY( !cvt->unshift_called );
+ fb.pubseekpos(pos);
+ VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/1.cc
new file mode 100644
index 0000000..c543212
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/1.cc
@@ -0,0 +1,46 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekpos_1";
+
+ wfilebuf fb;
+
+ fb.open(name, ios_base::out);
+ streampos pos = fb.pubseekoff(0, ios_base::beg);
+ fb.sputc(0xf001);
+
+ streampos ret = fb.pubseekpos(pos);
+ VERIFY( ret == streampos(streamoff(-1)) );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-1.cc
new file mode 100644
index 0000000..718589e
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-1.cc
@@ -0,0 +1,80 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekpos() should call codecvt::unshift()
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekpos_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ wfilebuf fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ streampos pos = fb.pubseekoff(0, ios_base::beg);
+ fb.sputc(L'a');
+
+ VERIFY( !cvt->unshift_called );
+ fb.pubseekpos(pos);
+ VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-2.cc
new file mode 100644
index 0000000..220a48c
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-2.cc
@@ -0,0 +1,81 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekpos() should call codecvt::unshift()
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekpos_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ wfilebuf fb;
+ fb.pubsetbuf(0, 0);
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ streampos pos = fb.pubseekoff(0, ios_base::beg);
+ fb.sputc(L'a');
+
+ VERIFY( !cvt->unshift_called );
+ fb.pubseekpos(pos);
+ VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-3.cc
new file mode 100644
index 0000000..eaa3cb6
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-3.cc
@@ -0,0 +1,80 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekpos() should call codecvt::unshift(),
+// but only if writing
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekpos_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ wfilebuf fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ streampos pos = fb.pubseekoff(0, ios_base::beg);
+
+ VERIFY( !cvt->unshift_called );
+ fb.pubseekpos(pos);
+ VERIFY( !cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-4.cc
new file mode 100644
index 0000000..70d36c8
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-4.cc
@@ -0,0 +1,81 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+ mutable bool unshift_called;
+
+ Cvt()
+ : unshift_called(false)
+ { }
+
+protected:
+ bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ int
+ do_encoding() const throw()
+ { return -1; }
+
+ std::codecvt_base::result
+ do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+ {
+ unshift_called = true;
+ to_next = to;
+ return std::codecvt_base::ok;
+ }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekpos() should call codecvt::unshift()
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_seekpos_12790";
+
+ Cvt* cvt = new Cvt;
+ locale loc(locale::classic(), cvt);
+
+ wfilebuf fb;
+ fb.pubimbue(loc);
+
+ fb.open(name, ios_base::out);
+ streampos pos = fb.pubseekoff(0, ios_base::beg);
+ fb.sputc(L'a');
+ fb.pubsync(); // Does not call unshift()
+
+ VERIFY( !cvt->unshift_called );
+ fb.pubseekpos(pos);
+ VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/char/1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/char/1.cc
new file mode 100644
index 0000000..202cc38
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/char/1.cc
@@ -0,0 +1,52 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <fstream>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_sync_1";
+
+ filebuf fb;
+
+ fb.open(name, ios_base::in | ios_base::out | ios_base::trunc);
+ fb.sputn("abc", 3);
+
+ fb.pubseekoff(0, ios_base::beg);
+ fb.sputc('1');
+
+ // Sync can't be used to switch from write mode to read mode.
+ fb.pubsync();
+
+ filebuf::int_type c = fb.sbumpc();
+ VERIFY( c == filebuf::traits_type::eof() );
+
+ fb.close();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc
new file mode 100644
index 0000000..8ff00ce
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc
@@ -0,0 +1,52 @@
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <fstream>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ using namespace std;
+
+ bool test __attribute__((unused)) = true;
+ const char* name = "tmp_sync_1";
+
+ wfilebuf fb;
+
+ fb.open(name, ios_base::in | ios_base::out | ios_base::trunc);
+ fb.sputn(L"abc", 3);
+
+ fb.pubseekoff(0, ios_base::beg);
+ fb.sputc(L'1');
+
+ // Sync can't be used to switch from write mode to read mode.
+ fb.pubsync();
+
+ wfilebuf::int_type c = fb.sbumpc();
+ VERIFY( c == wfilebuf::traits_type::eof() );
+
+ fb.close();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_fstream/3.cc b/libstdc++-v3/testsuite/27_io/basic_fstream/3.cc
index c71e0e8..484c611 100644
--- a/libstdc++-v3/testsuite/27_io/basic_fstream/3.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_fstream/3.cc
@@ -58,9 +58,9 @@ struct gnu_char_traits
{
typedef gnu_char_type char_type;
typedef long int_type;
- typedef long pos_type;
- typedef unsigned long off_type;
+ typedef std::streamoff off_type;
typedef long state_type;
+ typedef std::fpos<state_type> pos_type;
static void
assign(char_type& __c1, const char_type& __c2) { }
diff --git a/libstdc++-v3/testsuite/27_io/basic_ifstream/3.cc b/libstdc++-v3/testsuite/27_io/basic_ifstream/3.cc
index 7ffd7b3..6649be3 100644
--- a/libstdc++-v3/testsuite/27_io/basic_ifstream/3.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_ifstream/3.cc
@@ -58,9 +58,9 @@ struct gnu_char_traits
{
typedef gnu_char_type char_type;
typedef long int_type;
- typedef long pos_type;
- typedef unsigned long off_type;
+ typedef std::streamoff off_type;
typedef long state_type;
+ typedef std::fpos<state_type> pos_type;
static void
assign(char_type& __c1, const char_type& __c2) { }
diff --git a/libstdc++-v3/testsuite/27_io/basic_ofstream/3.cc b/libstdc++-v3/testsuite/27_io/basic_ofstream/3.cc
index 3cba219..8f264d4 100644
--- a/libstdc++-v3/testsuite/27_io/basic_ofstream/3.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_ofstream/3.cc
@@ -58,9 +58,9 @@ struct gnu_char_traits
{
typedef gnu_char_type char_type;
typedef long int_type;
- typedef long pos_type;
- typedef unsigned long off_type;
+ typedef std::streamoff off_type;
typedef long state_type;
+ typedef std::fpos<state_type> pos_type;
static void
assign(char_type& __c1, const char_type& __c2) { }
diff --git a/libstdc++-v3/testsuite/testsuite_character.h b/libstdc++-v3/testsuite/testsuite_character.h
new file mode 100644
index 0000000..67c35c2
--- /dev/null
+++ b/libstdc++-v3/testsuite/testsuite_character.h
@@ -0,0 +1,415 @@
+// -*- C++ -*-
+// Testing character type and state type with char_traits and codecvt
+// specializations for the C++ library testsuite.
+//
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+//
+// As a special exception, you may use this file as part of a free software
+// library without restriction. Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License. This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+#ifndef _GLIBCXX_TESTSUITE_CHARACTER_H
+#define _GLIBCXX_TESTSUITE_CHARACTER_H
+
+#include <string> // for char_traits
+#include <locale> // for codecvt
+#include <climits>
+
+namespace __gnu_test
+{
+ // Character type
+ struct character
+ {
+ unsigned char val;
+
+ static character from_char(char c)
+ {
+ character ret;
+ ret.val = c;
+ return ret;
+ }
+ };
+
+ // State type.
+ struct conversion_state
+ {
+ unsigned int state;
+ };
+}; // namespace __gnu_test
+
+namespace std
+{
+ // char_traits specialization. Meets the additional requirements for
+ // basic_filebuf.
+ template<>
+ struct char_traits<__gnu_test::character>
+ {
+ typedef __gnu_test::character char_type;
+ typedef unsigned int int_type;
+ typedef __gnu_test::conversion_state state_type;
+ typedef streamoff off_type;
+ typedef fpos<state_type> pos_type;
+
+ static void
+ assign(char_type& c1, const char_type& c2)
+ { c1 = c2; }
+
+ static bool
+ eq(const char_type& c1, const char_type& c2)
+ { return c1.val == c2.val; }
+
+ static bool
+ lt(const char_type& c1, const char_type& c2)
+ { return c1.val < c2.val; }
+
+ static int
+ compare(const char_type* s1, const char_type* s2, size_t n)
+ {
+ for (size_t i = 0; i < n; ++i)
+ {
+ if (lt(s1[i], s2[i]))
+ return -1;
+ else if (lt(s2[i], s1[i]))
+ return 1;
+ }
+ return 0;
+ }
+
+ static size_t
+ length(const char_type* s)
+ {
+ size_t n = 0;
+ while (!eq(s[n], char_type()))
+ ++n;
+ return n;
+ }
+
+ static const char_type*
+ find(const char_type* s, size_t n, const char_type& a)
+ {
+ for (size_t i = 0; i < n; ++i)
+ {
+ if (eq(s[i], a))
+ return s + i;
+ }
+ return NULL;
+ }
+
+ static char_type*
+ move(char_type* s1, const char_type* s2, size_t n)
+ {
+ if (s1 > s2)
+ {
+ for (size_t i = 0; i < n; ++i)
+ assign(s1[n - i - 1], s2[n - i - 1]);
+ }
+ else
+ {
+ for (size_t i = 0; i < n; ++i)
+ assign(s1[i], s2[i]);
+ }
+ return s1;
+ }
+
+ static char_type*
+ copy(char_type* s1, const char_type* s2, size_t n)
+ {
+ for (size_t i = 0; i < n; ++i)
+ assign(s1[i], s2[i]);
+ return s1;
+ }
+
+ static char_type*
+ assign(char_type* s, size_t n, char_type a)
+ {
+ for (size_t i = 0; i < n; ++i)
+ assign(s[i], a);
+ return s;
+ }
+
+ static int_type
+ not_eof(const int_type& c)
+ {
+ if (eq_int_type(c, eof()))
+ return 0;
+ return c;
+ }
+
+ // Note non-trivial conversion to maximize chance of catching bugs
+ static char_type
+ to_char_type(const int_type& c)
+ {
+ char_type ret;
+ ret.val = (c >> 5);
+ return ret;
+ }
+
+ static int_type
+ to_int_type(const char_type& c)
+ {
+ return c.val << 5;
+ }
+
+ static bool
+ eq_int_type(const int_type& c1, const int_type& c2)
+ { return c1 == c2; }
+
+ static int_type eof()
+ { return 0xf; }
+ };
+
+ // codecvt specialization
+ //
+ // The conversion performed by the specialization is not supposed to
+ // be useful, rather it has been designed to demonstrate the
+ // essential features of stateful conversions:
+ // * Number and value of bytes for each internal character depends on the
+ // state in addition to the character itself.
+ // * Unshift produces an unshift sequence and resets the state. On input
+ // the unshift sequence causes the state to be reset.
+ //
+ // The conversion for output is as follows:
+ // 1. Calculate the value tmp by xor-ing the state and the internal
+ // character
+ // 2. Split tmp into either two or three bytes depending on the value of
+ // state. Output those bytes.
+ // 3. tmp becomes the new value of state.
+ template<>
+ class codecvt<__gnu_test::character, char, __gnu_test::conversion_state>
+ : public locale::facet, public codecvt_base
+ {
+ public:
+ typedef __gnu_test::character intern_type;
+ typedef char extern_type;
+ typedef __gnu_test::conversion_state state_type;
+
+ explicit codecvt(size_t refs = 0)
+ : locale::facet(refs)
+ { }
+
+ result
+ out(state_type& state, const intern_type* from,
+ const intern_type* from_end, const intern_type*& from_next,
+ extern_type* to, extern_type* to_limit, extern_type*& to_next) const
+ {
+ return do_out(state, from, from_end, from_next,
+ to, to_limit, to_next);
+ }
+
+ result
+ unshift(state_type& state, extern_type* to, extern_type* to_limit,
+ extern_type*& to_next) const
+ { return do_unshift(state, to, to_limit, to_next); }
+
+ result
+ in(state_type& state, const extern_type* from,
+ const extern_type* from_end, const extern_type*& from_next,
+ intern_type* to, intern_type* to_limit, intern_type*& to_next) const
+ {
+ return do_in(state, from, from_end, from_next,
+ to, to_limit, to_next);
+ }
+
+ int
+ encoding() const throw()
+ { return do_encoding(); }
+
+ bool
+ always_noconv() const throw()
+ { return do_always_noconv(); }
+
+ int
+ length(state_type& state, const extern_type* from,
+ const extern_type* end, size_t max) const
+ { return do_length(state, from, end, max); }
+
+ int
+ max_length() const throw()
+ { return do_max_length(); }
+
+ static locale::id id;
+
+ protected:
+ ~codecvt()
+ { }
+
+ virtual result
+ do_out(state_type& state, const intern_type* from,
+ const intern_type* from_end, const intern_type*& from_next,
+ extern_type* to, extern_type* to_limit,
+ extern_type*& to_next) const
+ {
+ while (from < from_end && to < to_limit)
+ {
+ unsigned char tmp = (state.state ^ from->val);
+ if (state.state & 0x8)
+ {
+ if (to >= to_limit - 2)
+ break;
+ *to++ = (tmp & 0x7);
+ *to++ = ((tmp >> 3) & 0x7);
+ *to++ = ((tmp >> 6) & 0x3);
+ }
+ else
+ {
+ if (to >= to_limit - 1)
+ break;
+ *to++ = (tmp & 0xf);
+ *to++ = ((tmp >> 4) & 0xf);
+ }
+ state.state = tmp;
+ ++from;
+ }
+
+ from_next = from;
+ to_next = to;
+ return (from < from_end) ? partial : ok;
+ }
+
+ virtual result
+ do_in(state_type& state, const extern_type* from,
+ const extern_type* from_end, const extern_type*& from_next,
+ intern_type* to, intern_type* to_limit,
+ intern_type*& to_next) const
+ {
+ while (from < from_end && to < to_limit)
+ {
+ unsigned char c = *from;
+ if (c & 0xc0)
+ {
+ // Unshift sequence
+ state.state &= c;
+ ++from;
+ continue;
+ }
+
+ unsigned char tmp;
+ if (state.state & 0x8)
+ {
+ if (from >= from_end - 2)
+ break;
+ tmp = (*from++ & 0x7);
+ tmp |= ((*from++ << 3) & 0x38);
+ tmp |= ((*from++ << 6) & 0xc0);
+ }
+ else
+ {
+ if (from >= from_end - 1)
+ break;
+ tmp = (*from++ & 0xf);
+ tmp |= ((*from++ << 4) & 0xf0);
+ }
+ to->val = (tmp ^ state.state);
+ state.state = tmp;
+ ++to;
+ }
+
+ from_next = from;
+ to_next = to;
+ return (from < from_end) ? partial : ok;
+ }
+
+ virtual result
+ do_unshift(state_type& state, extern_type* to, extern_type* to_limit,
+ extern_type*& to_next) const
+ {
+ for (unsigned int i = 0; i < CHAR_BIT; ++i)
+ {
+ unsigned int mask = (1 << i);
+ if (state.state & mask)
+ {
+ if (to == to_limit)
+ {
+ to_next = to;
+ return partial;
+ }
+
+ state.state &= ~mask;
+ *to++ = static_cast<unsigned char>(~mask);
+ }
+ }
+
+ to_next = to;
+ return state.state == 0 ? ok : error;
+ }
+
+ virtual int
+ do_encoding() const throw()
+ { return -1; }
+
+ virtual bool
+ do_always_noconv() const throw()
+ { return false; }
+
+ virtual int
+ do_length(state_type& state, const extern_type* from,
+ const extern_type* end, size_t max) const
+ {
+ const extern_type* beg = from;
+ while (from < end && max)
+ {
+ unsigned char c = *from;
+ if (c & 0xc0)
+ {
+ // Unshift sequence
+ state.state &= c;
+ ++from;
+ continue;
+ }
+
+ unsigned char tmp;
+ if (state.state & 0x8)
+ {
+ if (from >= end - 2)
+ break;
+ tmp = (*from++ & 0x7);
+ tmp |= ((*from++ << 3) & 0x38);
+ tmp |= ((*from++ << 6) & 0xc0);
+ }
+ else
+ {
+ if (from >= end - 1)
+ break;
+ tmp = (*from++ & 0xf);
+ tmp |= ((*from++ << 4) & 0xf0);
+ }
+ state.state = tmp;
+ --max;
+ }
+ return from - beg;
+ }
+
+ // Maximum 8 bytes unshift sequence followed by max 3 bytes for
+ // one character.
+ virtual int
+ do_max_length() const throw()
+ { return 11; }
+ };
+
+ locale::id
+ codecvt<__gnu_test::character, char, __gnu_test::conversion_state>::id;
+} // namespace std
+
+#endif // _GLIBCXX_TESTSUITE_CHARACTER_H
+