From: Benjamin Kosnik Date: Thu, 17 Oct 2002 02:04:18 +0000 (+0000) Subject: [multiple changes] X-Git-Tag: releases/gcc-3.2.1~146 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aac88295c5c941757202c85206121c942f3de969;p=thirdparty%2Fgcc.git [multiple changes] 2002-10-16 Benjamin Kosnik * include/bits/locale_facets.h (__timepunct::__timepunct): Allocate _M_name_timepunct. (__timepunct::~__timepunct): Deallocate, remove specialization declarations. (messages::messages): Allocate _M_name_messages. (messages::~messages): Deallocate. (messages_byname): Same. * config/locale/gnu/time_members.cc (__timepunct::~__timepunct): Remove. * config/locale/generic/time_members.cc (__timepunct::~__timepunct): Remove. * docs/html/install.html: Add eqs_MX, en_PH to required locales list. 2002-10-16 Benjamin Kosnik * src/globals.cc (__gnu_cxx::c_locale_impl_compat): Add, alias to c_locale_impl. * testsuite/abi_check.cc (line_to_symbol_info): Collect size info. * docs/html/abi.txt: Update. 2002-10-16 Benjamin Kosnik * testsuite/22_locale/static_members.cc (test02): Less provincial. 2002-10-16 Benjamin Kosnik * testsuite/22_locale/static_members.cc (test02): Disable for systems without named locale support. * testsuite/22_locale/ctor_copy_dtor.cc (test04): Don't assume running the testsuites in "C" environment. Add new tests. * docs/html/22_locale/locale.html: Update. 2002-10-16 Benjamin Kosnik * testsuite/abi_check.cc (hash): Specialize. Simplify. Check compatible symbol versions. * config/linker-map.gnu: Clarify, explicitly export std::codecvt::c* symbols. * testsuite/22_locale/static_members.cc (test02): Avoid null strings. 2002-10-16 Benjamin Kosnik * testsuite/22_locale/static_members.cc (test02): Fix. 2002-10-16 Benjamin Kosnik * acconfig.h (_GLIBCPP_SYMVER): Add. (_GLIBCPP_ASM_SYMVER): Add. * acinclude.m4 (GLIBCPP_ENABLE_SYMVERS): Define _GLIBCPP_SYMVER. * aclocal.m4: Regenerate. * config.h.in: Regenerate. * configure: Regenerate. * include/bits/c++config (_GLIBCPP_AT_AT): Define, as an expedient hack around m4 issues with quoting '@'. * src/locale.cc: Use _GLIBCPP_ASM_SYMVER. * src/globals.cc (__gnu_cxx): Same. * testsuite/22_locale/ctor_copy_dtor.cc (test04): Fix for 2002-10-16 Benjamin Kosnik * config/linker-map.gnu (GLIBCPP_3.2.1): Add. (GLIBCPP_3.2): Don't export locale::_S_*. * src/ios.cc: Move globals into __gnu_cxx. Make old exported symbols match. * src/locale.cc: Same. * src/localename.cc: Same. 2002-10-16 Benjamin Kosnik * src/locale.cc: Fix comments, move ctors together. * testsuite/22_locale/static_members.cc (test03): Add. 2002-10-16 Paolo Carlini Benjamin Kosnik * include/bits/localefwd.h (class locale): Add static member _S_num_extra_categories, encoding the number of additional categories. Change _S_num_categories to _S_categories_size. (class locale::_Impl): Add _M_c_cats. (class locale::_Impl::_M_names): Change to array of chars. (class locale::_Impl::_M_check_same_name): Use _S_extra_categories_size, tweak. (locale::locale(const locale&, _Facet*)): Ditto. * src/locale.cc (locale::locale(const char* )): Rewrite to deal with the environment in a POSIX-compliant way while being thread safe. (locale::name()): Update to output POSIX environment strings. * src/localename.cc (locale::_Impl::_Impl(const _Impl&, size_t): Use _S_categories_size_*, tweak. (locale::_Impl::_Impl(facet**, size_t, bool)): Ditto. (locale::_Impl::_Impl(const char*, size_t)): Name each category individually. (locale::_Impl::_M_replace_categories): Use strcpy. * include/bits/locale_facets.h (numpunct::_M_initialize_numpunct): Change default argument to NULL from _S_c_locale. (timepunct::_M_initialize_timepunct): Same. _S_c_locale cleanups. * src/codecvt.c: _S_c_locale simplification. * src/ctype.c: Same. * src/globals.cc: Add fake_name. * src/locale-inst.cc: Remove extra includes. * src/locale.cc: Remove extra includes. Add _S_extra_categories_size definition. Correct "C" initialization. (locale::facet::facet): Don't initialize _S_c_locale. (locale::facet::_M_remove_reference): Adjust. * src/localename: Use facet_vec, facet_name. (locale::_Impl::_Impl(facet** __f, size_t __refs, bool)): Set facet ref counts to one. Initialize _S_c_locale. (locale::_Impl::_M_install_facet(id*, facet*)): Adjust facet ref counts when installing unilaterally. * config/locale/generic/c_locale.cc: Add _S_categories definition. * config/locale/generic/c_locale.h: Add _GLIBCPP_NUM_CATEGORIES macro. * config/locale/generic/time_members.cc: _S_c_locale cleanup. * config/locale/gnu/c_locale.cc: Add _S_categories definition. (_S_destroy_c_locale): Move checks against _S_c_locale here. * config/locale/gnu/c_locale.h: Add _GLIBCPP_NUM_CATEGORIES macro. * config/locale/gnu/ctype_members.cc: Simplify _S_destroy_c_locale calls, _S_c_locale usage. * config/locale/gnu/monetary_members.cc: Same, tweaks. * config/locale/gnu/monetary_members.cc: Same. * config/locale/gnu/time_members.cc: Same. * config/os/gnu-linux/ctype_noninline.h: Use locale::classic(). * docs/html/22_locale/locale.html: Add bits about global locales and "C" setlocale. * testsuite/22_locale/facet.cc (test02): Add. * testsuite/22_locale/static_members.cc (test02): Add. * testsuite/22_locale/ctor_copy_dtor.cc (test04): Add. From-SVN: r58233 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index ce3c3a2b0065..30f77dd96710 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,145 @@ +2002-10-16 Benjamin Kosnik + + * include/bits/locale_facets.h (__timepunct::__timepunct): Allocate + _M_name_timepunct. + (__timepunct::~__timepunct): Deallocate, remove specialization + declarations. + (messages::messages): Allocate _M_name_messages. + (messages::~messages): Deallocate. + (messages_byname): Same. + * config/locale/gnu/time_members.cc (__timepunct::~__timepunct): + Remove. + * config/locale/generic/time_members.cc (__timepunct::~__timepunct): + Remove. + + * docs/html/install.html: Add eqs_MX, en_PH to required locales list. + +2002-10-16 Benjamin Kosnik + + * src/globals.cc (__gnu_cxx::c_locale_impl_compat): Add, alias to + c_locale_impl. + * testsuite/abi_check.cc (line_to_symbol_info): Collect size info. + * docs/html/abi.txt: Update. + +2002-10-16 Benjamin Kosnik + + * testsuite/22_locale/static_members.cc (test02): Less provincial. + +2002-10-16 Benjamin Kosnik + + * testsuite/22_locale/static_members.cc (test02): Disable for + systems without named locale support. + * testsuite/22_locale/ctor_copy_dtor.cc (test04): Don't assume + running the testsuites in "C" environment. + Add new tests. + * docs/html/22_locale/locale.html: Update. + +2002-10-16 Benjamin Kosnik + + * testsuite/abi_check.cc (hash): Specialize. + Simplify. Check compatible symbol versions. + * config/linker-map.gnu: Clarify, explicitly export + std::codecvt::c* symbols. + + * testsuite/22_locale/static_members.cc (test02): Avoid null strings. + +2002-10-16 Benjamin Kosnik + + * testsuite/22_locale/static_members.cc (test02): Fix. + +2002-10-16 Benjamin Kosnik + + * acconfig.h (_GLIBCPP_SYMVER): Add. + (_GLIBCPP_ASM_SYMVER): Add. + * acinclude.m4 (GLIBCPP_ENABLE_SYMVERS): Define _GLIBCPP_SYMVER. + * aclocal.m4: Regenerate. + * config.h.in: Regenerate. + * configure: Regenerate. + * include/bits/c++config (_GLIBCPP_AT_AT): Define, as an expedient + hack around m4 issues with quoting '@'. + * src/locale.cc: Use _GLIBCPP_ASM_SYMVER. + * src/globals.cc (__gnu_cxx): Same. + + * testsuite/22_locale/ctor_copy_dtor.cc (test04): Fix for + +2002-10-16 Benjamin Kosnik + + * config/linker-map.gnu (GLIBCPP_3.2.1): Add. + (GLIBCPP_3.2): Don't export locale::_S_*. + * src/ios.cc: Move globals into __gnu_cxx. Make old exported + symbols match. + * src/locale.cc: Same. + * src/localename.cc: Same. + +2002-10-16 Benjamin Kosnik + + * src/locale.cc: Fix comments, move ctors together. + * testsuite/22_locale/static_members.cc (test03): Add. + +2002-10-16 Paolo Carlini + Benjamin Kosnik + + * include/bits/localefwd.h (class locale): Add static member + _S_num_extra_categories, encoding the number of additional + categories. + Change _S_num_categories to _S_categories_size. + (class locale::_Impl): Add _M_c_cats. + (class locale::_Impl::_M_names): Change to array of chars. + (class locale::_Impl::_M_check_same_name): Use + _S_extra_categories_size, tweak. + (locale::locale(const locale&, _Facet*)): Ditto. + * src/locale.cc (locale::locale(const char* )): Rewrite to deal + with the environment in a POSIX-compliant way while being thread + safe. + (locale::name()): Update to output POSIX environment strings. + * src/localename.cc + (locale::_Impl::_Impl(const _Impl&, size_t): Use + _S_categories_size_*, tweak. + (locale::_Impl::_Impl(facet**, size_t, bool)): Ditto. + (locale::_Impl::_Impl(const char*, size_t)): Name each category + individually. + (locale::_Impl::_M_replace_categories): Use strcpy. + + * include/bits/locale_facets.h (numpunct::_M_initialize_numpunct): + Change default argument to NULL from _S_c_locale. + (timepunct::_M_initialize_timepunct): Same. + _S_c_locale cleanups. + * src/codecvt.c: _S_c_locale simplification. + * src/ctype.c: Same. + * src/globals.cc: Add fake_name. + * src/locale-inst.cc: Remove extra includes. + * src/locale.cc: Remove extra includes. + Add _S_extra_categories_size definition. + Correct "C" initialization. + (locale::facet::facet): Don't initialize _S_c_locale. + (locale::facet::_M_remove_reference): Adjust. + * src/localename: Use facet_vec, facet_name. + (locale::_Impl::_Impl(facet** __f, size_t __refs, bool)): Set + facet ref counts to one. Initialize _S_c_locale. + (locale::_Impl::_M_install_facet(id*, facet*)): Adjust facet ref + counts when installing unilaterally. + + * config/locale/generic/c_locale.cc: Add _S_categories definition. + * config/locale/generic/c_locale.h: Add _GLIBCPP_NUM_CATEGORIES macro. + * config/locale/generic/time_members.cc: _S_c_locale cleanup. + + * config/locale/gnu/c_locale.cc: Add _S_categories definition. + (_S_destroy_c_locale): Move checks against _S_c_locale here. + * config/locale/gnu/c_locale.h: Add _GLIBCPP_NUM_CATEGORIES macro. + * config/locale/gnu/ctype_members.cc: Simplify _S_destroy_c_locale + calls, _S_c_locale usage. + * config/locale/gnu/monetary_members.cc: Same, tweaks. + * config/locale/gnu/monetary_members.cc: Same. + * config/locale/gnu/time_members.cc: Same. + * config/os/gnu-linux/ctype_noninline.h: Use locale::classic(). + + * docs/html/22_locale/locale.html: Add bits about global locales + and "C" setlocale. + + * testsuite/22_locale/facet.cc (test02): Add. + * testsuite/22_locale/static_members.cc (test02): Add. + * testsuite/22_locale/ctor_copy_dtor.cc (test04): Add. + 2002-10-11 Gabriel Dos Reis * include/std/std_limits.h (__glibcpp_char_digits10): Fix Typo. diff --git a/libstdc++-v3/Makefile.in b/libstdc++-v3/Makefile.in index 718150791b1d..7a427226f11c 100644 --- a/libstdc++-v3/Makefile.in +++ b/libstdc++-v3/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am +# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation @@ -157,7 +157,44 @@ MULTICLEAN = true # Work around what appears to be a GNU make bug handling MAKEFLAGS # values defined in terms of make variables, as is the case for CC and # friends when we are called from the top level Makefile. -AM_MAKEFLAGS = "AR_FLAGS=$(AR_FLAGS)" "CC_FOR_BUILD=$(CC_FOR_BUILD)" "CC_FOR_TARGET=$(CC_FOR_TARGET)" "CFLAGS=$(CFLAGS)" "CXXFLAGS=$(CXXFLAGS)" "CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" "CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" "INSTALL=$(INSTALL)" "INSTALL_DATA=$(INSTALL_DATA)" "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" "INSTALL_SCRIPT=$(INSTALL_SCRIPT)" "LDFLAGS=$(LDFLAGS)" "LIBCFLAGS=$(LIBCFLAGS)" "LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" "MAKE=$(MAKE)" "MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" "PICFLAG=$(PICFLAG)" "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" "SHELL=$(SHELL)" "RUNTESTFLAGS=$(RUNTESTFLAGS)" "exec_prefix=$(exec_prefix)" "infodir=$(infodir)" "libdir=$(libdir)" "includedir=$(includedir)" "prefix=$(prefix)" "tooldir=$(tooldir)" "AR=$(AR)" "AS=$(AS)" "LD=$(LD)" "LIBCFLAGS=$(LIBCFLAGS)" "PICFLAG=$(PICFLAG)" "RANLIB=$(RANLIB)" "NM=$(NM)" "NM_FOR_BUILD=$(NM_FOR_BUILD)" "NM_FOR_TARGET=$(NM_FOR_TARGET)" "DESTDIR=$(DESTDIR)" "WERROR=$(WERROR)" +AM_MAKEFLAGS = \ + "AR_FLAGS=$(AR_FLAGS)" \ + "CC_FOR_BUILD=$(CC_FOR_BUILD)" \ + "CC_FOR_TARGET=$(CC_FOR_TARGET)" \ + "CFLAGS=$(CFLAGS)" \ + "CXXFLAGS=$(CXXFLAGS)" \ + "CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \ + "CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \ + "INSTALL=$(INSTALL)" \ + "INSTALL_DATA=$(INSTALL_DATA)" \ + "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \ + "INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \ + "LDFLAGS=$(LDFLAGS)" \ + "LIBCFLAGS=$(LIBCFLAGS)" \ + "LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \ + "MAKE=$(MAKE)" \ + "MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \ + "PICFLAG=$(PICFLAG)" \ + "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \ + "SHELL=$(SHELL)" \ + "RUNTESTFLAGS=$(RUNTESTFLAGS)" \ + "exec_prefix=$(exec_prefix)" \ + "infodir=$(infodir)" \ + "libdir=$(libdir)" \ + "includedir=$(includedir)" \ + "prefix=$(prefix)" \ + "tooldir=$(tooldir)" \ + "AR=$(AR)" \ + "AS=$(AS)" \ + "LD=$(LD)" \ + "LIBCFLAGS=$(LIBCFLAGS)" \ + "PICFLAG=$(PICFLAG)" \ + "RANLIB=$(RANLIB)" \ + "NM=$(NM)" \ + "NM_FOR_BUILD=$(NM_FOR_BUILD)" \ + "NM_FOR_TARGET=$(NM_FOR_TARGET)" \ + "DESTDIR=$(DESTDIR)" \ + "WERROR=$(WERROR)" ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 CONFIG_HEADER = config.h @@ -169,7 +206,7 @@ mkcheck.in testsuite_flags.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) -TAR = tar +TAR = gtar GZIP_ENV = --best all: all-redirect .SUFFIXES: diff --git a/libstdc++-v3/acconfig.h b/libstdc++-v3/acconfig.h index aa0dd99cfa9e..777e94a5039a 100644 --- a/libstdc++-v3/acconfig.h +++ b/libstdc++-v3/acconfig.h @@ -46,6 +46,20 @@ // Define if you have the copysignf function. #undef _GLIBCPP_HAVE_COPYSIGNF +// Define to use symbol versioning in the shared library. +#undef _GLIBCPP_SYMVER + +// Define symbol versioning in assember directives. If symbol +// versioning is beigng used, and the assembler supports this kind of +// thing, then use it. +// NB: _GLIBCPP_AT_AT is a hack to work around quoting issues in m4. +#if _GLIBCPP_SYMVER + #define _GLIBCPP_ASM_SYMVER(cur, old, version) \ + asm (".symver " #cur "," #old _GLIBCPP_AT_AT #version); +#else + #define _GLIBCPP_ASM_SYMVER(cur, old, version) +#endif + // Define if mbstate_t exists in wchar.h. #undef HAVE_MBSTATE_T diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index a7ab248aa1cc..a8bfebdc4721 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -2201,6 +2201,7 @@ case $enable_symvers in ;; gnu) LINKER_MAP=config/linker-map.gnu + AC_DEFINE(_GLIBCPP_SYMVER) ;; esac diff --git a/libstdc++-v3/aclocal.m4 b/libstdc++-v3/aclocal.m4 index abb3ba9f9f29..2dd5fe2dbff2 100644 --- a/libstdc++-v3/aclocal.m4 +++ b/libstdc++-v3/aclocal.m4 @@ -2213,6 +2213,7 @@ case $enable_symvers in ;; gnu) LINKER_MAP=config/linker-map.gnu + AC_DEFINE(_GLIBCPP_SYMVER) ;; esac diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in index fcc2c3e2ebf5..de9f397390af 100644 --- a/libstdc++-v3/config.h.in +++ b/libstdc++-v3/config.h.in @@ -24,6 +24,20 @@ // Define to use concept checking code from the boost libraries. #undef _GLIBCPP_CONCEPT_CHECKS +// Define to use symbol versioning in the shared library. +#undef _GLIBCPP_SYMVER + +// Define symbol versioning in assember directives. If symbol +// versioning is beigng used, and the assembler supports this kind of +// thing, then use it. +// NB: _GLIBCPP_AT_AT is a hack to work around quoting issues in m4. +#if _GLIBCPP_SYMVER + #define _GLIBCPP_ASM_SYMVER(cur, old, version) \ + asm (".symver " #cur "," #old _GLIBCPP_AT_AT #version); +#else + #define _GLIBCPP_ASM_SYMVER(cur, old, version) +#endif + // Define if mbstate_t exists in wchar.h. #undef HAVE_MBSTATE_T diff --git a/libstdc++-v3/config/linker-map.gnu b/libstdc++-v3/config/linker-map.gnu index d4346b1c660e..588ad57fdd86 100644 --- a/libstdc++-v3/config/linker-map.gnu +++ b/libstdc++-v3/config/linker-map.gnu @@ -20,7 +20,6 @@ ## Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, ## USA. - GLIBCPP_3.2 { global: @@ -29,7 +28,17 @@ GLIBCPP_3.2 { # All but the last are terminated with a semicolon. extern "C++" { - std::[A-Za-z]*; + std::[A-Za-k]*; + std::length_error*; + std::logic_error*; + std::locale::[A-Za-z]*; + std::locale::_[A-Ra-z]*; + std::locale::_S_classic; + std::locale::_S_global; + std::locale::_S_num_categories; + std::locale::_S_normalize_category*; + std::locale::_[T-Za-z]*; + std::[A-Zm-z]*; std::__throw_*; std::__basic_file*; std::__num_base*; @@ -42,6 +51,11 @@ GLIBCPP_3.2 { }; # Names not in an 'extern' block are mangled names. + + # std::locale destructors + _ZNSt6localeD*; + + # std::has_facet* _ZSt9has_facet*; # operator new(unsigned) @@ -72,8 +86,8 @@ GLIBCPP_3.2 { # operator delete[](void*, std::nothrow_t const&) _ZdaPvRKSt9nothrow_t; - # vtable - _ZTV*; + # vtable + _ZTV*; _ZTT*; # typeinfo @@ -95,7 +109,6 @@ GLIBCPP_3.2 { *; }; - # Symbols in the support library (libsupc++) have their own tag. CXXABI_1.2 { diff --git a/libstdc++-v3/config/locale/generic/c_locale.cc b/libstdc++-v3/config/locale/generic/c_locale.cc index e274836fd901..689bbf592b93 100644 --- a/libstdc++-v3/config/locale/generic/c_locale.cc +++ b/libstdc++-v3/config/locale/generic/c_locale.cc @@ -223,4 +223,15 @@ namespace std __c_locale locale::facet::_S_clone_c_locale(__c_locale&) { return __c_locale(); } + + const char* locale::_S_categories[_S_categories_size + + _S_extra_categories_size] = + { + "LC_CTYPE", + "LC_NUMERIC", + "LC_COLLATE", + "LC_TIME", + "LC_MONETARY", + "LC_MESSAGES" + }; } // namespace std diff --git a/libstdc++-v3/config/locale/generic/c_locale.h b/libstdc++-v3/config/locale/generic/c_locale.h index bfd9bf0a0bf1..9627d8646afe 100644 --- a/libstdc++-v3/config/locale/generic/c_locale.h +++ b/libstdc++-v3/config/locale/generic/c_locale.h @@ -35,6 +35,8 @@ #include +#define _GLIBCPP_NUM_CATEGORIES 0 + namespace std { typedef int* __c_locale; diff --git a/libstdc++-v3/config/locale/generic/time_members.cc b/libstdc++-v3/config/locale/generic/time_members.cc index d02f0c3fa0ea..fd45645a690c 100644 --- a/libstdc++-v3/config/locale/generic/time_members.cc +++ b/libstdc++-v3/config/locale/generic/time_members.cc @@ -38,13 +38,6 @@ namespace std { - template<> - __timepunct::~__timepunct() - { - if (_M_c_locale_timepunct != _S_c_locale) - _S_destroy_c_locale(_M_c_locale_timepunct); - } - template<> void __timepunct:: @@ -121,13 +114,6 @@ namespace std } #ifdef _GLIBCPP_USE_WCHAR_T - template<> - __timepunct::~__timepunct() - { - if (_M_c_locale_timepunct != _S_c_locale) - _S_destroy_c_locale(_M_c_locale_timepunct); - } - template<> void __timepunct:: diff --git a/libstdc++-v3/config/locale/gnu/c_locale.cc b/libstdc++-v3/config/locale/gnu/c_locale.cc index 3982a65ceb6b..188f3a2f1c1b 100644 --- a/libstdc++-v3/config/locale/gnu/c_locale.cc +++ b/libstdc++-v3/config/locale/gnu/c_locale.cc @@ -178,9 +178,29 @@ namespace std void locale::facet::_S_destroy_c_locale(__c_locale& __cloc) - { __freelocale(__cloc); } + { + if (_S_c_locale != __cloc) + __freelocale(__cloc); + } __c_locale locale::facet::_S_clone_c_locale(__c_locale& __cloc) { return __duplocale(__cloc); } + + const char* locale::_S_categories[_S_categories_size + + _S_extra_categories_size] = + { + "LC_CTYPE", + "LC_NUMERIC", + "LC_COLLATE", + "LC_TIME", + "LC_MONETARY", + "LC_MESSAGES", + "LC_PAPER", + "LC_NAME", + "LC_ADDRESS", + "LC_TELEPHONE", + "LC_MEASUREMENT", + "LC_IDENTIFICATION" + }; } // namespace std diff --git a/libstdc++-v3/config/locale/gnu/c_locale.h b/libstdc++-v3/config/locale/gnu/c_locale.h index aabbe6af4256..130b843d7f9e 100644 --- a/libstdc++-v3/config/locale/gnu/c_locale.h +++ b/libstdc++-v3/config/locale/gnu/c_locale.h @@ -40,6 +40,8 @@ #define _GLIBCPP_C_LOCALE_GNU 1 +#define _GLIBCPP_NUM_CATEGORIES 6 + #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) namespace __gnu_cxx { diff --git a/libstdc++-v3/config/locale/gnu/ctype_members.cc b/libstdc++-v3/config/locale/gnu/ctype_members.cc index db1e356d0381..3b78c60405a1 100644 --- a/libstdc++-v3/config/locale/gnu/ctype_members.cc +++ b/libstdc++-v3/config/locale/gnu/ctype_members.cc @@ -44,8 +44,7 @@ namespace std ctype_byname::ctype_byname(const char* __s, size_t __refs) : ctype(0, false, __refs) { - if (_M_c_locale_ctype != _S_c_locale) - _S_destroy_c_locale(_M_c_locale_ctype); + _S_destroy_c_locale(_M_c_locale_ctype); _S_create_c_locale(_M_c_locale_ctype, __s); _M_toupper = _M_c_locale_ctype->__ctype_toupper; _M_tolower = _M_c_locale_ctype->__ctype_tolower; diff --git a/libstdc++-v3/config/locale/gnu/monetary_members.cc b/libstdc++-v3/config/locale/gnu/monetary_members.cc index 68b154bdc7ce..0386ab6dc546 100644 --- a/libstdc++-v3/config/locale/gnu/monetary_members.cc +++ b/libstdc++-v3/config/locale/gnu/monetary_members.cc @@ -220,7 +220,7 @@ namespace std moneypunct::_M_initialize_moneypunct(__c_locale __cloc, const char*) { - if (__cloc == _S_c_locale) + if (!__cloc) { // "C" locale _M_decimal_point = '.'; @@ -265,7 +265,7 @@ namespace std moneypunct::_M_initialize_moneypunct(__c_locale __cloc, const char*) { - if (__cloc == _S_c_locale) + if (!__cloc) { // "C" locale _M_decimal_point = '.'; @@ -319,7 +319,7 @@ namespace std moneypunct::_M_initialize_moneypunct(__c_locale __cloc, const char* __name) { - if (__cloc == _S_c_locale) + if (!__cloc) { // "C" locale _M_decimal_point = L'.'; @@ -348,14 +348,12 @@ namespace std _M_thousands_sep = static_cast(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc)}).__w); _M_grouping = __nl_langinfo_l(GROUPING, __cloc); - mbstate_t __state; - size_t __len; const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); - // NB: Should swich to __cloc's ctype info first. - __len = strlen(__cpossign); + mbstate_t __state; + size_t __len = strlen(__cpossign); if (__len) { ++__len; @@ -418,7 +416,7 @@ namespace std moneypunct::_M_initialize_moneypunct(__c_locale __cloc, const char* __name) { - if (__cloc == _S_c_locale) + if (!__cloc) { // "C" locale _M_decimal_point = L'.'; @@ -446,13 +444,12 @@ namespace std _M_thousands_sep = static_cast(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc)}).__w); _M_grouping = __nl_langinfo_l(GROUPING, __cloc); - mbstate_t __state; - size_t __len; const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); - // NB: Should swich to __cloc's ctype info first. + mbstate_t __state; + size_t __len; __len = strlen(__cpossign); if (__len) { diff --git a/libstdc++-v3/config/locale/gnu/numeric_members.cc b/libstdc++-v3/config/locale/gnu/numeric_members.cc index b71374c4b8e5..a502bfb2150f 100644 --- a/libstdc++-v3/config/locale/gnu/numeric_members.cc +++ b/libstdc++-v3/config/locale/gnu/numeric_members.cc @@ -42,7 +42,7 @@ namespace std void numpunct::_M_initialize_numpunct(__c_locale __cloc) { - if (__cloc == _S_c_locale) + if (!__cloc) { // "C" locale _M_decimal_point = '.'; @@ -76,7 +76,7 @@ namespace std void numpunct::_M_initialize_numpunct(__c_locale __cloc) { - if (__cloc == _S_c_locale) + if (!__cloc) { // "C" locale _M_decimal_point = L'.'; diff --git a/libstdc++-v3/config/locale/gnu/time_members.cc b/libstdc++-v3/config/locale/gnu/time_members.cc index ce3d9bf01066..7df10b8ab716 100644 --- a/libstdc++-v3/config/locale/gnu/time_members.cc +++ b/libstdc++-v3/config/locale/gnu/time_members.cc @@ -39,13 +39,6 @@ namespace std { - template<> - __timepunct::~__timepunct() - { - if (_M_c_locale_timepunct != _S_c_locale) - _S_destroy_c_locale(_M_c_locale_timepunct); - } - template<> void __timepunct:: @@ -67,11 +60,10 @@ namespace std void __timepunct::_M_initialize_timepunct(__c_locale __cloc) { - if (__cloc == _S_c_locale) + if (!__cloc) { // "C" locale - - _M_c_locale_timepunct = _S_c_locale; + _M_c_locale_timepunct = _S_c_locale; _M_date_format = "%m/%d/%y"; _M_date_era_format = "%m/%d/%y"; @@ -192,13 +184,6 @@ namespace std } #ifdef _GLIBCPP_USE_WCHAR_T - template<> - __timepunct::~__timepunct() - { - if (_M_c_locale_timepunct != _S_c_locale) - _S_destroy_c_locale(_M_c_locale_timepunct); - } - template<> void __timepunct:: @@ -220,11 +205,10 @@ namespace std void __timepunct::_M_initialize_timepunct(__c_locale __cloc) { - if (__cloc == _S_c_locale) + if (!__cloc) { // "C" locale - - _M_c_locale_timepunct = _S_c_locale; + _M_c_locale_timepunct = _S_c_locale; _M_date_format = L"%m/%d/%y"; _M_date_era_format = L"%m/%d/%y"; diff --git a/libstdc++-v3/config/os/gnu-linux/bits/ctype_noninline.h b/libstdc++-v3/config/os/gnu-linux/bits/ctype_noninline.h index 1578828ccedd..8f06d1397ee0 100644 --- a/libstdc++-v3/config/os/gnu-linux/bits/ctype_noninline.h +++ b/libstdc++-v3/config/os/gnu-linux/bits/ctype_noninline.h @@ -38,8 +38,7 @@ const ctype_base::mask* ctype::classic_table() throw() { - if (!_S_c_locale) - _S_create_c_locale(_S_c_locale, "C"); + locale::classic(); return _S_c_locale->__ctype_b; } #else @@ -96,7 +95,7 @@ ctype::ctype(const mask* __table, bool __del, size_t __refs) : __ctype_abstract_base(__refs), _M_del(__table != 0 && __del) { - _M_c_locale_ctype = _S_c_locale; + _M_c_locale_ctype = _S_c_locale; _M_toupper = _M_c_locale_ctype->__ctype_toupper; _M_tolower = _M_c_locale_ctype->__ctype_tolower; _M_table = __table ? __table : _M_c_locale_ctype->__ctype_b; diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index 50d041e687a7..51f3808247bb 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -22032,6 +22032,10 @@ case $enable_symvers in ;; gnu) LINKER_MAP=config/linker-map.gnu + cat >> confdefs.h <<\EOF +#define _GLIBCPP_SYMVER 1 +EOF + ;; esac @@ -22046,7 +22050,7 @@ else GLIBCPP_BUILD_VERSIONED_SHLIB_FALSE= fi echo $ac_n "checking versioning on shared library symbols""... $ac_c" 1>&6 -echo "configure:22050: checking versioning on shared library symbols" >&5 +echo "configure:22054: checking versioning on shared library symbols" >&5 echo "$ac_t""$enable_symvers" 1>&6 @@ -22134,7 +22138,7 @@ glibcpp_prefixdir=${prefix} # Process the option --with-gxx-include-dir= echo $ac_n "checking for --with-gxx-include-dir""... $ac_c" 1>&6 -echo "configure:22138: checking for --with-gxx-include-dir" >&5 +echo "configure:22142: checking for --with-gxx-include-dir" >&5 # Check whether --with-gxx-include-dir or --without-gxx-include-dir was given. if test "${with_gxx_include_dir+set}" = set; then withval="$with_gxx_include_dir" @@ -22158,7 +22162,7 @@ echo "$ac_t""$gxx_include_dir" 1>&6 # Process the option "--enable-version-specific-runtime-libs" echo $ac_n "checking for --enable-version-specific-runtime-libs""... $ac_c" 1>&6 -echo "configure:22162: checking for --enable-version-specific-runtime-libs" >&5 +echo "configure:22166: checking for --enable-version-specific-runtime-libs" >&5 # Check whether --enable-version-specific-runtime-libs or --disable-version-specific-runtime-libs was given. if test "${enable_version_specific_runtime_libs+set}" = set; then enableval="$enable_version_specific_runtime_libs" @@ -22204,7 +22208,7 @@ if test x"$glibcpp_toolexecdir" = x"no"; then fi echo $ac_n "checking for install location""... $ac_c" 1>&6 -echo "configure:22208: checking for install location" >&5 +echo "configure:22212: checking for install location" >&5 echo "$ac_t""$gxx_include_dir" 1>&6 diff --git a/libstdc++-v3/docs/html/22_locale/locale.html b/libstdc++-v3/docs/html/22_locale/locale.html index 999e82ed0bd7..6816204df8f3 100644 --- a/libstdc++-v3/docs/html/22_locale/locale.html +++ b/libstdc++-v3/docs/html/22_locale/locale.html @@ -1,8 +1,12 @@ - + + + - + Notes on the locale implementation. @@ -12,79 +16,459 @@ Notes on the locale implementation. -prepared by Benjamin Kosnik (bkoz@redhat.com) on August 8, 2001 +prepared by Benjamin Kosnik (bkoz@redhat.com) on October 14, 2002

-1. Abstract Describes the basic locale object, including nested -classes id, facet, and the reference-counted implementation object, -class _Impl. +1. Abstract

+Describes the basic locale object, including nested +classes id, facet, and the reference-counted implementation object, +class _Impl.

2. What the standard says

-See Chapter 22 of the standard. +Class locale is non-templatized and has two distinct types nested +inside of it: + +
+ +class facet +22.1.1.1.2 Class locale::facet + +
+ +

+Facets actually implement locale functionality. For instance, a facet +called numpunct is the data objects that can be used to query for the +thousands separator is in the German locale. +

+ +Literally, a facet is strictly defined: +
    +
  • containing the following public data member: +

    + static locale::id id; +

    +
  • + +
  • derived from another facet: +

    + class gnu_codecvt: public std::ctype<user-defined-type> +

    +
  • +
+ +

+Of interest in this class are the memory management options explicitly +specified as an argument to facet's constructor. Each constructor of a +facet class takes a std::size_t __refs argument: if __refs == 0, the +facet is deleted when the locale containing it is destroyed. If __refs +== 1, the facet is not destroyed, even when it is no longer +referenced. +

+ +
+ +class id +22.1.1.1.3 - Class locale::id + +
+ +

+Provides an index for looking up specific facets. +

-3. Problems with "C" locales : global locales, termination. +3. Interacting with "C" locales.

-The major problem is fitting an object-orientated and non-global locale -design ontop of POSIX and other relevant stanards, which include the -Single Unix (nee X/Open.) +Some help on determining the underlying support for locales on a system. +Note, this is specific to linux (and glibc-2.3.x) +

-Because POSIX falls down so completely, portibility is an issue. +
    +
  • `locale -a` displays available locales. +
    +
    +af_ZA
    +ar_AE
    +ar_AE.utf8
    +ar_BH
    +ar_BH.utf8
    +ar_DZ
    +ar_DZ.utf8
    +ar_EG
    +ar_EG.utf8
    +ar_IN
    +ar_IQ
    +ar_IQ.utf8
    +ar_JO
    +ar_JO.utf8
    +ar_KW
    +ar_KW.utf8
    +ar_LB
    +ar_LB.utf8
    +ar_LY
    +ar_LY.utf8
    +ar_MA
    +ar_MA.utf8
    +ar_OM
    +ar_OM.utf8
    +ar_QA
    +ar_QA.utf8
    +ar_SA
    +ar_SA.utf8
    +ar_SD
    +ar_SD.utf8
    +ar_SY
    +ar_SY.utf8
    +ar_TN
    +ar_TN.utf8
    +ar_YE
    +ar_YE.utf8
    +be_BY
    +be_BY.utf8
    +bg_BG
    +bg_BG.utf8
    +br_FR
    +bs_BA
    +C
    +ca_ES
    +ca_ES@euro
    +ca_ES.utf8
    +ca_ES.utf8@euro
    +cs_CZ
    +cs_CZ.utf8
    +cy_GB
    +da_DK
    +da_DK.iso885915
    +da_DK.utf8
    +de_AT
    +de_AT@euro
    +de_AT.utf8
    +de_AT.utf8@euro
    +de_BE
    +de_BE@euro
    +de_BE.utf8
    +de_BE.utf8@euro
    +de_CH
    +de_CH.utf8
    +de_DE
    +de_DE@euro
    +de_DE.utf8
    +de_DE.utf8@euro
    +de_LU
    +de_LU@euro
    +de_LU.utf8
    +de_LU.utf8@euro
    +el_GR
    +el_GR.utf8
    +en_AU
    +en_AU.utf8
    +en_BW
    +en_BW.utf8
    +en_CA
    +en_CA.utf8
    +en_DK
    +en_DK.utf8
    +en_GB
    +en_GB.iso885915
    +en_GB.utf8
    +en_HK
    +en_HK.utf8
    +en_IE
    +en_IE@euro
    +en_IE.utf8
    +en_IE.utf8@euro
    +en_IN
    +en_NZ
    +en_NZ.utf8
    +en_PH
    +en_PH.utf8
    +en_SG
    +en_SG.utf8
    +en_US
    +en_US.iso885915
    +en_US.utf8
    +en_ZA
    +en_ZA.utf8
    +en_ZW
    +en_ZW.utf8
    +es_AR
    +es_AR.utf8
    +es_BO
    +es_BO.utf8
    +es_CL
    +es_CL.utf8
    +es_CO
    +es_CO.utf8
    +es_CR
    +es_CR.utf8
    +es_DO
    +es_DO.utf8
    +es_EC
    +es_EC.utf8
    +es_ES
    +es_ES@euro
    +es_ES.utf8
    +es_ES.utf8@euro
    +es_GT
    +es_GT.utf8
    +es_HN
    +es_HN.utf8
    +es_MX
    +es_MX.utf8
    +es_NI
    +es_NI.utf8
    +es_PA
    +es_PA.utf8
    +es_PE
    +es_PE.utf8
    +es_PR
    +es_PR.utf8
    +es_PY
    +es_PY.utf8
    +es_SV
    +es_SV.utf8
    +es_US
    +es_US.utf8
    +es_UY
    +es_UY.utf8
    +es_VE
    +es_VE.utf8
    +et_EE
    +et_EE.utf8
    +eu_ES
    +eu_ES@euro
    +eu_ES.utf8
    +eu_ES.utf8@euro
    +fa_IR
    +fi_FI
    +fi_FI@euro
    +fi_FI.utf8
    +fi_FI.utf8@euro
    +fo_FO
    +fo_FO.utf8
    +fr_BE
    +fr_BE@euro
    +fr_BE.utf8
    +fr_BE.utf8@euro
    +fr_CA
    +fr_CA.utf8
    +fr_CH
    +fr_CH.utf8
    +fr_FR
    +fr_FR@euro
    +fr_FR.utf8
    +fr_FR.utf8@euro
    +fr_LU
    +fr_LU@euro
    +fr_LU.utf8
    +fr_LU.utf8@euro
    +ga_IE
    +ga_IE@euro
    +ga_IE.utf8
    +ga_IE.utf8@euro
    +gl_ES
    +gl_ES@euro
    +gl_ES.utf8
    +gl_ES.utf8@euro
    +gv_GB
    +gv_GB.utf8
    +he_IL
    +he_IL.utf8
    +hi_IN
    +hr_HR
    +hr_HR.utf8
    +hu_HU
    +hu_HU.utf8
    +id_ID
    +id_ID.utf8
    +is_IS
    +is_IS.utf8
    +it_CH
    +it_CH.utf8
    +it_IT
    +it_IT@euro
    +it_IT.utf8
    +it_IT.utf8@euro
    +iw_IL
    +iw_IL.utf8
    +ja_JP.eucjp
    +ja_JP.utf8
    +ka_GE
    +kl_GL
    +kl_GL.utf8
    +ko_KR.euckr
    +ko_KR.utf8
    +kw_GB
    +kw_GB.utf8
    +lt_LT
    +lt_LT.utf8
    +lv_LV
    +lv_LV.utf8
    +mi_NZ
    +mk_MK
    +mk_MK.utf8
    +mr_IN
    +ms_MY
    +ms_MY.utf8
    +mt_MT
    +mt_MT.utf8
    +nl_BE
    +nl_BE@euro
    +nl_BE.utf8
    +nl_BE.utf8@euro
    +nl_NL
    +nl_NL@euro
    +nl_NL.utf8
    +nl_NL.utf8@euro
    +nn_NO
    +nn_NO.utf8
    +no_NO
    +no_NO.utf8
    +oc_FR
    +pl_PL
    +pl_PL.utf8
    +POSIX
    +pt_BR
    +pt_BR.utf8
    +pt_PT
    +pt_PT@euro
    +pt_PT.utf8
    +pt_PT.utf8@euro
    +ro_RO
    +ro_RO.utf8
    +ru_RU
    +ru_RU.koi8r
    +ru_RU.utf8
    +ru_UA
    +ru_UA.utf8
    +se_NO
    +sk_SK
    +sk_SK.utf8
    +sl_SI
    +sl_SI.utf8
    +sq_AL
    +sq_AL.utf8
    +sr_YU
    +sr_YU@cyrillic
    +sr_YU.utf8
    +sr_YU.utf8@cyrillic
    +sv_FI
    +sv_FI@euro
    +sv_FI.utf8
    +sv_FI.utf8@euro
    +sv_SE
    +sv_SE.iso885915
    +sv_SE.utf8
    +ta_IN
    +te_IN
    +tg_TJ
    +th_TH
    +th_TH.utf8
    +tl_PH
    +tr_TR
    +tr_TR.utf8
    +uk_UA
    +uk_UA.utf8
    +ur_PK
    +uz_UZ
    +vi_VN
    +vi_VN.tcvn
    +wa_BE
    +wa_BE@euro
    +yi_US
    +zh_CN
    +zh_CN.gb18030
    +zh_CN.gbk
    +zh_CN.utf8
    +zh_HK
    +zh_HK.utf8
    +zh_TW
    +zh_TW.euctw
    +zh_TW.utf8
    +
    +
    +
  • + +
  • `locale` displays environmental variables + that impact how locale("") will be deduced. + +
    +
    +LANG=en_US
    +LC_CTYPE="en_US"
    +LC_NUMERIC="en_US"
    +LC_TIME="en_US"
    +LC_COLLATE="en_US"
    +LC_MONETARY="en_US"
    +LC_MESSAGES="en_US"
    +LC_PAPER="en_US"
    +LC_NAME="en_US"
    +LC_ADDRESS="en_US"
    +LC_TELEPHONE="en_US"
    +LC_MEASUREMENT="en_US"
    +LC_IDENTIFICATION="en_US"
    +LC_ALL=
    +
    +
    +
  • +
+ +

+From Josuttis, p. 697-698, which says, that "there is only *one* +relation (of the C++ locale mechanism) to the C locale mechanism: the +global C locale is modified if a named C++ locale object is set as the +global locale" (emphasis Paolo), that is:

+ std::locale::global(std::locale("")); -

-4. Design -

-Class locale in non-templatized and has three distinct types nested -inside of it: +

affects the C functions as if the following call was made:

-class facet -22.1.1.1.2 Class locale::facet + std::setlocale(LC_ALL, ""); -Facets actually implement locale functionality. For instance, a facet -called numpunct is the data objects that can be used to query for the -thousands separator is in the German locale. +

+On the other hand, there is *no* viceversa, that is, calling setlocale +has *no* whatsoever on the C++ locale mechanism, in particular on the +working of locale(""), which constructs the locale object from the +environment of the running program, that is, in practice, the set of +LC_ALL, LANG, etc. variable of the shell. +

-Literally, a facet is strictly defined: - - containing -public: - static locale::id id; -- or derived from another facet +

+4. Design +

-The only other thing of interest in this class is the memory -management of facets. Each constructor of a facet class takes a -std::size_t __refs argument: if __refs == 0, the facet is deleted when -no longer used. if __refs == 1, the facet is not destroyed, even when -it is no longer reference. +

+The major design challenge is fitting an object-orientated and +non-global locale design ontop of POSIX and other relevant stanards, +which include the Single Unix (nee X/Open.) +

-class id -Provides an index for looking up specific facets. +

+Because POSIX falls down so completely, portibility is an issue. +

class _Impl +The internal representation of the std::locale object. +

5. Examples

-
-  typedef __locale_t locale;
-
- More information can be found in the following testcases:
    -
  • testsuite/22_locale/ctype_char_members.cc
  • -
  • testsuite/22_locale/ctype_wchar_t_members.cc
  • +
  • testsuite/22_locale/all

@@ -92,8 +476,6 @@ More information can be found in the following testcases:

    -
  • locale -a displays available locales on linux
  • -
  • locale initialization: at what point does _S_classic, _S_global get initialized? Can named locales assume this initialization has already taken place?
  • diff --git a/libstdc++-v3/docs/html/abi.txt b/libstdc++-v3/docs/html/abi.txt index 770c3cf59740..73cb46c9c099 100644 --- a/libstdc++-v3/docs/html/abi.txt +++ b/libstdc++-v3/docs/html/abi.txt @@ -1,12 +1,5 @@ -=========================== - -See http://gcc.gnu.org/ml/libstdc++/2002-07/msg00054.html for why this -document exists, why it's incomplete, and what needs to be done still. - -=========================== - -2002-09-06 Benjamin Kosnik +2002-10-14 Benjamin Kosnik Description of the libstdc++ ABI. @@ -244,7 +237,7 @@ II. Library ABI changes The following will cause the library major version number to increase, say from "libstdc++.so.3.0.4" to "libstdc++.so.4.0.0". -- any g++ compiler ABI changes +- (anything) changing in the gcc/g++ compiler ABI - (anything) changing size of an exported symbol @@ -256,7 +249,14 @@ increase, say from "libstdc++.so.3.0.4" to "libstdc++.so.4.0.0". - (anything) deleting an exported symbol -Note: adding an exported symbol, if it's in a new linker map name, is ok. +- (anything) changing the size, alignment, or layout of types + specified in the C++ standard. These may not necessarily be + instantiated or otherwise exported in the library binary, and + include all the required locale facets, as well as things like + std::basic_streambuf, et al. + +Note: adding an exported symbol, if it's in a new and dependent +interface name, is ok. The following will cause the library revision version number to increase, say from "libstdc++.so.5.0.0" to "libstdc++.so.5.0.1". @@ -331,17 +331,20 @@ addition, all exported names are demangled, and the exported objects are checked to make sure they are the same size as the same object in the baseline. -In the future, more tests should be added. In particular, vtable -information, offsets of data members in class objects, and other -layout information should be checked. +This dataset is insufficient, yet a start. Also needed is a +comprehensive check for all user-visible types part of the standard +library for sizeof() and alignof() changes. -It should be possible to use sizeof, alignof, and offset to compute +Verifying compatible layouts of objects is not even attempted. It +should be possible to use sizeof, alignof, and offsetof to compute offsets for each structure and type in the standard library, saving to -another datafile. Then, compute this for new binaries, and look for -differences. +another datafile. Then, compute this in a similar way for new +binaries, and look for differences. Another approach might be to use the -fdump-class-hierarchy flag to -get information. +get information. However, currently this approach gives insufficient +data for use in library testing, as class data members, their offsets, +and other detailed data is not displayed with this flag. (See g++/7470 on how this was used to find bugs.) Perhaps there are other C++ ABI checkers. If so, please notify diff --git a/libstdc++-v3/docs/html/install.html b/libstdc++-v3/docs/html/install.html index 20e2a0a366bd..f91e6c7f2d71 100644 --- a/libstdc++-v3/docs/html/install.html +++ b/libstdc++-v3/docs/html/install.html @@ -104,8 +104,8 @@

    If the 'gnu' locale model is being used, the following locales are used and tested in the libstdc++ testsuites: en_HK, en_US, - fr_FR, fr_FR@euro, de_DE, de_DE@euro, ja_JP.eucjp, and - it_IT. Failure to have the underlying "C" library locale + fr_FR, fr_FR@euro, de_DE, de_DE@euro, ja_JP.eucjp, es_MX, en_PH, + and it_IT. Failure to have the underlying "C" library locale information installed will mean that C++ named locales for the above regions will not work: because of this, the libstdc++ testsuite will not pass the named locale tests. If this isn't an diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index 840f1ee76f53..611038f64170 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -55,6 +55,9 @@ // Use corrected code from the committee library group's issues list. #define _GLIBCPP_RESOLVE_LIB_DEFECTS 1 +// Hopefully temporary workaround to autoconf/m4 issue with quoting '@'. +#define _GLIBCPP_AT_AT "@@" + // In those parts of the standard C++ library that use a mutex instead // of a spin-lock, we now unconditionally use GCC's gthr.h mutex // abstraction layer. All support to directly map to various diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h index f99562fac49e..660bad3c11a9 100644 --- a/libstdc++-v3/include/bits/locale_facets.h +++ b/libstdc++-v3/include/bits/locale_facets.h @@ -525,7 +525,7 @@ namespace std // For use at construction time only. void - _M_initialize_numpunct(__c_locale __cloc = _S_c_locale); + _M_initialize_numpunct(__c_locale __cloc = NULL); }; template @@ -875,10 +875,7 @@ namespace std protected: virtual ~collate() - { - if (_M_c_locale_collate != _S_c_locale) - _S_destroy_c_locale(_M_c_locale_collate); - } + { _S_destroy_c_locale(_M_c_locale_collate); } virtual int do_compare(const _CharT* __lo1, const _CharT* __hi1, @@ -924,8 +921,7 @@ namespace std collate_byname(const char* __s, size_t __refs = 0) : collate<_CharT>(__refs) { - if (_M_c_locale_collate != _S_c_locale) - _S_destroy_c_locale(_M_c_locale_collate); + _S_destroy_c_locale(_M_c_locale_collate); _S_create_c_locale(_M_c_locale_collate, __s); } @@ -956,7 +952,7 @@ namespace std protected: __c_locale _M_c_locale_timepunct; - const char* _M_name_timepunct; + char* _M_name_timepunct; const _CharT* _M_date_format; const _CharT* _M_date_era_format; const _CharT* _M_time_format; @@ -1016,13 +1012,21 @@ namespace std public: explicit __timepunct(size_t __refs = 0) - : locale::facet(__refs), _M_name_timepunct("C") - { _M_initialize_timepunct(); } + : locale::facet(__refs) + { + _M_name_timepunct = new char[2]; + strcpy(_M_name_timepunct, "C"); + _M_initialize_timepunct(); + } explicit __timepunct(__c_locale __cloc, const char* __s, size_t __refs = 0) - : locale::facet(__refs), _M_name_timepunct(__s) - { _M_initialize_timepunct(__cloc); } + : locale::facet(__refs) + { + _M_name_timepunct = new char[strlen(__s) + 1]; + strcpy(_M_name_timepunct, __s); + _M_initialize_timepunct(__cloc); + } void _M_put(_CharT* __s, size_t __maxlen, const _CharT* __format, @@ -1119,20 +1123,21 @@ namespace std protected: virtual - ~__timepunct(); + ~__timepunct() + { + delete [] _M_name_timepunct; + _S_destroy_c_locale(_M_c_locale_timepunct); + } // For use at construction time only. void - _M_initialize_timepunct(__c_locale __cloc = _S_c_locale); + _M_initialize_timepunct(__c_locale __cloc = NULL); }; template locale::id __timepunct<_CharT>::id; // Specializations. - template<> - __timepunct::~__timepunct(); - template<> const char* __timepunct::_S_timezones[14]; @@ -1146,9 +1151,6 @@ namespace std __timepunct::_M_put(char*, size_t, const char*, const tm*) const; #ifdef _GLIBCPP_USE_WCHAR_T - template<> - __timepunct::~__timepunct(); - template<> const wchar_t* __timepunct::_S_timezones[14]; @@ -1459,7 +1461,7 @@ namespace std // For use at construction time only. void - _M_initialize_moneypunct(__c_locale __cloc = _S_c_locale, + _M_initialize_moneypunct(__c_locale __cloc = NULL, const char* __name = NULL); }; @@ -1628,7 +1630,7 @@ namespace std __c_locale _M_c_locale_messages; #if 1 // Only needed if glibc < 2.3 - const char* _M_name_messages; + char* _M_name_messages; #endif public: @@ -1636,15 +1638,20 @@ namespace std explicit messages(size_t __refs = 0) - : locale::facet(__refs), _M_name_messages("C") - { _M_c_locale_messages = _S_c_locale; } + : locale::facet(__refs) + { + _M_name_messages = new char[2]; + strcpy(_M_name_messages, "C"); + _M_c_locale_messages = _S_c_locale; + } // Non-standard. explicit - messages(__c_locale __cloc, const char* __name, size_t __refs = 0) + messages(__c_locale __cloc, const char* __s, size_t __refs = 0) : locale::facet(__refs) { - _M_name_messages = __name; + _M_name_messages = new char[strlen(__s) + 1]; + strcpy(_M_name_messages, __s); _M_c_locale_messages = _S_clone_c_locale(__cloc); } @@ -1668,8 +1675,8 @@ namespace std virtual ~messages() { - if (_M_c_locale_messages != _S_c_locale) - _S_destroy_c_locale(_M_c_locale_messages); + delete [] _M_name_messages; + _S_destroy_c_locale(_M_c_locale_messages); } virtual catalog @@ -1758,9 +1765,10 @@ namespace std messages_byname(const char* __s, size_t __refs = 0) : messages<_CharT>(__refs) { - _M_name_messages = __s; - if (_M_c_locale_messages != _S_c_locale) - _S_destroy_c_locale(_M_c_locale_messages); + delete [] _M_name_messages; + _M_name_messages = new char[strlen(__s) + 1]; + strcpy(_M_name_messages, __s); + _S_destroy_c_locale(_M_c_locale_messages); _S_create_c_locale(_M_c_locale_messages, __s); } diff --git a/libstdc++-v3/include/bits/localefwd.h b/libstdc++-v3/include/bits/localefwd.h index 028c4126b85e..d8d742b4c592 100644 --- a/libstdc++-v3/include/bits/localefwd.h +++ b/libstdc++-v3/include/bits/localefwd.h @@ -207,8 +207,8 @@ namespace std static const category time = 1L << 3; static const category monetary = 1L << 4; static const category messages = 1L << 5; - static const category all = (collate | ctype | monetary | - numeric | time | messages); + static const category all = (ctype | numeric | collate | + time | monetary | messages); // Construct/copy/destroy: locale() throw(); @@ -267,7 +267,26 @@ namespace std // Current global reference locale static _Impl* _S_global; - static const size_t _S_num_categories = 6; + // 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, + // LC_MONETARY, LC_NUMERIC, and LC_TIME. In addition, POSIX (IEEE + // 1003.1-2001) specifies LC_MESSAGES. + static const size_t _S_categories_size = 6; + + // In addition to the standard categories, the underlying + // operating system is allowed to define extra LC_* + // macros. For GNU systems, the following are also valid: + // LC_PAPER, LC_NAME, LC_ADDRESS, LC_TELEPHONE, LC_MEASUREMENT, + // and LC_IDENTIFICATION. + static const size_t _S_extra_categories_size = _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[_S_categories_size + + _S_extra_categories_size]; explicit locale(_Impl*) throw(); @@ -308,7 +327,9 @@ namespace std _Atomic_word _M_references; facet** _M_facets; size_t _M_facets_size; - const char* _M_names[_S_num_categories]; + + char* _M_names[_S_categories_size + + _S_extra_categories_size]; static const locale::id* const _S_id_ctype[]; static const locale::id* const _S_id_numeric[]; static const locale::id* const _S_id_collate[]; @@ -348,8 +369,10 @@ namespace std _M_check_same_name() { bool __ret = true; - for (size_t i = 0; __ret && i < _S_num_categories - 1; ++i) - __ret &= (strcmp(_M_names[i], _M_names[i + 1]) == 0); + for (size_t __i = 0; + __ret && __i < _S_categories_size + _S_extra_categories_size - 1; + ++__i) + __ret &= (strcmp(_M_names[__i], _M_names[__i + 1]) == 0); return __ret; } @@ -376,8 +399,14 @@ namespace std { _M_impl = new _Impl(*__other._M_impl, 1); _M_impl->_M_install_facet(&_Facet::id, __f); - for (size_t __i = 0; __i < _S_num_categories; ++__i) - _M_impl->_M_names[__i] = "*"; + for (size_t __i = 0; + __i < _S_categories_size + _S_extra_categories_size; ++__i) + { + delete [] _M_impl->_M_names[__i]; + char* __new = new char[2]; + strcpy(__new, "*"); + _M_impl->_M_names[__i] = __new; + } } // 22.1.1.1.2 Class locale::facet diff --git a/libstdc++-v3/src/codecvt.cc b/libstdc++-v3/src/codecvt.cc index a2fb42d96919..1fe6b97bc6d0 100644 --- a/libstdc++-v3/src/codecvt.cc +++ b/libstdc++-v3/src/codecvt.cc @@ -50,7 +50,7 @@ namespace std codecvt:: ~codecvt() - { } + { } codecvt_base::result codecvt:: diff --git a/libstdc++-v3/src/ctype.cc b/libstdc++-v3/src/ctype.cc index 7ca934eb379c..3d5ee618c53e 100644 --- a/libstdc++-v3/src/ctype.cc +++ b/libstdc++-v3/src/ctype.cc @@ -79,8 +79,7 @@ namespace std ctype::~ctype() { - if (_M_c_locale_ctype != _S_c_locale) - _S_destroy_c_locale(_M_c_locale_ctype); + _S_destroy_c_locale(_M_c_locale_ctype); if (_M_del) delete[] this->table(); } @@ -135,17 +134,13 @@ namespace std { _M_c_locale_ctype = _S_clone_c_locale(__cloc); } ctype::~ctype() - { - if (_M_c_locale_ctype != _S_c_locale) - _S_destroy_c_locale(_M_c_locale_ctype); - } + { _S_destroy_c_locale(_M_c_locale_ctype); } template<> ctype_byname::ctype_byname(const char* __s, size_t __refs) : ctype(__refs) { - if (_M_c_locale_ctype != _S_c_locale) - _S_destroy_c_locale(_M_c_locale_ctype); + _S_destroy_c_locale(_M_c_locale_ctype); _S_create_c_locale(_M_c_locale_ctype, __s); } #endif diff --git a/libstdc++-v3/src/globals.cc b/libstdc++-v3/src/globals.cc index 36d193fb406b..c6ff69c5e811 100644 --- a/libstdc++-v3/src/globals.cc +++ b/libstdc++-v3/src/globals.cc @@ -44,163 +44,209 @@ // Because declares the standard streams to be [io]stream // types instead of say [io]fstream types, it is also necessary to // allocate the actual file buffers in this file. -namespace std +namespace __gnu_cxx { - // Standard "C" locale. - typedef char fake_locale[sizeof(locale)] - __attribute__ ((aligned(__alignof__(locale)))); - fake_locale c_locale; + using namespace std; + + typedef char fake_facet_name[sizeof(char*)] + __attribute__ ((aligned(__alignof__(char*)))); + fake_facet_name facet_name[6 + _GLIBCPP_NUM_CATEGORIES]; typedef char fake_locale_Impl[sizeof(locale::_Impl)] __attribute__ ((aligned(__alignof__(locale::_Impl)))); fake_locale_Impl c_locale_impl; - + + + // NB: The asm directives renames these non-exported, namespace + // __gnu_cxx symbols into the mistakenly exported, namespace std + // symbols in GLIBCPP_3.2. + // The rename syntax is + // asm (".symver currentname,oldname@@GLIBCPP_3.2") + // At the same time, these new __gnu_cxx symbols are not exported. + // In the future, GLIBCXX_ABI > 5 should remove all uses of + // _GLIBCPP_ASM_SYMVER in this file. + typedef char fake_locale[sizeof(locale)] + __attribute__ ((aligned(__alignof__(locale)))); + fake_locale c_locale; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx8c_localeE, _ZSt8c_locale, GLIBCPP_3.2) + + // GLIBCXX_ABI > 5 will not need this symbol at all. + // It's here just as a placeholder, as the size of this exported + // object changed. The new symbol is not exported. + const int o = sizeof(locale::_Impl) - sizeof(char*[_GLIBCPP_NUM_CATEGORIES]); + typedef char fake_locale_Impl_compat[o] + __attribute__ ((aligned(__alignof__(o)))); + fake_locale_Impl_compat c_locale_impl_compat; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx20c_locale_impl_compatE, _ZSt13c_locale_impl, GLIBCPP_3.2) + typedef char fake_facet_vec[sizeof(locale::facet*)] __attribute__ ((aligned(__alignof__(locale::facet*)))); fake_facet_vec facet_vec[_GLIBCPP_NUM_FACETS]; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9facet_vecE, _ZSt9facet_vec, GLIBCPP_3.2) typedef char fake_ctype_c[sizeof(std::ctype)] __attribute__ ((aligned(__alignof__(std::ctype)))); fake_ctype_c ctype_c; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx7ctype_cE, _ZSt7ctype_c, GLIBCPP_3.2) typedef char fake_collate_c[sizeof(std::collate)] __attribute__ ((aligned(__alignof__(std::collate)))); fake_collate_c collate_c; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9collate_cE, _ZSt9collate_c, GLIBCPP_3.2) typedef char fake_numpunct_c[sizeof(numpunct)] __attribute__ ((aligned(__alignof__(numpunct)))); fake_numpunct_c numpunct_c; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx10numpunct_cE, _ZSt10numpunct_c, GLIBCPP_3.2) typedef char fake_num_get_c[sizeof(num_get)] __attribute__ ((aligned(__alignof__(num_get)))); fake_num_get_c num_get_c; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9num_get_cE, _ZSt9num_get_c, GLIBCPP_3.2) typedef char fake_num_put_c[sizeof(num_put)] __attribute__ ((aligned(__alignof__(num_put)))); fake_num_put_c num_put_c; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9num_put_cE, _ZSt9num_put_c, GLIBCPP_3.2) typedef char fake_codecvt_c[sizeof(codecvt)] __attribute__ ((aligned(__alignof__(codecvt)))); fake_codecvt_c codecvt_c; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9codecvt_cE, _ZSt9codecvt_c, GLIBCPP_3.2) typedef char fake_moneypunct_c[sizeof(moneypunct)] __attribute__ ((aligned(__alignof__(moneypunct)))); fake_moneypunct_c moneypunct_tc; fake_moneypunct_c moneypunct_fc; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx13moneypunct_tcE,\ + _ZSt13moneypunct_tc, GLIBCPP_3.2) + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx13moneypunct_fcE,\ + _ZSt13moneypunct_fc, GLIBCPP_3.2) typedef char fake_money_get_c[sizeof(money_get)] __attribute__ ((aligned(__alignof__(money_get)))); fake_money_get_c money_get_c; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx11money_get_cE, _ZSt11money_get_c, GLIBCPP_3.2) typedef char fake_money_put_c[sizeof(money_put)] __attribute__ ((aligned(__alignof__(money_put)))); fake_money_put_c money_put_c; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx11money_put_cE, _ZSt11money_put_c, GLIBCPP_3.2) typedef char fake_timepunct_c[sizeof(__timepunct)] __attribute__ ((aligned(__alignof__(__timepunct)))); fake_timepunct_c timepunct_c; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx11timepunct_cE, _ZSt11timepunct_c, GLIBCPP_3.2) typedef char fake_time_get_c[sizeof(time_get)] __attribute__ ((aligned(__alignof__(time_get)))); fake_time_get_c time_get_c; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx10time_get_cE, _ZSt10time_get_c, GLIBCPP_3.2) typedef char fake_time_put_c[sizeof(time_put)] __attribute__ ((aligned(__alignof__(time_put)))); fake_time_put_c time_put_c; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx10time_put_cE, _ZSt10time_put_c, GLIBCPP_3.2) typedef char fake_messages_c[sizeof(messages)] __attribute__ ((aligned(__alignof__(messages)))); fake_messages_c messages_c; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx10messages_cE, _ZSt10messages_c, GLIBCPP_3.2) #ifdef _GLIBCPP_USE_WCHAR_T typedef char fake_wtype_w[sizeof(std::ctype)] __attribute__ ((aligned(__alignof__(std::ctype)))); fake_wtype_w ctype_w; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx7ctype_wE, _ZSt7ctype_w, GLIBCPP_3.2) typedef char fake_wollate_w[sizeof(std::collate)] __attribute__ ((aligned(__alignof__(std::collate)))); fake_wollate_w collate_w; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9collate_wE, _ZSt9collate_w, GLIBCPP_3.2) typedef char fake_numpunct_w[sizeof(numpunct)] __attribute__ ((aligned(__alignof__(numpunct)))); fake_numpunct_w numpunct_w; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx10numpunct_wE, _ZSt10numpunct_w, GLIBCPP_3.2) typedef char fake_num_get_w[sizeof(num_get)] __attribute__ ((aligned(__alignof__(num_get)))); fake_num_get_w num_get_w; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9num_get_wE, _ZSt9num_get_w, GLIBCPP_3.2) typedef char fake_num_put_w[sizeof(num_put)] __attribute__ ((aligned(__alignof__(num_put)))); fake_num_put_w num_put_w; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9num_put_wE, _ZSt9num_put_w, GLIBCPP_3.2) typedef char fake_wodecvt_w[sizeof(codecvt)] __attribute__ ((aligned(__alignof__(codecvt)))); fake_wodecvt_w codecvt_w; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9codecvt_wE, _ZSt9codecvt_w, GLIBCPP_3.2) typedef char fake_moneypunct_w[sizeof(moneypunct)] __attribute__ ((aligned(__alignof__(moneypunct)))); fake_moneypunct_w moneypunct_tw; fake_moneypunct_w moneypunct_fw; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx13moneypunct_twE,\ + _ZSt13moneypunct_tw, GLIBCPP_3.2) + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx13moneypunct_fwE,\ + _ZSt13moneypunct_fw, GLIBCPP_3.2) typedef char fake_money_get_w[sizeof(money_get)] __attribute__ ((aligned(__alignof__(money_get)))); fake_money_get_w money_get_w; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx11money_get_wE, _ZSt11money_get_w, GLIBCPP_3.2) typedef char fake_money_put_w[sizeof(money_put)] __attribute__ ((aligned(__alignof__(money_put)))); fake_money_put_w money_put_w; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx11money_put_wE, _ZSt11money_put_w, GLIBCPP_3.2) typedef char fake_timepunct_w[sizeof(__timepunct)] __attribute__ ((aligned(__alignof__(__timepunct)))); fake_timepunct_w timepunct_w; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx11timepunct_wE, _ZSt11timepunct_w, GLIBCPP_3.2) typedef char fake_time_get_w[sizeof(time_get)] __attribute__ ((aligned(__alignof__(time_get)))); fake_time_get_w time_get_w; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx10time_get_wE, _ZSt10time_get_w, GLIBCPP_3.2) typedef char fake_time_put_w[sizeof(time_put)] __attribute__ ((aligned(__alignof__(time_put)))); fake_time_put_w time_put_w; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx10time_put_wE, _ZSt10time_put_w, GLIBCPP_3.2) typedef char fake_messages_w[sizeof(messages)] __attribute__ ((aligned(__alignof__(messages)))); fake_messages_w messages_w; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx10messages_wE, _ZSt10messages_w, GLIBCPP_3.2) #endif - // Standard stream objects. - typedef char fake_istream[sizeof(istream)] - __attribute__ ((aligned(__alignof__(istream)))); - typedef char fake_ostream[sizeof(ostream)] - __attribute__ ((aligned(__alignof__(ostream)))); - fake_istream cin; - fake_ostream cout; - fake_ostream cerr; - fake_ostream clog; - - typedef char fake_filebuf[sizeof(__gnu_cxx::stdio_filebuf)] - __attribute__ ((aligned(__alignof__(__gnu_cxx::stdio_filebuf)))); + typedef char fake_filebuf[sizeof(stdio_filebuf)] + __attribute__ ((aligned(__alignof__(stdio_filebuf)))); fake_filebuf buf_cout; fake_filebuf buf_cin; fake_filebuf buf_cerr; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx8buf_coutE, _ZSt8buf_cout, GLIBCPP_3.2) + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx7buf_cinE, _ZSt7buf_cin, GLIBCPP_3.2) + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx8buf_cerrE, _ZSt8buf_cerr, GLIBCPP_3.2) #ifdef _GLIBCPP_USE_WCHAR_T - typedef char fake_wistream[sizeof(wistream)] - __attribute__ ((aligned(__alignof__(wistream)))); - typedef char fake_wostream[sizeof(wostream)] - __attribute__ ((aligned(__alignof__(wostream)))); - fake_wistream wcin; - fake_wostream wcout; - fake_wostream wcerr; - fake_wostream wclog; - - typedef char fake_wfilebuf[sizeof(__gnu_cxx::stdio_filebuf)] - __attribute__ ((aligned(__alignof__(__gnu_cxx::stdio_filebuf)))); + typedef char fake_wfilebuf[sizeof(stdio_filebuf)] + __attribute__ ((aligned(__alignof__(stdio_filebuf)))); fake_wfilebuf buf_wcout; fake_wfilebuf buf_wcin; fake_wfilebuf buf_wcerr; + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9buf_wcoutE, _ZSt9buf_wcout, GLIBCPP_3.2) + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx8buf_wcinE, _ZSt8buf_wcin, GLIBCPP_3.2) + _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9buf_wcerrE, _ZSt9buf_wcerr, GLIBCPP_3.2) #endif +} // namespace __gnu_cxx - +namespace std +{ // 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. @@ -223,4 +269,25 @@ namespace std _GLIBCPP_mutex_address_init () { __GTHREAD_MUTEX_INIT_FUNCTION (_GLIBCPP_mutex_address); } #endif -} + + // Standard stream objects. + typedef char fake_istream[sizeof(istream)] + __attribute__ ((aligned(__alignof__(istream)))); + typedef char fake_ostream[sizeof(ostream)] + __attribute__ ((aligned(__alignof__(ostream)))); + fake_istream cin; + fake_ostream cout; + fake_ostream cerr; + fake_ostream clog; + +#ifdef _GLIBCPP_USE_WCHAR_T + typedef char fake_wistream[sizeof(wistream)] + __attribute__ ((aligned(__alignof__(wistream)))); + typedef char fake_wostream[sizeof(wostream)] + __attribute__ ((aligned(__alignof__(wostream)))); + fake_wistream wcin; + fake_wostream wcout; + fake_wostream wcerr; + fake_wostream wclog; +#endif +} // namespace std diff --git a/libstdc++-v3/src/ios.cc b/libstdc++-v3/src/ios.cc index c1167f8c15cf..7bfdc5b4bb40 100644 --- a/libstdc++-v3/src/ios.cc +++ b/libstdc++-v3/src/ios.cc @@ -39,28 +39,34 @@ #include #include -namespace std +namespace __gnu_cxx { // Extern declarations for global objects in src/globals.cc. + extern stdio_filebuf buf_cout; + extern stdio_filebuf buf_cin; + extern stdio_filebuf buf_cerr; + +#ifdef _GLIBCPP_USE_WCHAR_T + extern stdio_filebuf buf_wcout; + extern stdio_filebuf buf_wcin; + extern stdio_filebuf buf_wcerr; +#endif +} // namespace __gnu_cxx + +namespace std +{ + using namespace __gnu_cxx; + extern istream cin; extern ostream cout; extern ostream cerr; extern ostream clog; - using __gnu_cxx::stdio_filebuf; - extern stdio_filebuf buf_cout; - extern stdio_filebuf buf_cin; - extern stdio_filebuf buf_cerr; - #ifdef _GLIBCPP_USE_WCHAR_T extern wistream wcin; extern wostream wcout; extern wostream wcerr; extern wostream wclog; - - extern stdio_filebuf buf_wcout; - extern stdio_filebuf buf_wcin; - extern stdio_filebuf buf_wcerr; #endif // Definitions for static const data members of __ios_flags. diff --git a/libstdc++-v3/src/locale-inst.cc b/libstdc++-v3/src/locale-inst.cc index 5e6c6751bc44..8f2c86381779 100644 --- a/libstdc++-v3/src/locale-inst.cc +++ b/libstdc++-v3/src/locale-inst.cc @@ -35,11 +35,7 @@ #include #include #include -#include -#include #include -#include -#include namespace std { diff --git a/libstdc++-v3/src/locale.cc b/libstdc++-v3/src/locale.cc index 6314ba6a7a57..127197d0138f 100644 --- a/libstdc++-v3/src/locale.cc +++ b/libstdc++-v3/src/locale.cc @@ -31,19 +31,19 @@ #include #include #include // For towupper, etc. -#include -#include #include -#include -#include #include -namespace std +namespace __gnu_cxx { // Defined in globals.cc. - extern locale c_locale; - extern locale::_Impl c_locale_impl; - extern locale::facet** facet_vec; + extern std::locale c_locale; + extern std::locale::_Impl c_locale_impl; +} // namespace __gnu_cxx + +namespace std +{ + using namespace __gnu_cxx; // Definitions for static const data members of locale. const locale::category locale::none; @@ -55,9 +55,14 @@ namespace std const locale::category locale::messages; const locale::category locale::all; + // In the future, GLIBCXX_ABI > 5 should remove all uses of + // _GLIBCPP_ASM_SYMVER in this file, and remove exports of any + // static data members of locale. locale::_Impl* locale::_S_classic; locale::_Impl* locale::_S_global; - const size_t locale::_S_num_categories; + const size_t locale::_S_categories_size; + _GLIBCPP_ASM_SYMVER(_ZNSt6locale18_S_categories_sizeE, _ZNSt6locale17_S_num_categoriesE, GLIBCPP_3.2) + const size_t locale::_S_extra_categories_size; // Definitions for static const data members of locale::id _Atomic_word locale::id::_S_highwater; // init'd to 0 by linker @@ -146,31 +151,12 @@ namespace std locale::_Impl::_S_id_ctype, locale::_Impl::_S_id_numeric, locale::_Impl::_S_id_collate, - locale::_Impl::_S_id_monetary, locale::_Impl::_S_id_time, + locale::_Impl::_S_id_monetary, locale::_Impl::_S_id_messages, 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(); @@ -182,6 +168,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) { } @@ -192,18 +179,110 @@ namespace std _S_initialize(); if (strcmp(__s, "C") == 0 || strcmp(__s, "POSIX") == 0) (_M_impl = _S_classic)->_M_add_reference(); - else if (strcmp(__s, "") == 0) + else if (strcmp(__s, "") != 0) + _M_impl = new _Impl(__s, 1); + else { + // Get it from the environment. char* __env = getenv("LC_ALL"); - if (__env) - _M_impl = new _Impl(__env, 1); - else if ((__env = getenv("LANG"))) - _M_impl = new _Impl(__env, 1); + // If LC_ALL is set we are done. + if (__env && strcmp(__env, "") != 0) + { + if (strcmp(__env, "C") == 0 || strcmp(__env, "POSIX") == 0) + (_M_impl = _S_classic)->_M_add_reference(); + else + _M_impl = new _Impl(__env, 1); + } else - (_M_impl = _S_classic)->_M_add_reference(); + { + char* __res; + // LANG may set a default different from "C". + char* __env = getenv("LANG"); + if (!__env || strcmp(__env, "") == 0 || strcmp(__env, "C") == 0 + || strcmp(__env, "POSIX") == 0) + __res = strdup("C"); + else + __res = strdup(__env); + + // Scan the categories looking for the first one + // different from LANG. + size_t __i = 0; + if (strcmp(__res, "C") == 0) + for (__i = 0; + __i < _S_categories_size + _S_extra_categories_size; + ++__i) + { + __env = getenv(_S_categories[__i]); + if (__env && strcmp(__env, "") != 0 + && strcmp(__env, "C") != 0 + && strcmp(__env, "POSIX") != 0) + break; + } + else + for (__i = 0; + __i < _S_categories_size + _S_extra_categories_size; + ++__i) + { + __env = getenv(_S_categories[__i]); + if (__env && strcmp(__env, "") != 0 + && strcmp(__env, __res) != 0) + break; + } + + // If one is found, build the complete string of + // the form LC_CTYPE=xxx;LC_NUMERIC=yyy; and so on... + if (__i < _S_categories_size + _S_extra_categories_size) + { + string __str; + for (size_t __j = 0; __j < __i; ++__j) + { + __str += _S_categories[__j]; + __str += "="; + __str += __res; + __str += ";"; + } + __str += _S_categories[__i]; + __str += "="; + __str += __env; + __str += ";"; + __i++; + for (; __i < _S_categories_size + + _S_extra_categories_size; ++__i) + { + __env = getenv(_S_categories[__i]); + if (!__env || strcmp(__env, "") == 0) + { + __str += _S_categories[__i]; + __str += '='; + __str += __res; + __str += ';'; + } + else if (strcmp(__env, "C") == 0 + || strcmp(__env, "POSIX") == 0) + { + __str += _S_categories[__i]; + __str += "=C;"; + } + else + { + __str += _S_categories[__i]; + __str += "="; + __str += __env; + __str += ";"; + } + } + __str.erase(__str.end() - 1); + _M_impl = new _Impl(__str.c_str(), 1); + } + // ... otherwise either an additional instance of + // the "C" locale or LANG. + else if (strcmp(__res, "C") == 0) + (_M_impl = _S_classic)->_M_add_reference(); + else + _M_impl = new _Impl(__res, 1); + free(__res); + } } - else - _M_impl = new _Impl(__s, 1); } else __throw_runtime_error("attempt to create locale from NULL name"); @@ -221,6 +300,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() { @@ -261,20 +343,22 @@ namespace std string locale::name() const { - // Need some kind of separator character. This one was pretty much - // arbitrarily chosen as to not conflict with glibc locales: the - // exact formatting is not set in stone. - const char __separator = '|'; - string __ret; if (_M_impl->_M_check_same_name()) __ret = _M_impl->_M_names[0]; else { - for (size_t i = 0; i < _S_num_categories; ++i) + __ret += _S_categories[0]; + __ret += "="; + __ret += _M_impl->_M_names[0]; + for (size_t __i = 1; + __i < _S_categories_size + _S_extra_categories_size; + ++__i) { - __ret += __separator; - __ret += _M_impl->_M_names[i]; + __ret += ";"; + __ret += _S_categories[__i]; + __ret += "="; + __ret += _M_impl->_M_names[__i]; } } return __ret; @@ -291,12 +375,8 @@ namespace std try { // 26 Standard facets, 2 references. - // One reference for _M_classic, one for _M_global - facet** f = new(&facet_vec) facet*[_GLIBCPP_NUM_FACETS]; - for (size_t __i = 0; __i < _GLIBCPP_NUM_FACETS; ++__i) - f[__i] = 0; - - _S_classic = new (&c_locale_impl) _Impl(f, 2, true); + // 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); } @@ -313,6 +393,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) { @@ -361,11 +457,8 @@ namespace std ~facet() { } locale::facet:: - facet(size_t __refs) throw() : _M_references(__refs) - { - if (!_S_c_locale) - _S_create_c_locale(_S_c_locale, "C"); - } + facet(size_t __refs) throw() : _M_references(__refs ? 1 : 0) + { } void locale::facet:: @@ -376,7 +469,7 @@ namespace std locale::facet:: _M_remove_reference() throw() { - if (__exchange_and_add(&_M_references, -1) == 0) + if (__exchange_and_add(&_M_references, -1) == 1) { try { delete this; } diff --git a/libstdc++-v3/src/localename.cc b/libstdc++-v3/src/localename.cc index 8fa911891705..61aa952e6ad2 100644 --- a/libstdc++-v3/src/localename.cc +++ b/libstdc++-v3/src/localename.cc @@ -30,9 +30,14 @@ #include #include -namespace std +namespace __gnu_cxx { + using namespace std; + // Defined in globals.cc. + extern locale::facet** facet_vec; + extern char* facet_name[6 + _GLIBCPP_NUM_CATEGORIES]; + extern std::ctype ctype_c; extern std::collate collate_c; extern numpunct numpunct_c; @@ -63,6 +68,11 @@ namespace std extern time_put time_put_w; extern std::messages messages_w; #endif +} // namespace __gnu_cxx + +namespace std +{ + using namespace __gnu_cxx; locale::_Impl:: ~_Impl() throw() @@ -71,6 +81,10 @@ namespace std if (_M_facets[__i]) _M_facets[__i]->_M_remove_reference(); delete [] _M_facets; + + for (size_t __i = 0; + __i < _S_categories_size + _S_extra_categories_size; ++__i) + delete [] _M_names[__i]; } // Clone existing _Impl object. @@ -95,14 +109,19 @@ namespace std if (_M_facets[__i]) _M_facets[__i]->_M_add_reference(); } - for (size_t __i = 0; __i < _S_num_categories; ++__i) - _M_names[__i] = __imp._M_names[__i]; + for (size_t __i = 0; + __i < _S_categories_size + _S_extra_categories_size; ++__i) + { + char* __new = new char[strlen(__imp._M_names[__i]) + 1]; + strcpy(__new, __imp._M_names[__i]); + _M_names[__i] = __new; + } } // Construct named _Impl. locale::_Impl:: _Impl(const char* __s, size_t __refs) - : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS) // XXX + : _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. @@ -122,11 +141,40 @@ namespace std } // Name all the categories. - for (size_t i = 0; i < _S_num_categories; ++i) - _M_names[i] = __s; + if (!strchr(__s, ';')) + { + size_t __len = strlen(__s) + 1; + for (size_t __i = 0; + __i < _S_categories_size + _S_extra_categories_size; ++__i) + { + _M_names[__i] = new char[__len]; + strcpy(_M_names[__i], __s); + } + } + else + { + char* __tmp = strdup(__s); + __tmp[strlen(__tmp)] = ';'; + strtok(__tmp, "=;"); + for (size_t __i = 0; + __i < _S_categories_size + _S_extra_categories_size - 1; ++__i) + { + char* __src = strtok(NULL, "=;"); + char* __new = new char[strlen(__src) + 1]; + strcpy(__new, __src); + _M_names[__i] = __new; + strtok(NULL, "=;"); + } + char* __src = strtok(NULL, "=;"); + char* __new = new char[strlen(__src) + 1]; + strcpy(__new, __src); + _M_names[_S_categories_size + _S_extra_categories_size - 1] = __new; - // Construct all standard facets and add them to _M_facets. - _M_init_facet(new std::ctype(__cloc)); + free(__tmp); + } + + // Construct all standard facets and add them to _M_facets. + _M_init_facet(new std::ctype(__cloc, 0, false)); _M_init_facet(new codecvt); _M_init_facet(new numpunct(__cloc)); _M_init_facet(new num_get); @@ -162,47 +210,61 @@ namespace std // Construct "C" _Impl. locale::_Impl:: - _Impl(facet** __f, size_t __refs, bool) - : _M_references(__refs), _M_facets(__f), _M_facets_size(_GLIBCPP_NUM_FACETS) + _Impl(facet**, size_t __refs, bool) + : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS) { + // Initialize the underlying locale model. + locale::facet::_S_create_c_locale(locale::facet::_S_c_locale, "C"); + + _M_facets = new(&facet_vec) facet*[_M_facets_size]; + for (size_t __i = 0; __i < _M_facets_size; ++__i) + _M_facets[__i] = 0; + // Name all the categories. - for (size_t i = 0; i < _S_num_categories; ++i) - _M_names[i] = "C"; + for (size_t __i = 0; + __i < _S_categories_size + _S_extra_categories_size; ++__i) + { + _M_names[__i] = new (&facet_name[__i]) char[2]; + strcpy(_M_names[__i], "C"); + } // This is needed as presently the C++ version of "C" locales // != data in the underlying locale model for __timepunct, // numpunct, and moneypunct. Also, the "C" locales must be // constructed in a way such that they are pre-allocated. - _M_init_facet(new (&ctype_c) std::ctype); - _M_init_facet(new (&codecvt_c) codecvt); - _M_init_facet(new (&numpunct_c) numpunct); - _M_init_facet(new (&num_get_c) num_get); - _M_init_facet(new (&num_put_c) num_put); - _M_init_facet(new (&collate_c) std::collate); - _M_init_facet(new (&moneypunct_fc) moneypunct); - _M_init_facet(new (&moneypunct_tc) moneypunct); - _M_init_facet(new (&money_get_c) money_get); - _M_init_facet(new (&money_put_c) money_put); - _M_init_facet(new (&timepunct_c) __timepunct); - _M_init_facet(new (&time_get_c) time_get); - _M_init_facet(new (&time_put_c) time_put); - _M_init_facet(new (&messages_c) std::messages); + // NB: Set locale::facets(ref) count to one so that each individual + // facet is not destroyed when the locale (and thus locale::_Impl) is + // 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)); + _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)); + _M_init_facet(new (&moneypunct_fc) moneypunct(1)); + _M_init_facet(new (&moneypunct_tc) moneypunct(1)); + _M_init_facet(new (&money_get_c) money_get(1)); + _M_init_facet(new (&money_put_c) money_put(1)); + _M_init_facet(new (&timepunct_c) __timepunct(1)); + _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); - _M_init_facet(new (&codecvt_w) codecvt); - _M_init_facet(new (&numpunct_w) numpunct); - _M_init_facet(new (&num_get_w) num_get); - _M_init_facet(new (&num_put_w) num_put); - _M_init_facet(new (&collate_w) std::collate); - _M_init_facet(new (&moneypunct_fw) moneypunct); - _M_init_facet(new (&moneypunct_tw) moneypunct); - _M_init_facet(new (&money_get_w) money_get); - _M_init_facet(new (&money_put_w) money_put); - _M_init_facet(new (&timepunct_w) __timepunct); - _M_init_facet(new (&time_get_w) time_get); - _M_init_facet(new (&time_put_w) time_put); - _M_init_facet(new (&messages_w) std::messages); -#endif + _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)); + _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)); + _M_init_facet(new (&moneypunct_fw) moneypunct(1)); + _M_init_facet(new (&moneypunct_tw) moneypunct(1)); + _M_init_facet(new (&money_get_w) money_get(1)); + _M_init_facet(new (&money_put_w) money_put(1)); + _M_init_facet(new (&timepunct_w) __timepunct(1)); + _M_init_facet(new (&time_get_w) time_get(1)); + _M_init_facet(new (&time_put_w) time_put(1)); + _M_init_facet(new (&messages_w) std::messages(1)); +#endif } void @@ -210,7 +272,7 @@ namespace std _M_replace_categories(const _Impl* __imp, category __cat) { category __mask; - for (unsigned int __ix = 0; __ix < _S_num_categories; ++__ix) + for (size_t __ix = 0; __ix < _S_categories_size; ++__ix) { __mask = 1 << __ix; if (__mask & __cat) @@ -220,7 +282,12 @@ namespace std // If both have names, go ahead and mangle. if (strcmp(_M_names[__ix], "*") != 0 && strcmp(__imp->_M_names[__ix], "*") != 0) - _M_names[__ix] = __imp->_M_names[__ix]; + { + delete [] _M_names[__ix]; + char* __new = new char[strlen(__imp->_M_names[__ix]) + 1]; + strcpy(__new, __imp->_M_names[__ix]); + _M_names[__ix] = __new; + } } } } @@ -250,6 +317,8 @@ namespace std if (__fp) { size_t __index = __idp->_M_id(); + + // Check size of facet vector to ensure adequate room. if (__index > _M_facets_size - 1) { facet** __old = _M_facets; @@ -266,11 +335,11 @@ namespace std delete [] __old; } + __fp->_M_add_reference(); facet*& __fpr = _M_facets[__index]; if (__fpr) { // Replacing an existing facet. Order matters. - __fp->_M_add_reference(); __fpr->_M_remove_reference(); __fpr = __fp; } diff --git a/libstdc++-v3/testsuite/22_locale/ctor_copy_dtor.cc b/libstdc++-v3/testsuite/22_locale/ctor_copy_dtor.cc index a27b2457e874..8ffef6e34e1e 100644 --- a/libstdc++-v3/testsuite/22_locale/ctor_copy_dtor.cc +++ b/libstdc++-v3/testsuite/22_locale/ctor_copy_dtor.cc @@ -121,7 +121,7 @@ void test01() string str1, str2; // construct a locale object with the C facet - const locale& loc01 = locale::classic(); + const locale loc01 = locale::classic(); // 1 // template locale(const locale& other, Facet* f) @@ -315,16 +315,183 @@ void test03() { bool test = true; #ifdef _GLIBCPP_HAVE_SETENV - const char* oldLANG = getenv("LANG"); - if (!setenv("LANG", "it_IT", 1)) + const char* LC_ALL_orig = getenv("LC_ALL"); + if (!setenv("LC_ALL", "it_IT", 1)) { std::locale loc(""); VERIFY( loc.name() == "it_IT" ); - setenv("LANG", oldLANG ? oldLANG : "", 1); + setenv("LC_ALL", LC_ALL_orig ? LC_ALL_orig : "", 1); } #endif } + +// More tests for locale("") == POSIX locale::name. +void test04() +{ + bool test = true; + using namespace std; + +#ifdef _GLIBCPP_HAVE_SETENV + + const char* LANG_orig = getenv("LANG") ? strdup(getenv("LANG")) : ""; + const char* LC_ALL_orig = getenv("LC_ALL") ? strdup(getenv("LC_ALL")) : ""; + const char* LC_CTYPE_orig = + getenv("LC_CTYPE") ? strdup(getenv("LC_CTYPE")) : ""; + const char* LC_NUMERIC_orig = + getenv("LC_NUMERIC") ? strdup(getenv("LC_NUMERIC")) : ""; + const char* LC_COLLATE_orig = + getenv("LC_COLLATE") ? strdup(getenv("LC_COLLATE")) : ""; + const char* LC_TIME_orig = + getenv("LC_TIME") ? strdup(getenv("LC_TIME")) : ""; + const char* LC_MONETARY_orig = + getenv("LC_MONETARY") ? strdup(getenv("LC_MONETARY")) : ""; + const char* LC_MESSAGES_orig = + getenv("LC_MESSAGES") ? strdup(getenv("LC_MESSAGES")) : ""; +#if _GLIBCPP_NUM_CATEGORIES + const char* LC_PAPER_orig = + getenv("LC_PAPER") ? strdup(getenv("LC_PAPER")) : ""; + const char* LC_NAME_orig = + getenv("LC_NAME") ? strdup(getenv("LC_NAME")) : ""; + const char* LC_ADDRESS_orig = + getenv("LC_ADDRESS") ? strdup(getenv("LC_ADDRESS")) : ""; + const char* LC_TELEPHONE_orig = + getenv("LC_TELEPHONE") ? strdup(getenv("LC_TELEPHONE")) : ""; + const char* LC_MEASUREMENT_orig = + getenv("LC_MEASUREMENT") ? strdup(getenv("LC_MEASUREMENT")) : ""; + const char* LC_IDENTIFICATION_orig = + getenv("LC_IDENTIFICATION") ? strdup(getenv("LC_IDENTIFICATION")) : ""; +#endif + + // Check that a "POSIX" LC_ALL is equivalent to "C". + if (!setenv("LC_ALL", "POSIX", 1)) + { + locale loc(""); + VERIFY( loc.name() == "C" ); + } + setenv("LC_ALL", "", 1); + + // Check that a "en_PH" LC_ALL is equivalent to "en_PH". + if (!setenv("LC_ALL", "en_PH", 1)) + { + locale loc(""); + VERIFY( loc.name() == "en_PH" ); + } + setenv("LC_ALL", "", 1); + + // Explicit check that LC_ALL sets regardless of LC_* and LANG. + if (!setenv("LANG", "es_MX", 1) && !setenv("LC_COLLATE", "de_DE", 1)) + { + if (!setenv("LC_ALL", "en_PH", 1)) + { + locale loc(""); + VERIFY( loc.name() == "en_PH" ); + } + setenv("LC_ALL", "", 1); + setenv("LANG", LANG_orig ? LANG_orig : "", 1); + setenv("LC_COLLATE", LC_COLLATE_orig ? LC_COLLATE_orig : "", 1); + } + + // NB: LANG checks all LC_* macro settings. As such, all LC_* macros + // must be cleared for these tests, and then restored. + setenv("LC_ALL", "", 1); + setenv("LC_CTYPE", "", 1); + setenv("LC_NUMERIC", "", 1); + setenv("LC_COLLATE", "", 1); + setenv("LC_TIME", "", 1); + setenv("LC_MONETARY", "", 1); + setenv("LC_MESSAGES", "", 1); +#if _GLIBCPP_NUM_CATEGORIES + setenv("LC_PAPER", "", 1); + setenv("LC_NAME", "", 1); + setenv("LC_ADDRESS", "", 1); + setenv("LC_TELEPHONE", "", 1); + setenv("LC_MEASUREMENT", "", 1); + setenv("LC_IDENTIFICATION", "", 1); +#endif + + // Check the default set by LANG. + if (!setenv("LANG", "fr_FR", 1)) + { + locale loc(""); + VERIFY( loc.name() == "fr_FR" ); + } + + // Check that a "POSIX" LANG is equivalent to "C". + if (!setenv("LANG", "POSIX", 1)) + { + locale loc(""); + VERIFY( loc.name() == "C" ); + } + + // Setting a category in the "C" default. + if (!setenv("LC_COLLATE", "de_DE", 1)) + { + locale loc(""); + +#if _GLIBCPP_NUM_CATEGORIES + VERIFY( loc.name() == "LC_CTYPE=C;LC_NUMERIC=C;LC_COLLATE=de_DE;" + "LC_TIME=C;LC_MONETARY=C;LC_MESSAGES=C;LC_PAPER=C;" + "LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=C;" + "LC_IDENTIFICATION=C" ); +#else + VERIFY( loc.name() == "LC_CTYPE=C;LC_NUMERIC=C;LC_COLLATE=de_DE;" + "LC_TIME=C;LC_MONETARY=C;LC_MESSAGES=C" ); +#endif + } + + // Changing the LANG default while LC_COLLATE is set. + if (!setenv("LANG", "fr_FR", 1)) + { + locale loc(""); +#if _GLIBCPP_NUM_CATEGORIES + VERIFY( loc.name() == "LC_CTYPE=fr_FR;LC_NUMERIC=fr_FR;" + "LC_COLLATE=de_DE;LC_TIME=fr_FR;LC_MONETARY=fr_FR;" + "LC_MESSAGES=fr_FR;LC_PAPER=fr_FR;LC_NAME=fr_FR;" + "LC_ADDRESS=fr_FR;LC_TELEPHONE=fr_FR;LC_MEASUREMENT=fr_FR;" + "LC_IDENTIFICATION=fr_FR" ); +#else + VERIFY( loc.name() == "LC_CTYPE=fr_FR;LC_NUMERIC=fr_FR;" + "LC_COLLATE=de_DE;LC_TIME=fr_FR;LC_MONETARY=fr_FR;" + "LC_MESSAGES=fr_FR" ); +#endif + } + + // Changing another (C only) category. +#if _GLIBCPP_NUM_CATEGORIES + if (!setenv("LC_IDENTIFICATION", "it_IT", 1)) + { + locale loc(""); + VERIFY( loc.name() == "LC_CTYPE=fr_FR;LC_NUMERIC=fr_FR;" + "LC_COLLATE=de_DE;LC_TIME=fr_FR;LC_MONETARY=fr_FR;" + "LC_MESSAGES=fr_FR;LC_PAPER=fr_FR;LC_NAME=fr_FR;" + "LC_ADDRESS=fr_FR;LC_TELEPHONE=fr_FR;LC_MEASUREMENT=fr_FR;" + "LC_IDENTIFICATION=it_IT" ); + } +#endif + + // Restore the environment. + setenv("LANG", LANG_orig ? LANG_orig : "", 1); + setenv("LC_ALL", LC_ALL_orig ? LC_ALL_orig : "", 1); + setenv("LC_CTYPE", LC_CTYPE_orig ? LC_CTYPE_orig : "", 1); + setenv("LC_NUMERIC", LC_NUMERIC_orig ? LC_NUMERIC_orig : "", 1); + setenv("LC_COLLATE", LC_COLLATE_orig ? LC_COLLATE_orig : "", 1); + setenv("LC_TIME", LC_TIME_orig ? LC_TIME_orig : "", 1); + setenv("LC_MONETARY", LC_MONETARY_orig ? LC_MONETARY_orig : "", 1); + setenv("LC_MESSAGES", LC_MESSAGES_orig ? LC_MESSAGES_orig : "", 1); +#if _GLIBCPP_NUM_CATEGORIES + setenv("LC_PAPER", LC_PAPER_orig ? LC_PAPER_orig : "", 1); + setenv("LC_NAME", LC_NAME_orig ? LC_NAME_orig : "", 1); + setenv("LC_ADDRESS", LC_ADDRESS_orig ? LC_ADDRESS_orig : "", 1); + setenv("LC_TELEPHONE", LC_TELEPHONE_orig ? LC_TELEPHONE_orig : "", 1); + setenv("LC_MEASUREMENT", LC_MEASUREMENT_orig ? LC_MEASUREMENT_orig : "", 1); + setenv("LC_IDENTIFICATION", + LC_IDENTIFICATION_orig ? LC_IDENTIFICATION_orig : "", 1); +#endif + +#endif +} + int main() { test00(); @@ -335,6 +502,7 @@ int main() test02(); test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/22_locale/facet.cc b/libstdc++-v3/testsuite/22_locale/facet.cc index 431718e78345..9c613b4c2033 100644 --- a/libstdc++-v3/testsuite/22_locale/facet.cc +++ b/libstdc++-v3/testsuite/22_locale/facet.cc @@ -1,6 +1,6 @@ // 2000-08-31 Benjamin Kosnik -// Copyright (C) 2000 Free Software Foundation +// Copyright (C) 2000, 2002 Free Software Foundation // // 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 @@ -25,6 +25,7 @@ #include #include #include +#include #include // 1 a class if a facet if it is publicly derived from another facet @@ -233,9 +234,69 @@ void test01() } } +// 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; + +void test02() +{ + using namespace std; + bool test = true; + + // 1: Destroyed when out of scope. + VERIFY( counter == 0 ); + { + locale loc01(locale::classic(), new facet_type); + VERIFY( counter == 1 ); + } + VERIFY( counter == 0 ); + + // 2: Not destroyed when out of scope, deliberately leaked. + VERIFY( counter == 0 ); + { + // Default refs argument is zero. + locale loc02(locale::classic(), new facet_type(1)); + VERIFY( counter == 1 ); + } + VERIFY( counter == 1 ); + + // 3: Pathological. + counter = 0; + { + // Test bounds. + facet_type* f = new facet_type(numeric_limits::max()); + VERIFY( counter == 1 ); + // Add a reference. + locale loc01(locale::classic(), f); + { + // Add another reference... + locale loc02(locale::classic(), f); + } + VERIFY( counter == 1 ); + } + + // 4: Named locale should destroy facets when it goes out of scope. + // Not quite sure how to test for this w/o valgrind at the moment. + { + locale loc03("es_MX"); + } +} + int main () { test01(); + test02(); return 0; } diff --git a/libstdc++-v3/testsuite/22_locale/static_members.cc b/libstdc++-v3/testsuite/22_locale/static_members.cc index 16e856a2ee4c..9811dd9a8067 100644 --- a/libstdc++-v3/testsuite/22_locale/static_members.cc +++ b/libstdc++-v3/testsuite/22_locale/static_members.cc @@ -1,6 +1,6 @@ // 2000-09-13 Benjamin Kosnik -// Copyright (C) 2000 Free Software Foundation +// Copyright (C) 2000, 2002 Free Software Foundation // // 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 @@ -22,6 +22,7 @@ #include // for mbstate_t #include +#include #include typedef std::codecvt ccodecvt; @@ -30,14 +31,15 @@ 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& loc01 = locale::classic(); - // construct a locale object with the specialized facet. - locale loc02(locale::classic(), new gnu_codecvt); + // Construct a locale object with the C facet. + const locale loc01 = locale::classic(); + + // Construct a locale object with the specialized facet. + locale loc02(locale::classic(), new gnu_codecvt); VERIFY ( loc01 != loc02 ); VERIFY ( !(loc01 == loc02) ); @@ -50,15 +52,143 @@ 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 settings. + locale::global(global_orig); +} + +// Sanity check locale::global(loc) and setlocale. +void test02() +{ + using namespace std; + bool test = true; + + const string ph("en_PH"); + const string mx("es_MX"); + const char* orig = setlocale(LC_ALL, NULL); + const char* testph = setlocale(LC_ALL, ph.c_str()); + const char* testmx = setlocale(LC_ALL, mx.c_str()); + setlocale(LC_ALL, orig); + + // If the underlying locale doesn't support these names, setlocale + // won't be reset. Therefore, disable unless we know these specific + // named locales work. + if (testph && testmx) + { + const locale loc_ph(ph.c_str()); + const locale loc_mx(mx.c_str()); + + // Use setlocale between two calls to locale("") + const locale loc_env_1(""); + setlocale(LC_ALL, ph.c_str()); + const locale loc_env_2(""); + VERIFY( loc_env_1 == loc_env_2 ); + + // Change global locale. + locale global_orig = locale::global(loc_mx); + const char* lc_all_mx = setlocale(LC_ALL, NULL); + if (lc_all_mx) + { + cout << "lc_all_mx is " << lc_all_mx << endl; + VERIFY( mx == lc_all_mx ); + } + + // 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 () { test01(); + test02(); + test03(); return 0; } diff --git a/libstdc++-v3/testsuite/abi_check.cc b/libstdc++-v3/testsuite/abi_check.cc index 1e407811437a..21ca619ca83f 100644 --- a/libstdc++-v3/testsuite/abi_check.cc +++ b/libstdc++-v3/testsuite/abi_check.cc @@ -46,17 +46,35 @@ struct symbol_info enum category { none, function, object, error }; category type; std::string name; - std::string name_demangled; - std::string version; + std::string demangled_name; int size; + std::string version_name; symbol_info() : type(none), size(0) { } symbol_info(const symbol_info& other) - : type(other.type), name(other.name), name_demangled(other.name_demangled), - version(other.version), size(other.size) { } + : type(other.type), name(other.name), demangled_name(other.demangled_name), + size(other.size), version_name(other.version_name) { } }; +namespace __gnu_cxx +{ + using namespace std; + + template<> + struct hash + { + size_t operator()(const string& s) const + { + const collate& c = use_facet >(locale::classic()); + return c.hash(s.c_str(), s.c_str() + s.size()); + } + }; +} + +typedef std::deque symbol_names; +typedef __gnu_cxx::hash_map symbol_infos; + bool check_compatible(const symbol_info& lhs, const symbol_info& rhs, bool verbose = false) @@ -93,8 +111,7 @@ check_compatible(const symbol_info& lhs, const symbol_info& rhs, } } - // Expect something more sophisticated eventually. - if (lhs.version != rhs.version) + if (lhs.version_name != rhs.version_name) { ret = false; if (verbose) @@ -106,19 +123,6 @@ check_compatible(const symbol_info& lhs, const symbol_info& rhs, return ret; } -template - std::basic_ostream<_CharT, _Traits>& - operator<<(std::basic_ostream<_CharT, _Traits>& os, symbol_info& si) - { - using namespace std; - os << si.type << endl; - os << si.name << endl; - os << si.name_demangled << endl; - os << si.version << endl; - os << si.size << endl; - return os; - } - const char* demangle(const std::string& mangled) { @@ -187,7 +191,7 @@ line_to_symbol_info(std::string& input, symbol_info& output) istringstream iss(size); int x; iss >> x; - if (iss.good()) + if (!iss.fail()) output.size = x; input.erase(input.begin(), input.begin() + n + 1); } @@ -203,7 +207,7 @@ line_to_symbol_info(std::string& input, symbol_info& output) input.erase(input.begin(), input.begin() + n + 1); // Set version name. - output.version = input; + output.version_name = input; } else { @@ -213,12 +217,9 @@ line_to_symbol_info(std::string& input, symbol_info& output) } // Set the demangled name. - output.name_demangled = demangle(output.name); + output.demangled_name = demangle(output.name); } -typedef std::deque symbol_names; -typedef __gnu_cxx::hash_map symbol_infos; - void create_symbol_data(const char* file, symbol_infos& symbols, symbol_names& names) @@ -238,7 +239,7 @@ create_symbol_data(const char* file, symbol_infos& symbols, { symbol_info symbol; line_to_symbol_info(line, symbol); - symbols[symbol.name.c_str()] = symbol; + symbols[symbol.name] = symbol; names.push_back(symbol.name); line = empty; } @@ -256,7 +257,7 @@ report_symbol_info(const symbol_info& symbol, std::size_t n) // Add any other information to display here. cout << tab << "demangled symbol"<< endl; - cout << tab << symbol.name_demangled << endl; + cout << tab << symbol.demangled_name << endl; cout << endl; } @@ -279,10 +280,10 @@ main(int argc, char** argv) exit(1); } + + // Quick sanity/setup check for arguments. const char* test_file = argv[2]; const char* baseline_file = argv[3]; - - // Quick sanity/setup check if (access(test_file, R_OK) != 0) { cerr << "Cannot read symbols file " << test_file @@ -303,7 +304,7 @@ main(int argc, char** argv) create_symbol_data(baseline_file, baseline_symbols, baseline_names); create_symbol_data(test_file, test_symbols, test_names); - // More sanity checking. + // Sanity check results. const symbol_names::size_type baseline_size = baseline_names.size(); const symbol_names::size_type test_size = test_names.size(); if (!baseline_size || !test_size) @@ -315,53 +316,71 @@ main(int argc, char** argv) // Sort out names. // Assuming baseline_names, test_names are both unique w/ no duplicates. // - // The pairs of names in shared_names are needed to do lookups on - // the hash tables of common symbols to do compares. - // // The names added to missing_names are baseline_names not found in // test_names // -> symbols that have been deleted. // - // The names left in test_names are names not in baseline_names + // The names added to added_names are test_names are names not in + // baseline_names // -> symbols that have been added. - typedef pair string_pair; - vector shared_names; + symbol_names shared_names; symbol_names missing_names; + symbol_names added_names = test_names; for (size_t i = 0; i < baseline_size; ++i) { - symbol_names::iterator end = test_names.end(); - symbol_names::iterator it = find(test_names.begin(), end, - baseline_names[i]); + string what(baseline_names[i]); + symbol_names::iterator end = added_names.end(); + symbol_names::iterator it = find(added_names.begin(), end, what); if (it != end) { // Found. - shared_names.push_back(string_pair(baseline_names[i], *it)); - test_names.erase(it); + shared_names.push_back(what); + added_names.erase(it); } else - missing_names.push_back(baseline_names[i]); + missing_names.push_back(what); } - // Check common names for detailed compatibility. - const vector::size_type shared_size = shared_names.size(); + // Check shared names for compatibility. typedef pair symbol_pair; vector incompatible; - for (size_t i = 0; i < shared_size; ++i) + for (size_t i = 0; i < shared_names.size(); ++i) { - symbol_info base = baseline_symbols[shared_names[i].first.c_str()]; - symbol_info test = test_symbols[shared_names[i].second.c_str()]; + symbol_info base = baseline_symbols[shared_names[i]]; + symbol_info test = test_symbols[shared_names[i]]; if (!check_compatible(base, test)) incompatible.push_back(symbol_pair(base, test)); } + // Check added names for compatibility. + for (size_t i = 0; i < added_names.size(); ++i) + { + vector compatible_versions; + compatible_versions.push_back("GLIBCPP_3.2.1"); + + symbol_info test = test_symbols[added_names[i]]; + vector::iterator end = compatible_versions.end(); + + // Check version names for compatibility... + vector::iterator it1 = find(compatible_versions.begin(), end, + test.version_name); + + // Check for weak label. + vector::iterator it2 = find(compatible_versions.begin(), end, + test.name); + + if (it1 == end && it2 == end) + incompatible.push_back(symbol_pair(test, test)); + } + // Report results. - cout << test_names.size() << " added symbols " << endl; - for (size_t j = 0; j < test_names.size() ; ++j) - report_symbol_info(test_symbols[test_names[j].c_str()], j + 1); + cout << added_names.size() << " added symbols " << endl; + for (size_t j = 0; j < added_names.size() ; ++j) + report_symbol_info(test_symbols[added_names[j]], j + 1); cout << missing_names.size() << " missing symbols " << endl; for (size_t j = 0; j < missing_names.size() ; ++j) - report_symbol_info(baseline_symbols[missing_names[j].c_str()], j + 1); + report_symbol_info(baseline_symbols[missing_names[j]], j + 1); cout << incompatible.size() << " incompatible symbols " << endl; for (size_t j = 0; j < incompatible.size() ; ++j)