diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 62ee709966b..5f1afaade75 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,8 @@ +2002-10-09 Benjamin Kosnik + + * src/locale.cc: Fix comments, move ctors together. + * testsuite/22_locale/static_members.cc (test03): Add. + 2002-10-08 Jonathan Lennox PR libstdc++/8071, libstdc++/8127, libstdc++/6745 diff --git a/libstdc++-v3/src/locale.cc b/libstdc++-v3/src/locale.cc index 641bee21baa..d9c69313491 100644 --- a/libstdc++-v3/src/locale.cc +++ b/libstdc++-v3/src/locale.cc @@ -148,25 +148,6 @@ namespace std 0 }; - locale::~locale() throw() - { _M_impl->_M_remove_reference(); } - - void - locale::_M_coalesce(const locale& __base, const locale& __add, - category __cat) - { - __cat = _S_normalize_category(__cat); - _M_impl = new _Impl(*__base._M_impl, 1); - - try - { _M_impl->_M_replace_categories(__add._M_impl, __cat); } - catch (...) - { - _M_impl->_M_remove_reference(); - __throw_exception_again; - } - } - locale::locale() throw() { _S_initialize(); @@ -178,6 +159,7 @@ namespace std // This is used to initialize global and classic locales, and // assumes that the _Impl objects are constructed correctly. + // The lack of a reference increment is intentional. locale::locale(_Impl* __ip) throw() : _M_impl(__ip) { } @@ -309,6 +291,9 @@ namespace std locale::locale(const locale& __base, const locale& __add, category __cat) { _M_coalesce(__base, __add, __cat); } + locale::~locale() throw() + { _M_impl->_M_remove_reference(); } + bool locale::operator==(const locale& __rhs) const throw() { @@ -381,7 +366,7 @@ namespace std try { // 26 Standard facets, 2 references. - // One reference for _M_classic, one for _M_global + // One reference for _S_classic, one for _S_global _S_classic = new (&c_locale_impl) _Impl(0, 2, true); _S_global = _S_classic; new (&c_locale) locale(_S_classic); @@ -399,6 +384,22 @@ namespace std return c_locale; } + void + locale::_M_coalesce(const locale& __base, const locale& __add, + category __cat) + { + __cat = _S_normalize_category(__cat); + _M_impl = new _Impl(*__base._M_impl, 1); + + try + { _M_impl->_M_replace_categories(__add._M_impl, __cat); } + catch (...) + { + _M_impl->_M_remove_reference(); + __throw_exception_again; + } + } + locale::category locale::_S_normalize_category(category __cat) { diff --git a/libstdc++-v3/testsuite/22_locale/static_members.cc b/libstdc++-v3/testsuite/22_locale/static_members.cc index 06b125852c2..f8a909203dc 100644 --- a/libstdc++-v3/testsuite/22_locale/static_members.cc +++ b/libstdc++-v3/testsuite/22_locale/static_members.cc @@ -23,8 +23,7 @@ #include // for mbstate_t #include #include -//#include -#define VERIFY(x) test &= x +#include typedef std::codecvt ccodecvt; class gnu_codecvt: public ccodecvt { }; @@ -32,12 +31,11 @@ class gnu_codecvt: public ccodecvt { }; void test01() { using namespace std; - bool test = true; + string str1, str2; // Construct a locale object with the C facet. - const locale loc_env(""); const locale loc01 = locale::classic(); // Construct a locale object with the specialized facet. @@ -54,13 +52,13 @@ void test01() // global locale loc03; VERIFY ( loc03 == loc01); - locale loc04 = locale::global(loc02); + locale global_orig = locale::global(loc02); locale loc05; VERIFY (loc05 != loc03); VERIFY (loc05 == loc02); - // Reset global locale. - locale::global(loc_env); + // Reset global settings. + locale::global(global_orig); } // Sanity check locale::global(loc) and setlocale. @@ -77,20 +75,102 @@ void test02() // Get underlying current locale and environment settings. const string lc_all_orig = std::setlocale(LC_ALL, NULL); - const locale loc_orig(""); + const locale env_orig(""); // setlocale to en_PH string lc_all_ph = std::setlocale(LC_ALL, ph.c_str()); const locale loc_env(""); - VERIFY( loc_env == loc_orig ); + VERIFY( loc_env == env_orig ); - locale::global(loc_mx); + locale global_orig = locale::global(loc_mx); string lc_all_mx = std::setlocale(LC_ALL, NULL); VERIFY( lc_all_mx == mx.c_str() ); - // Restore global info. - locale::global(loc_orig); + // Restore global settings. + locale::global(global_orig); +} + +// Static counter for use in checking ctors/dtors. +static std::size_t counter; + +class surf : public std::locale::facet +{ +public: + static std::locale::id id; + surf(size_t refs = 0): std::locale::facet(refs) { ++counter; } + ~surf() { --counter; } +}; + +std::locale::id surf::id; + +typedef surf facet_type; + +// Verify lifetimes of global objects. +void test03() +{ + using namespace std; + bool test = true; + + string name; + locale global_orig; + // 1: Destroyed when out of scope. + { + { + { + VERIFY( counter == 0 ); + { + locale loc01(locale::classic(), new facet_type); + VERIFY( counter == 1 ); + global_orig = locale::global(loc01); + name = loc01.name(); + } + VERIFY( counter == 1 ); + locale loc02 = locale(); + // Weak, but it's something... + VERIFY( loc02.name() == name ); + } + VERIFY( counter == 1 ); + // NB: loc03 should be a copy of the previous global locale. + locale loc03 = locale::global(global_orig); + VERIFY( counter == 1 ); + VERIFY( loc03.name() == name ); + } + VERIFY( counter == 0 ); + locale loc04 = locale(); + VERIFY( loc04 == global_orig ); + } + + // 2: Not destroyed when out of scope, deliberately leaked. + { + { + { + VERIFY( counter == 0 ); + { + locale loc01(locale::classic(), new facet_type(1)); + VERIFY( counter == 1 ); + global_orig = locale::global(loc01); + name = loc01.name(); + } + VERIFY( counter == 1 ); + locale loc02 = locale(); + // Weak, but it's something... + VERIFY( loc02.name() == name ); + } + VERIFY( counter == 1 ); + // NB: loc03 should be a copy of the previous global locale. + locale loc03 = locale::global(global_orig); + VERIFY( counter == 1 ); + VERIFY( loc03.name() == name ); + } + VERIFY( counter == 1 ); + locale loc04 = locale(); + VERIFY( loc04 == global_orig ); + } + VERIFY( counter == 1 ); + + // Restore global settings. + locale::global(global_orig); } int main () @@ -98,5 +178,6 @@ int main () test01(); test02(); + test03(); return 0; }