ios_base.h (ios_base::_M_getloc): Return reference to the imbued locale.

2003-06-26  Benjamin Kosnik  <bkoz@redhat.com>

	* 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  <bkoz@redhat.com>
	    Jerry Quinn  <jlquinn@optonline.net>

	* 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.

Co-Authored-By: Jerry Quinn <jlquinn@optonline.net>

From-SVN: r68558
This commit is contained in:
Benjamin Kosnik 2003-06-27 07:25:38 +00:00 committed by Benjamin Kosnik
parent d51d146fb0
commit 215f9e283a
16 changed files with 621 additions and 316 deletions

View File

@ -1,3 +1,49 @@
2003-06-26 Benjamin Kosnik <bkoz@redhat.com>
* 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 <bkoz@redhat.com>
Jerry Quinn <jlquinn@optonline.net>
* 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 <ncm-nospam@cantrip.org>
Paolo Carlini <pcarlini@unitus.it>

View File

@ -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.

View File

@ -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<char>::_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<char>;
_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<char>::~numpunct()
{ }
{ delete _M_data; }
#ifdef _GLIBCPP_USE_WCHAR_T
template<>
@ -59,15 +73,37 @@ namespace std
numpunct<wchar_t>::_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<wchar_t>;
_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<unsigned char>(__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<unsigned char>(__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<wchar_t>::~numpunct()
{ }
{ delete _M_data; }
#endif
}

View File

@ -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<char>::_M_initialize_numpunct(__c_locale __cloc)
{
if (!_M_data)
_M_data = new __numpunct_cache<char>;
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<char>::~numpunct()
{ }
{ delete _M_data; }
#ifdef _GLIBCPP_USE_WCHAR_T
template<>
void
numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc)
{
if (!_M_data)
_M_data = new __numpunct_cache<wchar_t>;
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<unsigned char>(__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<unsigned char>(__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<wchar_t>(__u.__w);
_M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
__u.__s = __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc);
_M_thousands_sep = static_cast<wchar_t>(__u.__w);
if (_M_thousands_sep == L'\0')
_M_grouping = "";
_M_data->_M_thousands_sep = static_cast<wchar_t>(__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<wchar_t>::~numpunct()
{ }
{ delete _M_data; }
#endif
}

View File

@ -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,

View File

@ -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

View File

@ -71,7 +71,11 @@ namespace std
template<typename _Facet>
friend const _Facet&
use_facet(const locale&);
template<typename _Cache>
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<typename _Facet>
friend const _Facet&
use_facet(const locale&);
template<typename _Facet>
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<typename _Facet>
friend bool
has_facet(const locale&) throw();
template<typename _Facet>
friend const _Facet&
use_facet(const locale&);
template<typename _Facet>
friend bool
has_facet(const locale&) throw();
template<typename _Cache>
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<typename _Facet>
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<typename _Facet>
@ -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<typename _Facet>
friend const _Facet&
use_facet(const locale&);
template<typename _Facet>
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

View File

@ -574,6 +574,96 @@ namespace std
_S_format_float(const ios_base& __io, char* __fptr, char __mod);
};
template<typename _CharT>
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<typename _CharT>
void
__numpunct_cache<_CharT>::_M_cache(const locale& __loc)
{
const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__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<ctype<_CharT> >(__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<typename _CharT>
__numpunct_cache<_CharT>::~__numpunct_cache()
{
if (_M_allocated)
{
delete [] _M_grouping;
delete [] _M_truename;
delete [] _M_falsename;
}
}
template<typename _CharT>
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<ctype<_CharT> >(__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<typename _CharT>
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

View File

@ -86,6 +86,21 @@ namespace std
return static_cast<const _Facet&>(*__facets[__i]);
}
// Routine to access a cache for the facet. If the cache didn't
// exist before, it gets constructed on the fly.
template<typename _Facet>
const _Facet&
__use_cache(const locale& __loc);
template<>
const __numpunct_cache<char>&
__use_cache(const locale& __loc);
#ifdef _GLIBCPP_USE_WCHAR_T
template<>
const __numpunct_cache<wchar_t>&
__use_cache(const locale& __loc);
#endif
// Stage 1: Determine a conversion specifier.
template<typename _CharT, typename _InIter>
@ -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<streamsize>(0))
__prec = static_cast<streamsize>(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<ctype<_CharT> >(__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<typename _CharT>
void
__locale_cache<_CharT>::_M_init(const locale& __loc)
{
if (__builtin_expect(has_facet<numpunct<_CharT> >(__loc), true))
{
const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__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<ctype<_CharT> >(__loc), true))
{
const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__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.

View File

@ -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<char>)]
__attribute__ ((aligned(__alignof__(std::ctype<char>))));
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<char>)]
__attribute__ ((aligned(__alignof__(std::__numpunct_cache<char>))));
fake_locale_cache_c numpunct_cache_c;
#ifdef _GLIBCPP_USE_WCHAR_T
typedef char fake_locale_cache_w[sizeof(std::__numpunct_cache<wchar_t>)]
__attribute__ ((aligned(__alignof__(std::__numpunct_cache<wchar_t>))));
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.

View File

@ -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

View File

@ -45,7 +45,6 @@ namespace std
template class moneypunct_byname<char, true>;
template class money_get<char, istreambuf_iterator<char> >;
template class money_put<char, ostreambuf_iterator<char> >;
template class __locale_cache<char>;
#ifdef _GLIBCPP_USE_WCHAR_T
template class moneypunct<wchar_t, false>;
@ -54,11 +53,11 @@ namespace std
template class moneypunct_byname<wchar_t, true>;
template class money_get<wchar_t, istreambuf_iterator<wchar_t> >;
template class money_put<wchar_t, ostreambuf_iterator<wchar_t> >;
template class __locale_cache<wchar_t>;
#endif
// numpunct, numpunct_byname, num_get, and num_put
template class numpunct<char>;
template struct __numpunct_cache<char>;
template class numpunct_byname<char>;
template class num_get<char, istreambuf_iterator<char> >;
template class num_put<char, ostreambuf_iterator<char> >;
@ -102,6 +101,7 @@ namespace std
#ifdef _GLIBCPP_USE_WCHAR_T
template class numpunct<wchar_t>;
template struct __numpunct_cache<wchar_t>;
template class numpunct_byname<wchar_t>;
template class num_get<wchar_t, istreambuf_iterator<wchar_t> >;
template class num_put<wchar_t, ostreambuf_iterator<wchar_t> >;

View File

@ -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<char>&
__use_cache(const locale& __loc)
{
size_t __i = numpunct<char>::id._M_id();
const locale::facet** __caches = __loc._M_impl->_M_caches;
if (!__caches[__i])
{
__numpunct_cache<char>* __tmp = new __numpunct_cache<char>;
__tmp->_M_cache(__loc);
__loc._M_impl->_M_install_cache(__tmp, __i);
}
return static_cast<const __numpunct_cache<char>&>(*__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<wchar_t>&
__use_cache(const locale& __loc)
{
size_t __i = numpunct<wchar_t>::id._M_id();
const locale::facet** __caches = __loc._M_impl->_M_caches;
if (!__caches[__i])
{
__numpunct_cache<wchar_t>* __tmp = new __numpunct_cache<wchar_t>;
__tmp->_M_cache(__loc);
__loc._M_impl->_M_install_cache(__tmp, __i);
}
return static_cast<const __numpunct_cache<wchar_t>&>(*__caches[__i]);
}
#endif
// Definitions for static const data members of time_base
template<>

View File

@ -69,6 +69,12 @@ namespace __gnu_cxx
extern time_put<wchar_t> time_put_w;
extern std::messages<wchar_t> messages_w;
#endif
extern locale::facet* cache_vec[_GLIBCPP_NUM_FACETS];
extern std::__numpunct_cache<char> numpunct_cache_c;
#ifdef _GLIBCPP_USE_WCHAR_T
extern std::__numpunct_cache<wchar_t> 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<char>(0, false, 1));
_M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1));
_M_init_facet(new (&numpunct_c) numpunct<char>(1));
// Safe to cache this.
typedef __numpunct_cache<char> num_cache_c;
num_cache_c* __npc = new (&numpunct_cache_c) num_cache_c(2);
_M_init_facet(new (&numpunct_c) numpunct<char>(__npc, 1));
_M_init_facet(new (&num_get_c) num_get<char>(1));
_M_init_facet(new (&num_put_c) num_put<char>(1));
_M_init_facet(new (&collate_c) std::collate<char>(1));
@ -264,10 +312,15 @@ namespace std
_M_init_facet(new (&time_get_c) time_get<char>(1));
_M_init_facet(new (&time_put_c) time_put<char>(1));
_M_init_facet(new (&messages_c) std::messages<char>(1));
#ifdef _GLIBCPP_USE_WCHAR_T
_M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1));
_M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1));
_M_init_facet(new (&numpunct_w) numpunct<wchar_t>(1));
typedef __numpunct_cache<wchar_t> num_cache_w;
num_cache_w* __npw = new (&numpunct_cache_w) num_cache_w(2);
_M_init_facet(new (&numpunct_w) numpunct<wchar_t>(__npw, 1));
_M_init_facet(new (&num_get_w) num_get<wchar_t>(1));
_M_init_facet(new (&num_put_w) num_put<wchar_t>(1));
_M_init_facet(new (&collate_w) std::collate<wchar_t>(1));
@ -280,6 +333,13 @@ namespace std
_M_init_facet(new (&time_put_w) time_put<wchar_t>(1));
_M_init_facet(new (&messages_w) std::messages<wchar_t>(1));
#endif
// This locale is safe to pre-cache, after all the facets have
// been installed.
_M_caches[numpunct<char>::id._M_id()] = __npc;
#ifdef _GLIBCPP_USE_WCHAR_T
_M_caches[numpunct<wchar_t>::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

View File

@ -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 }

View File

@ -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 }