diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 9e2c2c13761..4572136f010 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,49 @@ +2003-06-26 Benjamin Kosnik + + * include/bits/ios_base.h (ios_base::_M_getloc): Return reference + to the imbued locale. + * include/bits/locale_facets.tcc (num_put::_M_convert_int): Use + _M_getloc. + (num_put::_M_convert_float): Use. + +2003-06-26 Benjamin Kosnik + Jerry Quinn + + * config/linker-map.gnu: Add __numpunct_cache. + * config/locale/gnu/numeric_members.cc + (numpunct::_M_initialize_numpunct): Account for _M_data, fill in + all elements for "C" locale. + (numpunct::~numpunct): Delete _M_data. + * config/locale/generic/numeric_members.cc: Same. + * include/bits/basic_ios.tcc + (basic_ios::init): Remove __locale_cache bits. + (basic_ios::_M_cache_locale): Same. + * include/bits/ios_base.h: Same. Tweaks. + * include/bits/locale_classes.h: Tweaks. Reorder classes. + (__use_cache): Make friends with _Impl, locale. + (_Impl::_M_caches): Add. + (_Impl::_M_install_cache): Add. + * include/bits/locale_facets.h (__numpunct_cache): New. + (numpunct): Encapsulate data members in __numpunct_cache member, + _M_data. Adjust virtuals. + (numpunct::numpunct): New ctor for the same. + (__locale_cache_base): Remove. + (__locale_cache): Remove. + * include/bits/locale_facets.tcc (__use_cache): New function, + specializations. + (num_put::_M_convert_int, _M_convert_float, do_put): Use it. + * src/globals.cc: Add cache_vec, numpunct_cache_c, numpunct_cache_w. + * src/ios.cc (ios_base::ios_base): Remove __locale_cache. + * src/locale-inst.cc: Same. Add __numpunct_cache. + * src/locale.cc: Tweak inlines. + (__use_cache): Define specializations. + * src/localename.cc: Use global bits. + (_Impl::~Impl): Deal with __numpunct_cache destruction. + (_Impl::_Impl): Same. Pre-cache standard numpunct facets. + (_Impl::_M_init_facet): Take into account __numpunct_cache. + * testsuite/27_io/ios_base/cons/assign_neg.cc: Update line numbers. + * testsuite/27_io/ios_base/cons/copy_neg.cc: Same. + 2003-06-26 Nathan C. Myers Paolo Carlini diff --git a/libstdc++-v3/config/linker-map.gnu b/libstdc++-v3/config/linker-map.gnu index 77d69fc72f0..21bdfd322a8 100644 --- a/libstdc++-v3/config/linker-map.gnu +++ b/libstdc++-v3/config/linker-map.gnu @@ -55,7 +55,8 @@ GLIBCPP_3.4 { std::__num_base::_S_format_float*; std::__num_base::_S_format_int*; std::__num_base::_S_atoms_in; - std::__num_base::_S_atoms_out + std::__num_base::_S_atoms_out; + std::__numpunct_cache*; }; # Names not in an 'extern' block are mangled names. diff --git a/libstdc++-v3/config/locale/generic/numeric_members.cc b/libstdc++-v3/config/locale/generic/numeric_members.cc index f942e0415b0..320f0ff4ba1 100644 --- a/libstdc++-v3/config/locale/generic/numeric_members.cc +++ b/libstdc++-v3/config/locale/generic/numeric_members.cc @@ -1,6 +1,6 @@ // std::numpunct implementation details, generic version -*- C++ -*- -// Copyright (C) 2001, 2002 Free Software Foundation, Inc. +// Copyright (C) 2001, 2002, 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 @@ -42,16 +42,30 @@ namespace std numpunct::_M_initialize_numpunct(__c_locale) { // "C" locale - _M_decimal_point = '.'; - _M_thousands_sep = ','; - _M_grouping = ""; - _M_truename = "true"; - _M_falsename = "false"; + if (!_M_data) + _M_data = new __numpunct_cache; + + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + + _M_data->_M_decimal_point = '.'; + _M_data->_M_thousands_sep = ','; + + for (size_t i = 0; i < __num_base::_S_oend; ++i) + _M_data->_M_atoms_out[i] = __num_base::_S_atoms_out[i]; + _M_data->_M_atoms_out[__num_base::_S_oend] = wchar_t(); + + for (size_t i = 0; i < __num_base::_S_iend; ++i) + _M_data->_M_atoms_in[i] = __num_base::_S_atoms_in[i]; + _M_data->_M_atoms_in[__num_base::_S_iend] = wchar_t(); + + _M_data->_M_truename = "true"; + _M_data->_M_falsename = "false"; } template<> numpunct::~numpunct() - { } + { delete _M_data; } #ifdef _GLIBCPP_USE_WCHAR_T template<> @@ -59,15 +73,37 @@ namespace std numpunct::_M_initialize_numpunct(__c_locale) { // "C" locale - _M_decimal_point = L'.'; - _M_thousands_sep = L','; - _M_grouping = ""; - _M_truename = L"true"; - _M_falsename = L"false"; + if (!_M_data) + _M_data = new __numpunct_cache; + + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + + _M_data->_M_decimal_point = L'.'; + _M_data->_M_thousands_sep = L','; + + // Use ctype::widen code without the facet... + unsigned char uc; + for (size_t i = 0; i < __num_base::_S_oend; ++i) + { + uc = static_cast(__num_base::_S_atoms_out[i]); + _M_data->_M_atoms_out[i] = btowc(uc); + } + _M_data->_M_atoms_out[__num_base::_S_oend] = wchar_t(); + + for (size_t i = 0; i < __num_base::_S_iend; ++i) + { + uc = static_cast(__num_base::_S_atoms_in[i]); + _M_data->_M_atoms_in[i] = btowc(uc); + } + _M_data->_M_atoms_in[__num_base::_S_iend] = wchar_t(); + + _M_data->_M_truename = L"true"; + _M_data->_M_falsename = L"false"; } template<> numpunct::~numpunct() - { } + { delete _M_data; } #endif } diff --git a/libstdc++-v3/config/locale/gnu/numeric_members.cc b/libstdc++-v3/config/locale/gnu/numeric_members.cc index 5b666ebe608..dd8c76b38f3 100644 --- a/libstdc++-v3/config/locale/gnu/numeric_members.cc +++ b/libstdc++-v3/config/locale/gnu/numeric_members.cc @@ -1,6 +1,6 @@ // std::numpunct implementation details, GNU version -*- C++ -*- -// Copyright (C) 2001, 2002 Free Software Foundation, Inc. +// Copyright (C) 2001, 2002, 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 @@ -42,70 +42,112 @@ namespace std void numpunct::_M_initialize_numpunct(__c_locale __cloc) { + if (!_M_data) + _M_data = new __numpunct_cache; + if (!__cloc) { // "C" locale - _M_decimal_point = '.'; - _M_thousands_sep = ','; - _M_grouping = ""; + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + + _M_data->_M_decimal_point = '.'; + _M_data->_M_thousands_sep = ','; + + for (size_t i = 0; i < __num_base::_S_oend; ++i) + _M_data->_M_atoms_out[i] = __num_base::_S_atoms_out[i]; + _M_data->_M_atoms_out[__num_base::_S_oend] = wchar_t(); + + for (size_t i = 0; i < __num_base::_S_iend; ++i) + _M_data->_M_atoms_in[i] = __num_base::_S_atoms_in[i]; + _M_data->_M_atoms_in[__num_base::_S_iend] = wchar_t(); } else { // Named locale. - _M_decimal_point = *(__nl_langinfo_l(RADIXCHAR, __cloc)); - _M_thousands_sep = *(__nl_langinfo_l(THOUSEP, __cloc)); - // Check for NUL, which implies no grouping. - if (_M_thousands_sep == '\0') - _M_grouping = ""; + _M_data->_M_decimal_point = *(__nl_langinfo_l(RADIXCHAR, __cloc)); + _M_data->_M_thousands_sep = *(__nl_langinfo_l(THOUSEP, __cloc)); + + // Check for NULL, which implies no grouping. + if (_M_data->_M_thousands_sep == '\0') + _M_data->_M_grouping = ""; else - _M_grouping = __nl_langinfo_l(GROUPING, __cloc); + _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc); } // NB: There is no way to extact this info from posix locales. // _M_truename = __nl_langinfo_l(YESSTR, __cloc); - _M_truename = "true"; + _M_data->_M_truename = "true"; // _M_falsename = __nl_langinfo_l(NOSTR, __cloc); - _M_falsename = "false"; + _M_data->_M_falsename = "false"; } template<> numpunct::~numpunct() - { } + { delete _M_data; } #ifdef _GLIBCPP_USE_WCHAR_T template<> void numpunct::_M_initialize_numpunct(__c_locale __cloc) { + if (!_M_data) + _M_data = new __numpunct_cache; + if (!__cloc) { // "C" locale - _M_decimal_point = L'.'; - _M_thousands_sep = L','; - _M_grouping = ""; + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + + _M_data->_M_decimal_point = L'.'; + _M_data->_M_thousands_sep = L','; + +#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) + __c_locale __old = __uselocale(_S_c_locale); +#endif + // Use ctype::widen code without the facet... + unsigned char uc; + for (size_t i = 0; i < __num_base::_S_oend; ++i) + { + uc = static_cast(__num_base::_S_atoms_out[i]); + _M_data->_M_atoms_out[i] = btowc(uc); + } + _M_data->_M_atoms_out[__num_base::_S_oend] = wchar_t(); + + for (size_t i = 0; i < __num_base::_S_iend; ++i) + { + uc = static_cast(__num_base::_S_atoms_in[i]); + _M_data->_M_atoms_in[i] = btowc(uc); + } + _M_data->_M_atoms_in[__num_base::_S_iend] = wchar_t(); +#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) + __uselocale(__old); +#endif } else { // Named locale. union __s_and_w { const char *__s; unsigned int __w; } __u; __u.__s = __nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc); - _M_decimal_point = static_cast(__u.__w); + _M_data->_M_decimal_point = static_cast(__u.__w); __u.__s = __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc); - _M_thousands_sep = static_cast(__u.__w); - if (_M_thousands_sep == L'\0') - _M_grouping = ""; + _M_data->_M_thousands_sep = static_cast(__u.__w); + + if (_M_data->_M_thousands_sep == L'\0') + _M_data->_M_grouping = ""; else - _M_grouping = __nl_langinfo_l(GROUPING, __cloc); + _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc); } // NB: There is no way to extact this info from posix locales. // _M_truename = __nl_langinfo_l(YESSTR, __cloc); - _M_truename = L"true"; + _M_data->_M_truename = L"true"; // _M_falsename = __nl_langinfo_l(NOSTR, __cloc); - _M_falsename = L"false"; + _M_data->_M_falsename = L"false"; } template<> numpunct::~numpunct() - { } + { delete _M_data; } #endif } diff --git a/libstdc++-v3/include/bits/basic_ios.tcc b/libstdc++-v3/include/bits/basic_ios.tcc index cf2701effb2..54f34b599e5 100644 --- a/libstdc++-v3/include/bits/basic_ios.tcc +++ b/libstdc++-v3/include/bits/basic_ios.tcc @@ -138,12 +138,7 @@ namespace std ios_base::_M_init(); // Cache locale data and specific facets used by iostreams. - if (!_M_locale_cache.get()) - { - typedef __locale_cache<_CharT> __cache_t; - this->_M_locale_cache = auto_ptr<__locale_cache_base>(static_cast<__locale_cache_base*>(new __cache_t)); - _M_cache_locale(_M_ios_locale); - } + _M_cache_locale(_M_ios_locale); // NB: The 27.4.4.1 Postconditions Table specifies requirements // after basic_ios::init() has been called. As part of this, @@ -176,7 +171,6 @@ namespace std _M_num_put = &use_facet<__numput_type>(__loc); if (__builtin_expect(has_facet<__numget_type>(__loc), true)) _M_num_get = &use_facet<__numget_type>(__loc); - static_cast<__locale_cache<_CharT>&>(_M_cache())._M_init(__loc); } // Inhibit implicit instantiations for required instantiations, diff --git a/libstdc++-v3/include/bits/ios_base.h b/libstdc++-v3/include/bits/ios_base.h index 37a02a43ddd..ef2f57ab0f8 100644 --- a/libstdc++-v3/include/bits/ios_base.h +++ b/libstdc++-v3/include/bits/ios_base.h @@ -146,8 +146,6 @@ namespace std enum _Ios_Seekdir { _S_ios_seekdir_end = 1L << 16 }; - class __locale_cache_base; - // 27.4.2 Class ios_base /** * @brief The very top of the I/O class hierarchy. @@ -212,47 +210,65 @@ namespace std * - floatfield */ typedef _Ios_Fmtflags fmtflags; + /// Insert/extract @c bool in alphabetic rather than numeric format. static const fmtflags boolalpha = fmtflags(__ios_flags::_S_boolalpha); + /// Converts integer input or generates integer output in decimal base. static const fmtflags dec = fmtflags(__ios_flags::_S_dec); + /// Generate floating-point output in fixed-point notation. static const fmtflags fixed = fmtflags(__ios_flags::_S_fixed); + /// Converts integer input or generates integer output in hexadecimal base. static const fmtflags hex = fmtflags(__ios_flags::_S_hex); + /// Adds fill characters at a designated internal point in certain /// generated output, or identical to @c right if no such point is /// designated. static const fmtflags internal = fmtflags(__ios_flags::_S_internal); + /// Adds fill characters on the right (final positions) of certain /// generated output. (I.e., the thing you print is flush left.) static const fmtflags left = fmtflags(__ios_flags::_S_left); + /// Converts integer input or generates integer output in octal base. static const fmtflags oct = fmtflags(__ios_flags::_S_oct); + /// Adds fill characters on the left (initial positions) of certain /// generated output. (I.e., the thing you print is flush right.) static const fmtflags right = fmtflags(__ios_flags::_S_right); + /// Generates floating-point output in scientific notation. static const fmtflags scientific = fmtflags(__ios_flags::_S_scientific); + /// Generates a prefix indicating the numeric base of generated integer /// output. static const fmtflags showbase = fmtflags(__ios_flags::_S_showbase); + /// Generates a decimal-point character unconditionally in generated /// floating-point output. static const fmtflags showpoint = fmtflags(__ios_flags::_S_showpoint); + /// Generates a + sign in non-negative generated numeric output. static const fmtflags showpos = fmtflags(__ios_flags::_S_showpos); + /// Skips leading white space before certain input operations. static const fmtflags skipws = fmtflags(__ios_flags::_S_skipws); + /// Flushes output after each output operation. static const fmtflags unitbuf = fmtflags(__ios_flags::_S_unitbuf); + /// Replaces certain lowercase letters with their uppercase equivalents /// in generated output. static const fmtflags uppercase = fmtflags(__ios_flags::_S_uppercase); + /// A mask of left|right|internal. Useful for the 2-arg form of @c setf. static const fmtflags adjustfield = fmtflags(__ios_flags::_S_adjustfield); + /// A mask of dec|oct|hex. Useful for the 2-arg form of @c setf. static const fmtflags basefield = fmtflags(__ios_flags::_S_basefield); + /// A mask of scientific|fixed. Useful for the 2-arg form of @c setf. static const fmtflags floatfield = fmtflags(__ios_flags::_S_floatfield); @@ -269,15 +285,19 @@ namespace std * - goodbit */ typedef _Ios_Iostate iostate; + /// Indicates a loss of integrity in an input or output sequence (such /// as an irrecoverable read error from a file). static const iostate badbit = iostate(__ios_flags::_S_badbit); + /// Indicates that an input operation reached the end of an input sequence. static const iostate eofbit = iostate(__ios_flags::_S_eofbit); + /// Indicates that an input operation failed to read the expected /// characters, or that an output operation failed to generate the /// desired characters. static const iostate failbit = iostate(__ios_flags::_S_failbit); + /// Indicates all is well. static const iostate goodbit = iostate(0); @@ -296,19 +316,25 @@ namespace std * - trunc */ typedef _Ios_Openmode openmode; + /// Seek to end before each write. static const openmode app = openmode(__ios_flags::_S_app); + /// Open and seek to end immediately after opening. static const openmode ate = openmode(__ios_flags::_S_ate); + /// Perform input and output in binary mode (as opposed to text mode). /// This is probably not what you think it is; see /// http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#3 and /// http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#7 for more. static const openmode binary = openmode(__ios_flags::_S_bin); + /// Open for input. Default for @c ifstream and fstream. static const openmode in = openmode(__ios_flags::_S_in); + /// Open for output. Default for @c ofstream and fstream. static const openmode out = openmode(__ios_flags::_S_out); + /// Open for input. Default for @c ofstream. static const openmode trunc = openmode(__ios_flags::_S_trunc); @@ -323,10 +349,13 @@ namespace std * - end, equivalent to @c SEEK_END in the C standard library. */ typedef _Ios_Seekdir seekdir; + /// Request a seek relative to the beginning of the stream. static const seekdir beg = seekdir(0); + /// Request a seek relative to the current position within the sequence. static const seekdir cur = seekdir(SEEK_CUR); + /// Request a seek relative to the current end of the sequence. static const seekdir end = seekdir(SEEK_END); @@ -432,10 +461,6 @@ namespace std // Members for locale and locale caching. locale _M_ios_locale; - // Cache of locale and facet data. - // Cast this to __locale_cache<_CharT>* - auto_ptr<__locale_cache_base> _M_locale_cache; - void _M_init(); @@ -604,7 +629,7 @@ namespace std /** * @brief Locale access - * @return The locale currently in effect. + * @return A copy of the current locale. * * If @c imbue(loc) has previously been called, then this function * returns @c loc. Otherwise, it returns a copy of @c std::locale(), @@ -613,6 +638,16 @@ namespace std inline locale getloc() const { return _M_ios_locale; } + /** + * @brief Locale access + * @return A reference to the current locale. + * + * Like getloc above, but returns a reference instead of + * generating a copy. + */ + inline const locale& + _M_getloc() const { return _M_ios_locale; } + // [27.4.2.5] ios_base storage functions /** * @doctodo @@ -642,11 +677,6 @@ namespace std return __word._M_pword; } - // Access to the cache. Not safe to call until basic_ios::_M_init() has - // happened. - __locale_cache_base& - _M_cache() { return *_M_locale_cache; } - // Destructor /** * Destroys local storage and diff --git a/libstdc++-v3/include/bits/locale_classes.h b/libstdc++-v3/include/bits/locale_classes.h index e7210f821fe..cfc11493216 100644 --- a/libstdc++-v3/include/bits/locale_classes.h +++ b/libstdc++-v3/include/bits/locale_classes.h @@ -71,7 +71,11 @@ namespace std template friend const _Facet& use_facet(const locale&); - + + template + friend const _Cache& + __use_cache(const locale& __loc); + // Category values: // NB: Order must match _S_facet_categories definition in locale.cc static const category none = 0; @@ -141,6 +145,12 @@ namespace std // Current global locale static _Impl* _S_global; + // Names of underlying locale categories. + // NB: locale::global() has to know how to modify all the + // underlying categories, not just the ones required by the C++ + // standard. + static const char** _S_categories; + // Number of standard categories. For C++, these categories are // collate, ctype, monetary, numeric, time, and messages. These // directly correspond to ISO C99 macros LC_COLLATE, LC_CTYPE, @@ -153,12 +163,6 @@ namespace std // and LC_IDENTIFICATION. static const size_t _S_categories_size = 6 + _GLIBCPP_NUM_CATEGORIES; - // Names of underlying locale categories. - // NB: locale::global() has to know how to modify all the - // underlying categories, not just the ones required by the C++ - // standard. - static const char** _S_categories; - explicit locale(_Impl*) throw(); @@ -177,7 +181,107 @@ namespace std }; - // Implementation object for locale + // 22.1.1.1.2 Class locale::facet + class locale::facet + { + private: + friend class locale; + friend class locale::_Impl; + + mutable _Atomic_word _M_references; + + protected: + // Contains data from the underlying "C" library for the classic locale. + static __c_locale _S_c_locale; + + // String literal for the name of the classic locale. + static char _S_c_name[2]; + + explicit + facet(size_t __refs = 0) throw() : _M_references(__refs ? 1 : 0) + { } + + virtual + ~facet(); + + static void + _S_create_c_locale(__c_locale& __cloc, const char* __s, + __c_locale __old = 0); + + static __c_locale + _S_clone_c_locale(__c_locale& __cloc); + + static void + _S_destroy_c_locale(__c_locale& __cloc); + + private: + inline void + _M_add_reference() const throw() + { __atomic_add(&_M_references, 1); } + + inline void + _M_remove_reference() const throw() + { + if (__exchange_and_add(&_M_references, -1) == 1) + { + try + { delete this; } + catch (...) + { } + } + } + + facet(const facet&); // Not defined. + + void + operator=(const facet&); // Not defined. + }; + + + // 22.1.1.1.3 Class locale::id + class locale::id + { + private: + friend class locale; + friend class locale::_Impl; + + template + friend const _Facet& + use_facet(const locale&); + + template + friend bool + has_facet(const locale&) throw (); + + // NB: There is no accessor for _M_index because it may be used + // before the constructor is run; the effect of calling a member + // function (even an inline) would be undefined. + mutable size_t _M_index; + + // Last id number assigned. + static _Atomic_word _S_highwater; + + void + operator=(const id&); // Not defined. + + id(const id&); // Not defined. + + public: + // NB: This class is always a static data member, and thus can be + // counted on to be zero-initialized. + id() { } + + inline size_t + _M_id() const + { + if (!_M_index) + _M_index = 1 + __exchange_and_add(&_S_highwater, 1); + return _M_index - 1; + } + }; + + + // Implementation object for locale. class locale::_Impl { public: @@ -185,19 +289,24 @@ namespace std friend class locale; friend class locale::facet; + template + friend bool + has_facet(const locale&) throw(); + template friend const _Facet& use_facet(const locale&); - template - friend bool - has_facet(const locale&) throw(); + template + friend const _Cache& + __use_cache(const locale& __loc); private: // Data Members. _Atomic_word _M_references; const facet** _M_facets; size_t _M_facets_size; + const facet** _M_caches; char** _M_names; static const locale::id* const _S_id_ctype[]; static const locale::id* const _S_id_numeric[]; @@ -258,7 +367,14 @@ namespace std template inline void _M_init_facet(_Facet* __facet) - { _M_install_facet(&_Facet::id, __facet); } + { _M_install_facet(&_Facet::id, __facet); } + + void + _M_install_cache(const facet* __cache, size_t __index) + { + __cache->_M_add_reference(); + _M_caches[__index] = __cache; + } }; template @@ -274,93 +390,6 @@ namespace std _M_impl->_M_names[__i] = __new; } } - - - // 22.1.1.1.2 Class locale::facet - class locale::facet - { - private: - friend class locale; - friend class locale::_Impl; - - mutable _Atomic_word _M_references; - - protected: - // Contains data from the underlying "C" library for the classic locale. - static __c_locale _S_c_locale; - - // String literal for the name of the classic locale. - static char _S_c_name[2]; - - explicit - facet(size_t __refs = 0) throw(); - - virtual - ~facet(); - - static void - _S_create_c_locale(__c_locale& __cloc, const char* __s, - __c_locale __old = 0); - - static __c_locale - _S_clone_c_locale(__c_locale& __cloc); - - static void - _S_destroy_c_locale(__c_locale& __cloc); - - private: - void - _M_add_reference() const throw(); - - void - _M_remove_reference() const throw(); - - facet(const facet&); // Not defined. - - void - operator=(const facet&); // Not defined. - }; - - - // 22.1.1.1.3 Class locale::id - class locale::id - { - private: - friend class locale; - friend class locale::_Impl; - template - friend const _Facet& - use_facet(const locale&); - template - friend bool - has_facet(const locale&) throw (); - - // NB: There is no accessor for _M_index because it may be used - // before the constructor is run; the effect of calling a member - // function (even an inline) would be undefined. - mutable size_t _M_index; - - // Last id number assigned. - static _Atomic_word _S_highwater; - - void - operator=(const id&); // Not defined. - - id(const id&); // Not defined. - - public: - // NB: This class is always a static data member, and thus can be - // counted on to be zero-initialized. - id(); - - inline size_t - _M_id() const - { - if (!_M_index) - _M_index = 1 + __exchange_and_add(&_S_highwater, 1); - return _M_index - 1; - } - }; } // namespace std #endif diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h index a0060e8d591..72141f1983e 100644 --- a/libstdc++-v3/include/bits/locale_facets.h +++ b/libstdc++-v3/include/bits/locale_facets.h @@ -574,6 +574,96 @@ namespace std _S_format_float(const ios_base& __io, char* __fptr, char __mod); }; + template + struct __numpunct_cache : public locale::facet + { + // Types: + typedef _CharT char_type; + + const char* _M_grouping; + bool _M_use_grouping; + const char_type* _M_truename; + const char_type* _M_falsename; + char_type _M_decimal_point; + char_type _M_thousands_sep; + + // A list of valid numeric literals for output: in the standard + // "C" locale, this is "-+xX0123456789abcdef0123456789ABCDEF". + // This array contains the chars after having been passed + // through the current locale's ctype<_CharT>.widen(). + _CharT _M_atoms_out[__num_base::_S_oend + 1]; + + // A list of valid numeric literals for output: in the standard + // "C" locale, this is "0123456789eEabcdfABCDF" + // This array contains the chars after having been passed + // through the current locale's ctype<_CharT>.widen(). + _CharT _M_atoms_in[__num_base::_S_iend + 1]; + + bool _M_allocated; + + __numpunct_cache(size_t __refs = 0) : locale::facet(__refs), + _M_grouping(NULL), _M_use_grouping(false), _M_truename(NULL), + _M_falsename(NULL), _M_decimal_point(char_type()), + _M_thousands_sep(char_type()), _M_allocated(false) + { } + + ~__numpunct_cache(); + + void + _M_cache(const locale& __loc); + }; + + template + void + __numpunct_cache<_CharT>::_M_cache(const locale& __loc) + { + const numpunct<_CharT>& __np = use_facet >(__loc); + string __grouping = __np.grouping(); + char* __group = new char[__grouping.length() + 1]; + __grouping.copy(__group, __grouping.length()); + __group[__grouping.length()] = _CharT(); + _M_grouping = __group; + + _M_use_grouping = __grouping.length() != 0 && __grouping.data()[0] != 0; + + typedef basic_string<_CharT> __string_type; + + __string_type __true = __np.truename(); + _CharT* __truename = new _CharT[__true.length() + 1]; + __true.copy(__truename, __true.length()); + __truename[__true.length()] = _CharT(); + _M_truename = __truename; + + __string_type __false = __np.falsename(); + _CharT* __falsename = new _CharT[__false.length() + 1]; + __false.copy(__falsename, __false.length()); + __falsename[__false.length()] = _CharT(); + _M_falsename = __falsename; + + _M_decimal_point = __np.decimal_point(); + _M_thousands_sep = __np.thousands_sep(); + + const ctype<_CharT>& __ct = use_facet >(__loc); + __ct.widen(__num_base::_S_atoms_out, + __num_base::_S_atoms_out + __num_base::_S_oend, _M_atoms_out); + _M_atoms_out[__num_base::_S_oend] = _CharT(); + __ct.widen(__num_base::_S_atoms_in, + __num_base::_S_atoms_in + __num_base::_S_iend, _M_atoms_in); + _M_atoms_in[__num_base::_S_iend] = _CharT(); + + _M_allocated = true; + } + + template + __numpunct_cache<_CharT>::~__numpunct_cache() + { + if (_M_allocated) + { + delete [] _M_grouping; + delete [] _M_truename; + delete [] _M_falsename; + } + } template class numpunct : public locale::facet @@ -582,23 +672,26 @@ namespace std // Types: typedef _CharT char_type; typedef basic_string<_CharT> string_type; + typedef __numpunct_cache<_CharT> __cache_type; - static locale::id id; - - private: - char_type _M_decimal_point; - char_type _M_thousands_sep; - const char* _M_grouping; - const char_type* _M_truename; - const char_type* _M_falsename; + protected: + __cache_type* _M_data; public: + static locale::id id; + explicit - numpunct(size_t __refs = 0) : locale::facet(__refs) + numpunct(size_t __refs = 0) : facet(__refs), _M_data(NULL) { _M_initialize_numpunct(); } explicit - numpunct(__c_locale __cloc, size_t __refs = 0) : locale::facet(__refs) + numpunct(__cache_type* __cache, size_t __refs = 0) + : facet(__refs), _M_data(__cache) + { _M_initialize_numpunct(); } + + explicit + numpunct(__c_locale __cloc, size_t __refs = 0) + : locale::facet(__refs), _M_data(NULL) { _M_initialize_numpunct(__cloc); } char_type @@ -627,23 +720,23 @@ namespace std virtual char_type do_decimal_point() const - { return _M_decimal_point; } + { return _M_data->_M_decimal_point; } virtual char_type do_thousands_sep() const - { return _M_thousands_sep; } + { return _M_data->_M_thousands_sep; } virtual string do_grouping() const - { return _M_grouping; } + { return _M_data->_M_grouping; } virtual string_type do_truename() const - { return _M_truename; } + { return _M_data->_M_truename; } virtual string_type do_falsename() const - { return _M_falsename; } + { return _M_data->_M_falsename; } // For use at construction time only. void @@ -1928,75 +2021,6 @@ namespace std inline _CharT tolower(_CharT __c, const locale& __loc) { return use_facet >(__loc).tolower(__c); } - - - // __locale_cache holds the information extracted from the - // numpunct<> and moneypunct<> facets in a form optimized for - // parsing and formatting. It is stored as an - // auto_ptr<__locale_cache_base> member of ios_base and directly - // accessed via a casting to the derived __locale_cache<_CharT> in - // parameterized facets. - // The intent twofold: to avoid the costs of creating a locale - // object and to avoid calling the virtual functions in a locale's - // facet to look up data. - class __locale_cache_base - { - public: - virtual - ~__locale_cache_base() { } - }; - - template - class __locale_cache : public __locale_cache_base - { - // Types: - typedef _CharT char_type; - typedef char_traits<_CharT> traits_type; - typedef basic_string<_CharT> string_type; - - public: - // Data Members: - - // A list of valid numeric literals: for the standard "C" - // locale, this is "-+xX0123456789abcdef0123456789ABCDEF". This - // array contains the chars after having been passed through the - // current locale's ctype<_CharT>.widen(). - _CharT _M_literals[__num_base::_S_oend]; - - // The sign used to separate decimal values: for standard US - // locales, this would usually be: "." Abstracted from - // numpunct::decimal_point(). - _CharT _M_decimal_point; - - // The sign used to separate groups of digits into smaller - // strings that the eye can parse with less difficulty: for - // standard US locales, this would usually be: "," Abstracted - // from numpunct::thousands_sep(). - _CharT _M_thousands_sep; - - // However the US's "false" and "true" are translated. From - // numpunct::truename() and numpunct::falsename(), respectively. - string_type _M_truename; - string_type _M_falsename; - - // If we are checking groupings. This should be equivalent to - // numpunct::groupings().size() != 0 - bool _M_use_grouping; - - // If we are using numpunct's groupings, this is the current - // grouping string in effect (from numpunct::grouping()). - string _M_grouping; - - __locale_cache() : _M_use_grouping(false) - { }; - - __locale_cache& - operator=(const __locale_cache& __lc); - - // Make sure the cache is built before the first use. - void - _M_init(const locale&); - }; } // namespace std #endif diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index 624018285d8..5081591c1cb 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -86,6 +86,21 @@ namespace std return static_cast(*__facets[__i]); } + // Routine to access a cache for the facet. If the cache didn't + // exist before, it gets constructed on the fly. + template + const _Facet& + __use_cache(const locale& __loc); + + template<> + const __numpunct_cache& + __use_cache(const locale& __loc); + +#ifdef _GLIBCPP_USE_WCHAR_T + template<> + const __numpunct_cache& + __use_cache(const locale& __loc); +#endif // Stage 1: Determine a conversion specifier. template @@ -768,11 +783,12 @@ namespace std _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, _ValueT __v) const { - typedef __locale_cache<_CharT> __cache_type; - __cache_type& __lc = static_cast<__cache_type&>(__io._M_cache()); - _CharT* __lit = __lc._M_literals; + typedef typename numpunct<_CharT>::__cache_type __cache_type; + const locale& __loc = __io._M_getloc(); + const __cache_type& __lc = __use_cache<__cache_type>(__loc); + const _CharT* __lit = __lc._M_atoms_out; - // Long enough to hold hex, dec, and octal representations. + // Long enough to hold hex, dec, and octal representations. int __ilen = 4 * sizeof(_ValueT); _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __ilen)); @@ -872,8 +888,9 @@ namespace std else if (__prec < static_cast(0)) __prec = static_cast(6); - typedef __locale_cache<_CharT> __cache_type; - __cache_type& __lc = static_cast<__cache_type&>(__io._M_cache()); + typedef typename numpunct<_CharT>::__cache_type __cache_type; + const locale& __loc = __io._M_getloc(); + const __cache_type& __lc = __use_cache<__cache_type>(__loc); // [22.2.2.2.2] Stage 1, numeric conversion to character. int __len; @@ -918,7 +935,6 @@ namespace std // [22.2.2.2.2] Stage 2, convert to char_type, using correct // numpunct.decimal_point() values for '.' and adding grouping. - const locale __loc = __io.getloc(); const ctype<_CharT>& __ctype = use_facet >(__loc); _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) @@ -974,8 +990,10 @@ namespace std } else { - typedef __locale_cache<_CharT> __cache_type; - __cache_type& __lc = static_cast<__cache_type&>(__io._M_cache()); + typedef typename numpunct<_CharT>::__cache_type __cache_type; + const locale& __loc = __io._M_getloc(); + const __cache_type& __lc = __use_cache<__cache_type>(__loc); + typedef basic_string<_CharT> __string_type; __string_type __name; if (__v) @@ -2273,31 +2291,6 @@ namespace std return __s; } - // Generic definition, locale cache initialization. - template - void - __locale_cache<_CharT>::_M_init(const locale& __loc) - { - if (__builtin_expect(has_facet >(__loc), true)) - { - const numpunct<_CharT>& __np = use_facet >(__loc); - _M_falsename = __np.falsename(); - _M_truename = __np.truename(); - _M_thousands_sep = __np.thousands_sep(); - _M_decimal_point = __np.decimal_point(); - _M_grouping = __np.grouping(); - _M_use_grouping = _M_grouping.size() != 0 - && _M_grouping.data()[0] != 0; - } - if (__builtin_expect(has_facet >(__loc), true)) - { - const ctype<_CharT>& __ct = use_facet >(__loc); - __ct.widen(__num_base::_S_atoms_out, - __num_base::_S_atoms_out + __num_base::_S_oend, - _M_literals); - } - } - // Inhibit implicit instantiations for required instantiations, // which are defined via explicit instantiations elsewhere. // NB: This syntax is a GNU extension. diff --git a/libstdc++-v3/src/globals.cc b/libstdc++-v3/src/globals.cc index a0220f1cd8e..6793a9b5da1 100644 --- a/libstdc++-v3/src/globals.cc +++ b/libstdc++-v3/src/globals.cc @@ -127,6 +127,10 @@ namespace __gnu_cxx __attribute__ ((aligned(__alignof__(locale::facet*)))); fake_facet_vec facet_vec[_GLIBCPP_NUM_FACETS]; + typedef char fake_cache_vec[sizeof(locale::facet*)] + __attribute__ ((aligned(__alignof__(locale::facet*)))); + fake_cache_vec cache_vec[_GLIBCPP_NUM_FACETS]; + typedef char fake_ctype_c[sizeof(std::ctype)] __attribute__ ((aligned(__alignof__(std::ctype)))); fake_ctype_c ctype_c; @@ -235,6 +239,17 @@ namespace __gnu_cxx fake_messages_w messages_w; #endif + // Storage for C locale caches + typedef char fake_locale_cache_c[sizeof(std::__numpunct_cache)] + __attribute__ ((aligned(__alignof__(std::__numpunct_cache)))); + fake_locale_cache_c numpunct_cache_c; + +#ifdef _GLIBCPP_USE_WCHAR_T + typedef char fake_locale_cache_w[sizeof(std::__numpunct_cache)] + __attribute__ ((aligned(__alignof__(std::__numpunct_cache)))); + fake_locale_cache_w numpunct_cache_w; +#endif + // Globals for once-only runtime initialization of mutex objects. This // allows static initialization of these objects on systems that need a // function call to initialize a mutex. For example, see stl_threads.h. diff --git a/libstdc++-v3/src/ios.cc b/libstdc++-v3/src/ios.cc index ee4fd24cc54..ee969b5d9c7 100644 --- a/libstdc++-v3/src/ios.cc +++ b/libstdc++-v3/src/ios.cc @@ -297,8 +297,8 @@ namespace std return __old; } - ios_base::ios_base() : _M_callbacks(0), _M_word_size(_S_local_word_size), - _M_word(_M_local_word), _M_locale_cache(0) + ios_base::ios_base() + : _M_callbacks(0), _M_word_size(_S_local_word_size), _M_word(_M_local_word) { // Do nothing: basic_ios::init() does it. // NB: _M_callbacks and _M_word must be zero for non-initialized diff --git a/libstdc++-v3/src/locale-inst.cc b/libstdc++-v3/src/locale-inst.cc index 73b028df1be..0936102a916 100644 --- a/libstdc++-v3/src/locale-inst.cc +++ b/libstdc++-v3/src/locale-inst.cc @@ -45,7 +45,6 @@ namespace std template class moneypunct_byname; template class money_get >; template class money_put >; - template class __locale_cache; #ifdef _GLIBCPP_USE_WCHAR_T template class moneypunct; @@ -54,11 +53,11 @@ namespace std template class moneypunct_byname; template class money_get >; template class money_put >; - template class __locale_cache; #endif // numpunct, numpunct_byname, num_get, and num_put template class numpunct; + template struct __numpunct_cache; template class numpunct_byname; template class num_get >; template class num_put >; @@ -102,6 +101,7 @@ namespace std #ifdef _GLIBCPP_USE_WCHAR_T template class numpunct; + template struct __numpunct_cache; template class numpunct_byname; template class num_get >; template class num_put >; diff --git a/libstdc++-v3/src/locale.cc b/libstdc++-v3/src/locale.cc index db08de0feca..7788a58419d 100644 --- a/libstdc++-v3/src/locale.cc +++ b/libstdc++-v3/src/locale.cc @@ -449,30 +449,37 @@ namespace std locale::facet:: ~facet() { } - locale::facet:: - facet(size_t __refs) throw() : _M_references(__refs ? 1 : 0) - { } + template<> + const __numpunct_cache& + __use_cache(const locale& __loc) + { + size_t __i = numpunct::id._M_id(); + const locale::facet** __caches = __loc._M_impl->_M_caches; + if (!__caches[__i]) + { + __numpunct_cache* __tmp = new __numpunct_cache; + __tmp->_M_cache(__loc); + __loc._M_impl->_M_install_cache(__tmp, __i); + } + return static_cast&>(*__caches[__i]); + } - void - locale::facet:: - _M_add_reference() const throw() - { __atomic_add(&_M_references, 1); } - - void - locale::facet:: - _M_remove_reference() const throw() - { - if (__exchange_and_add(&_M_references, -1) == 1) - { - try - { delete this; } - catch (...) - { } - } - } - - locale::id::id() - { } +#ifdef _GLIBCPP_USE_WCHAR_T + template<> + const __numpunct_cache& + __use_cache(const locale& __loc) + { + size_t __i = numpunct::id._M_id(); + const locale::facet** __caches = __loc._M_impl->_M_caches; + if (!__caches[__i]) + { + __numpunct_cache* __tmp = new __numpunct_cache; + __tmp->_M_cache(__loc); + __loc._M_impl->_M_install_cache(__tmp, __i); + } + return static_cast&>(*__caches[__i]); + } +#endif // Definitions for static const data members of time_base template<> diff --git a/libstdc++-v3/src/localename.cc b/libstdc++-v3/src/localename.cc index c09900b628f..424bc64fec7 100644 --- a/libstdc++-v3/src/localename.cc +++ b/libstdc++-v3/src/localename.cc @@ -69,6 +69,12 @@ namespace __gnu_cxx extern time_put time_put_w; extern std::messages messages_w; #endif + + extern locale::facet* cache_vec[_GLIBCPP_NUM_FACETS]; + extern std::__numpunct_cache numpunct_cache_c; +#ifdef _GLIBCPP_USE_WCHAR_T + extern std::__numpunct_cache numpunct_cache_w; +#endif } // namespace __gnu_cxx namespace std @@ -83,6 +89,11 @@ namespace std _M_facets[__i]->_M_remove_reference(); delete [] _M_facets; + for (size_t __i = 0; __i < _M_facets_size; ++__i) + if (_M_caches[__i]) + _M_caches[__i]->_M_remove_reference(); + delete [] _M_caches; + for (size_t __i = 0; __i < _S_categories_size; ++__i) delete [] _M_names[__i]; delete [] _M_names; @@ -91,7 +102,7 @@ namespace std // Clone existing _Impl object. locale::_Impl:: _Impl(const _Impl& __imp, size_t __refs) - : _M_references(__refs), _M_facets_size(__imp._M_facets_size) // XXX + : _M_references(__refs), _M_facets_size(__imp._M_facets_size) { try { @@ -111,6 +122,22 @@ namespace std _M_facets[__i]->_M_add_reference(); } + try + { + _M_caches = new const facet*[_M_facets_size]; + } + catch(...) + { + delete [] _M_caches; + __throw_exception_again; + } + for (size_t __i = 0; __i < _M_facets_size; ++__i) + { + _M_caches[__i] = __imp._M_caches[__i]; + if (_M_caches[__i]) + _M_caches[__i]->_M_add_reference(); + } + try { _M_names = new char*[_S_categories_size]; @@ -131,10 +158,10 @@ namespace std // Construct named _Impl. locale::_Impl:: _Impl(const char* __s, size_t __refs) - : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS) + : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS) { - // Initialize the underlying locale model, which also checks - // to see if the given name is valid. + // Initialize the underlying locale model, which also checks to + // see if the given name is valid. __c_locale __cloc; locale::facet::_S_create_c_locale(__cloc, __s); @@ -150,6 +177,18 @@ namespace std __throw_exception_again; } + try + { + _M_caches = new const facet*[_M_facets_size]; + for (size_t __i = 0; __i < _M_facets_size; ++__i) + _M_caches[__i] = 0; + } + catch(...) + { + delete [] _M_caches; + __throw_exception_again; + } + // Name all the categories. try { @@ -235,6 +274,10 @@ namespace std for (size_t __i = 0; __i < _M_facets_size; ++__i) _M_facets[__i] = 0; + _M_caches = new (&cache_vec) const facet*[_M_facets_size]; + for (size_t __i = 0; __i < _M_facets_size; ++__i) + _M_caches[__i] = 0; + // Name all the categories. _M_names = new (&name_vec) char*[_S_categories_size]; for (size_t __i = 0; __i < _S_categories_size; ++__i) @@ -252,7 +295,12 @@ namespace std // destroyed. _M_init_facet(new (&ctype_c) std::ctype(0, false, 1)); _M_init_facet(new (&codecvt_c) codecvt(1)); - _M_init_facet(new (&numpunct_c) numpunct(1)); + + // Safe to cache this. + typedef __numpunct_cache num_cache_c; + num_cache_c* __npc = new (&numpunct_cache_c) num_cache_c(2); + _M_init_facet(new (&numpunct_c) numpunct(__npc, 1)); + _M_init_facet(new (&num_get_c) num_get(1)); _M_init_facet(new (&num_put_c) num_put(1)); _M_init_facet(new (&collate_c) std::collate(1)); @@ -264,10 +312,15 @@ namespace std _M_init_facet(new (&time_get_c) time_get(1)); _M_init_facet(new (&time_put_c) time_put(1)); _M_init_facet(new (&messages_c) std::messages(1)); + #ifdef _GLIBCPP_USE_WCHAR_T _M_init_facet(new (&ctype_w) std::ctype(1)); _M_init_facet(new (&codecvt_w) codecvt(1)); - _M_init_facet(new (&numpunct_w) numpunct(1)); + + typedef __numpunct_cache num_cache_w; + num_cache_w* __npw = new (&numpunct_cache_w) num_cache_w(2); + _M_init_facet(new (&numpunct_w) numpunct(__npw, 1)); + _M_init_facet(new (&num_get_w) num_get(1)); _M_init_facet(new (&num_put_w) num_put(1)); _M_init_facet(new (&collate_w) std::collate(1)); @@ -280,6 +333,13 @@ namespace std _M_init_facet(new (&time_put_w) time_put(1)); _M_init_facet(new (&messages_w) std::messages(1)); #endif + + // This locale is safe to pre-cache, after all the facets have + // been installed. + _M_caches[numpunct::id._M_id()] = __npc; +#ifdef _GLIBCPP_USE_WCHAR_T + _M_caches[numpunct::id._M_id()] = __npw; +#endif } void @@ -336,18 +396,31 @@ namespace std // Check size of facet vector to ensure adequate room. if (__index > _M_facets_size - 1) { - const facet** __old = _M_facets; - const facet** __new; const size_t __new_size = __index + 4; - __new = new const facet*[__new_size]; + + // New facet array. + const facet** __oldf = _M_facets; + const facet** __newf; + __newf = new const facet*[__new_size]; for (size_t __i = 0; __i < _M_facets_size; ++__i) - __new[__i] = _M_facets[__i]; + __newf[__i] = _M_facets[__i]; for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2) - __new[__i2] = 0; + __newf[__i2] = 0; + + // New cache array. + const facet** __oldc = _M_caches; + const facet** __newc; + __newc = new const facet*[__new_size]; + for (size_t __i = 0; __i < _M_facets_size; ++__i) + __newc[__i] = _M_caches[__i]; + for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2) + __newc[__i2] = 0; _M_facets_size = __new_size; - _M_facets = __new; - delete [] __old; + _M_facets = __newf; + _M_caches = __newc; + delete [] __oldf; + delete [] __oldc; } __fp->_M_add_reference(); @@ -365,6 +438,21 @@ namespace std // swanky-fresh _Impl. _M_facets[__index] = __fp; } + + // Ideally, it would be nice to only remove the caches that + // are now incorrect. However, some of the caches depend on + // multiple facets, and we only know about one facet + // here. It's no great loss: the first use of the new facet + // will create a new, correctly cached facet anyway. + for (size_t __i = 0; __i < _M_facets_size; ++__i) + { + const facet* __cpr = _M_caches[__i]; + if (__cpr) + { + __cpr->_M_remove_reference(); + _M_caches[__i] = 0; + } + } } } } // namespace std diff --git a/libstdc++-v3/testsuite/27_io/ios_base/cons/assign_neg.cc b/libstdc++-v3/testsuite/27_io/ios_base/cons/assign_neg.cc index 7e138313b6f..e6f9921b368 100644 --- a/libstdc++-v3/testsuite/27_io/ios_base/cons/assign_neg.cc +++ b/libstdc++-v3/testsuite/27_io/ios_base/cons/assign_neg.cc @@ -41,5 +41,5 @@ void test01() io1 = io2; } // { dg-error "within this context" "" { target *-*-* } 41 } -// { dg-error "is private" "" { target *-*-* } 666 } +// { dg-error "is private" "" { target *-*-* } 696 } // { dg-error "operator=" "" { target *-*-* } 0 } diff --git a/libstdc++-v3/testsuite/27_io/ios_base/cons/copy_neg.cc b/libstdc++-v3/testsuite/27_io/ios_base/cons/copy_neg.cc index 56531485c8b..5d77444b342 100644 --- a/libstdc++-v3/testsuite/27_io/ios_base/cons/copy_neg.cc +++ b/libstdc++-v3/testsuite/27_io/ios_base/cons/copy_neg.cc @@ -41,5 +41,5 @@ void test02() test_base io2 = io1; } // { dg-error "within this context" "" { target *-*-* } 41 } -// { dg-error "is private" "" { target *-*-* } 663 } +// { dg-error "is private" "" { target *-*-* } 693 } // { dg-error "copy constructor" "" { target *-*-* } 0 }