From 1d9aba81050b524d9dd61e59f4b28382782051b3 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Thu, 4 Dec 2008 17:16:27 +0000 Subject: [PATCH] re PR libstdc++/38368 (locale(const char* std_name) may create locale with broken facets) 2008-12-04 Paolo Carlini PR libstdc++/38368 * config/locale/gnu/numeric_members.cc (numpunct:: _M_initialize_numpunct, numpunct::_M_initialize_numpunct): Fix for THOUSANDS_SEP == '\0' consistently with "C" locale. * config/locale/gnu/monetary_members.cc (moneypunct:: _M_initialize_moneypunct, moneypunct:: _M_initialize_moneypunct, moneypunct:: _M_initialize_moneypunct, moneypunct:: _M_initialize_moneypunct): Fix for __MON_DECIMAL_POINT == '\0' or __MON_THOUSANDS_SEP == '\0' consistently with "C" locale. * testsuite/22_locale/locale/cons/38368.cc: New. From-SVN: r142439 --- libstdc++-v3/ChangeLog | 14 ++ .../config/locale/gnu/monetary_members.cc | 122 ++++++++++++++++-- .../config/locale/gnu/numeric_members.cc | 32 ++++- .../testsuite/22_locale/locale/cons/38368.cc | 54 ++++++++ 4 files changed, 201 insertions(+), 21 deletions(-) create mode 100644 libstdc++-v3/testsuite/22_locale/locale/cons/38368.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index e7a587d8741..3df3b49183b 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,17 @@ +2008-12-04 Paolo Carlini + + PR libstdc++/38368 + * config/locale/gnu/numeric_members.cc (numpunct:: + _M_initialize_numpunct, numpunct::_M_initialize_numpunct): + Fix for THOUSANDS_SEP == '\0' consistently with "C" locale. + * config/locale/gnu/monetary_members.cc (moneypunct:: + _M_initialize_moneypunct, moneypunct:: + _M_initialize_moneypunct, moneypunct:: + _M_initialize_moneypunct, moneypunct:: + _M_initialize_moneypunct): Fix for __MON_DECIMAL_POINT == '\0' or + __MON_THOUSANDS_SEP == '\0' consistently with "C" locale. + * testsuite/22_locale/locale/cons/38368.cc: New. + 2008-12-02 Paolo Carlini PR libstdc++/38365 (cont) diff --git a/libstdc++-v3/config/locale/gnu/monetary_members.cc b/libstdc++-v3/config/locale/gnu/monetary_members.cc index ea2b4fcad4e..1bf2487c86d 100644 --- a/libstdc++-v3/config/locale/gnu/monetary_members.cc +++ b/libstdc++-v3/config/locale/gnu/monetary_members.cc @@ -220,6 +220,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _M_data->_M_thousands_sep = ','; _M_data->_M_grouping = ""; _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; _M_data->_M_curr_symbol = ""; _M_data->_M_curr_symbol_size = 0; _M_data->_M_positive_sign = ""; @@ -240,11 +241,35 @@ _GLIBCXX_BEGIN_NAMESPACE(std) __cloc)); _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, __cloc)); - _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc); - _M_data->_M_grouping_size = strlen(_M_data->_M_grouping); _M_data->_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); _M_data->_M_positive_sign_size = strlen(_M_data->_M_positive_sign); + // Check for NULL, which implies no grouping. + if (_M_data->_M_thousands_sep == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = ','; + } + else + { + _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc); + _M_data->_M_grouping_size = strlen(_M_data->_M_grouping); + } + + // Check for NULL, which implies no fractional digits. + if (_M_data->_M_decimal_point == '\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = '.'; + } + else + _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, + __cloc)); + char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc)); if (!__nposn) _M_data->_M_negative_sign = "()"; @@ -256,8 +281,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std) // _Intl == true _M_data->_M_curr_symbol = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); _M_data->_M_curr_symbol_size = strlen(_M_data->_M_curr_symbol); - _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, - __cloc)); char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc)); char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc)); char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc)); @@ -285,6 +308,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _M_data->_M_thousands_sep = ','; _M_data->_M_grouping = ""; _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; _M_data->_M_curr_symbol = ""; _M_data->_M_curr_symbol_size = 0; _M_data->_M_positive_sign = ""; @@ -305,11 +329,35 @@ _GLIBCXX_BEGIN_NAMESPACE(std) __cloc)); _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, __cloc)); - _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc); - _M_data->_M_grouping_size = strlen(_M_data->_M_grouping); _M_data->_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); _M_data->_M_positive_sign_size = strlen(_M_data->_M_positive_sign); + // Check for NULL, which implies no grouping. + if (_M_data->_M_thousands_sep == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = ','; + } + else + { + _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc); + _M_data->_M_grouping_size = strlen(_M_data->_M_grouping); + } + + // Check for NULL, which implies no fractional digits. + if (_M_data->_M_decimal_point == '\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = '.'; + } + else + _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, + __cloc)); + char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc)); if (!__nposn) _M_data->_M_negative_sign = "()"; @@ -321,7 +369,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std) // _Intl == false _M_data->_M_curr_symbol = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); _M_data->_M_curr_symbol_size = strlen(_M_data->_M_curr_symbol); - _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc)); char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc)); char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc)); char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc)); @@ -362,6 +409,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _M_data->_M_thousands_sep = L','; _M_data->_M_grouping = ""; _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; _M_data->_M_curr_symbol = L""; _M_data->_M_curr_symbol_size = 0; _M_data->_M_positive_sign = L""; @@ -397,8 +445,32 @@ _GLIBCXX_BEGIN_NAMESPACE(std) __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc); _M_data->_M_thousands_sep = __u.__w; - _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc); - _M_data->_M_grouping_size = strlen(_M_data->_M_grouping); + + // Check for NULL, which implies no grouping. + if (_M_data->_M_thousands_sep == L'\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = L','; + } + else + { + _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc); + _M_data->_M_grouping_size = strlen(_M_data->_M_grouping); + } + + // Check for NULL, which implies no fractional digits. + if (_M_data->_M_decimal_point == L'\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = L'.'; + } + else + _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, + __cloc)); const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); @@ -467,8 +539,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std) __throw_exception_again; } - _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, - __cloc)); char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc)); char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc)); char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc)); @@ -507,6 +577,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _M_data->_M_thousands_sep = L','; _M_data->_M_grouping = ""; _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; _M_data->_M_curr_symbol = L""; _M_data->_M_curr_symbol_size = 0; _M_data->_M_positive_sign = L""; @@ -542,8 +613,32 @@ _GLIBCXX_BEGIN_NAMESPACE(std) __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc); _M_data->_M_thousands_sep = __u.__w; - _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc); - _M_data->_M_grouping_size = strlen(_M_data->_M_grouping); + + // Check for NULL, which implies no grouping. + if (_M_data->_M_thousands_sep == L'\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = L','; + } + else + { + _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc); + _M_data->_M_grouping_size = strlen(_M_data->_M_grouping); + } + + // Check for NULL, which implies no fractional digits. + if (_M_data->_M_decimal_point == L'\0') + { + // Like in "C" locale. + _M_data->_M_frac_digits = 0; + _M_data->_M_decimal_point = L'.'; + } + else + _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, + __cloc)); const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); @@ -613,7 +708,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std) __throw_exception_again; } - _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc)); char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc)); char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc)); char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc)); diff --git a/libstdc++-v3/config/locale/gnu/numeric_members.cc b/libstdc++-v3/config/locale/gnu/numeric_members.cc index 7a0400b46ca..93039e7654d 100644 --- a/libstdc++-v3/config/locale/gnu/numeric_members.cc +++ b/libstdc++-v3/config/locale/gnu/numeric_members.cc @@ -1,6 +1,7 @@ // std::numpunct implementation details, GNU version -*- C++ -*- -// Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +// Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -71,10 +72,18 @@ _GLIBCXX_BEGIN_NAMESPACE(std) // Check for NULL, which implies no grouping. if (_M_data->_M_thousands_sep == '\0') - _M_data->_M_grouping = ""; + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = ','; + } else - _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc); - _M_data->_M_grouping_size = strlen(_M_data->_M_grouping); + { + _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc); + _M_data->_M_grouping_size = strlen(_M_data->_M_grouping); + } } // NB: There is no way to extact this info from posix locales. @@ -128,11 +137,20 @@ _GLIBCXX_BEGIN_NAMESPACE(std) __u.__s = __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc); _M_data->_M_thousands_sep = __u.__w; + // Check for NULL, which implies no grouping. if (_M_data->_M_thousands_sep == L'\0') - _M_data->_M_grouping = ""; + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = L','; + } else - _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc); - _M_data->_M_grouping_size = strlen(_M_data->_M_grouping); + { + _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc); + _M_data->_M_grouping_size = strlen(_M_data->_M_grouping); + } } // NB: There is no way to extact this info from posix locales. diff --git a/libstdc++-v3/testsuite/22_locale/locale/cons/38368.cc b/libstdc++-v3/testsuite/22_locale/locale/cons/38368.cc new file mode 100644 index 00000000000..6f4bca12379 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/locale/cons/38368.cc @@ -0,0 +1,54 @@ +// { dg-require-namedlocale "" } + +// Copyright (C) 2008 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +// USA. + +// 22.1.1.2 locale constructors and destructors [lib.locale.cons] + +#include +#include + +// libstdc++/38368 +void test01() +{ + using namespace std; + bool test __attribute__((unused)) = true; + + locale loc(locale("C"), "en_US", locale::collate); + locale loc_copy(loc.name().c_str()); + + const moneypunct& mpunt = + use_facet >(loc_copy); + VERIFY( mpunt.decimal_point() == '.' ); + VERIFY( mpunt.thousands_sep() == ',' ); + + const moneypunct& mpunf = + use_facet >(loc_copy); + VERIFY( mpunf.decimal_point() == '.' ); + VERIFY( mpunf.thousands_sep() == ',' ); + + const numpunct& npun = use_facet >(loc_copy); + VERIFY( npun.decimal_point() == '.' ); + VERIFY( npun.thousands_sep() == ',' ); +} + +int main() +{ + test01(); + return 0; +}