diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index b4f402d096e9..b2e5216c8ab6 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,4 +1,14 @@ -2002-02-26 Loren Rittle +2002-02-26 Benjamin Kosnik + + * include/bits/basic_ios.tcc (basic_ios::init): Set _M_fill to zero. + Adjust comment. + * include/bits/basic_ios.h (basic_ios::_M_fill): Make mutable. + (basic_ios::_M_fill_init): New. + (basic_ios::fill()): Deal with _M_fill lazily. + Adjust comment. + * testsuite/27_io/ios_init.cc (test02): Adjust testcase. + +2002-02-26 Loren Rittle * include/Makefile.am (thread_target_headers): Unconditionally stage and install gthr-posix.h. diff --git a/libstdc++-v3/include/bits/basic_ios.h b/libstdc++-v3/include/bits/basic_ios.h index f91719582f1d..dea2fdb38575 100644 --- a/libstdc++-v3/include/bits/basic_ios.h +++ b/libstdc++-v3/include/bits/basic_ios.h @@ -64,7 +64,8 @@ namespace std // Data members: protected: basic_ostream<_CharT, _Traits>* _M_tie; - char_type _M_fill; + mutable char_type _M_fill; + mutable bool _M_fill_init; iostate _M_exception; basic_streambuf<_CharT, _Traits>* _M_streambuf; @@ -160,7 +161,14 @@ namespace std char_type fill() const - { return _M_fill; } + { + if (!_M_fill_init) + { + _M_fill = this->widen(' '); + _M_fill_init = true; + } + return _M_fill; + } char_type fill(char_type __ch) diff --git a/libstdc++-v3/include/bits/basic_ios.tcc b/libstdc++-v3/include/bits/basic_ios.tcc index b4f523f54835..63a439747b7b 100644 --- a/libstdc++-v3/include/bits/basic_ios.tcc +++ b/libstdc++-v3/include/bits/basic_ios.tcc @@ -144,17 +144,20 @@ namespace std _M_cache_facets(_M_ios_locale); _M_tie = 0; - // NB: The 27.4.4.1 Postconditions Table only specifies - // requirements after basic_ios::init() has been called. As part - // of this, fill() must return widen(' '), which needs an imbued - // ctype facet of char_type to return without throwing an - // exception. Unfortunately, ctype is not necessarily a - // required facet, so streams with char_type != [char, wchar_t] - // will not have it by default. However, because fill()'s - // signature is const, this data member cannot be lazily - // initialized. Thus, thoughts of using a non-const helper - // function in ostream inserters is really besides the point. - _M_fill = this->widen(' '); + // NB: The 27.4.4.1 Postconditions Table specifies requirements + // after basic_ios::init() has been called. As part of this, + // fill() must return widen(' ') any time after init() has been + // called, which needs an imbued ctype facet of char_type to + // return without throwing an exception. Unfortunately, + // ctype is not necessarily a required facet, so + // streams with char_type != [char, wchar_t] will not have it by + // default. Because of this, the correct value for _M_fill is + // constructed on the first call of fill(). That way, + // unformatted input and output with non-required basic_ios + // instantiations is possible even without imbuing the expected + // ctype facet. + _M_fill = 0; + _M_fill_init = false; _M_exception = goodbit; _M_streambuf = __sb; diff --git a/libstdc++-v3/testsuite/27_io/ios_init.cc b/libstdc++-v3/testsuite/27_io/ios_init.cc index 9f87ee0d32e5..7cef9cce6834 100644 --- a/libstdc++-v3/testsuite/27_io/ios_init.cc +++ b/libstdc++-v3/testsuite/27_io/ios_init.cc @@ -83,10 +83,8 @@ void test01() } // Non-required instantiations don't have the required facets inbued, -// by default, into the locale object. As such, basic_ios::init is -// required to return a bad_cast for the first use of fill() call. +// by default, into the locale object. // See 27.4.4.1 - class gnu_ios: public std::basic_ios { }; void test02() @@ -94,6 +92,7 @@ void test02() bool test = true; // 01: Doesn't call basic_ios::init, which uses ctype.. + // This should be unambiguously correct. try { gnu_ios gios; @@ -103,15 +102,12 @@ void test02() test = false; } - // 02: Calls basic_ios::init, which uses ctype.. + // 02: Calls basic_ios::init, which may call ctype... try { std::basic_string str; std::basic_ostringstream oss(str); - // Shouldn't get this far. - test = false; - // Try each member functions for unformatted io. // put oss.put(324); @@ -125,7 +121,9 @@ void test02() } catch(const std::bad_cast& obj) { - // This is correct. + // Should be able to do the above without calling fill() and + // forcing a call to widen... + test = false; } catch(...) {