re PR libstdc++/38368 (locale(const char* std_name) may create locale with broken...
authorPaolo Carlini <paolo.carlini@oracle.com>
Thu, 4 Dec 2008 17:16:27 +0000 (17:16 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Thu, 4 Dec 2008 17:16:27 +0000 (17:16 +0000)
2008-12-04  Paolo Carlini  <paolo.carlini@oracle.com>

PR libstdc++/38368
* config/locale/gnu/numeric_members.cc (numpunct<char>::
_M_initialize_numpunct, numpunct<wchar_t>::_M_initialize_numpunct):
Fix for THOUSANDS_SEP == '\0' consistently with "C" locale.
* config/locale/gnu/monetary_members.cc (moneypunct<char, true>::
_M_initialize_moneypunct, moneypunct<char, false>::
_M_initialize_moneypunct, moneypunct<wchar_t, true>::
_M_initialize_moneypunct, moneypunct<wchar_t, false>::
_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
libstdc++-v3/config/locale/gnu/monetary_members.cc
libstdc++-v3/config/locale/gnu/numeric_members.cc
libstdc++-v3/testsuite/22_locale/locale/cons/38368.cc [new file with mode: 0644]

index e7a587d..3df3b49 100644 (file)
@@ -1,3 +1,17 @@
+2008-12-04  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR libstdc++/38368
+       * config/locale/gnu/numeric_members.cc (numpunct<char>::
+       _M_initialize_numpunct, numpunct<wchar_t>::_M_initialize_numpunct):
+       Fix for THOUSANDS_SEP == '\0' consistently with "C" locale.
+       * config/locale/gnu/monetary_members.cc (moneypunct<char, true>::
+       _M_initialize_moneypunct, moneypunct<char, false>::
+       _M_initialize_moneypunct, moneypunct<wchar_t, true>::
+       _M_initialize_moneypunct, moneypunct<wchar_t, false>::
+       _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  <paolo.carlini@oracle.com>
 
        PR libstdc++/38365 (cont)
index ea2b4fc..1bf2487 100644 (file)
@@ -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));
index 7a0400b..93039e7 100644 (file)
@@ -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 (file)
index 0000000..6f4bca1
--- /dev/null
@@ -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 <locale>
+#include <testsuite_hooks.h>
+
+// 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<char, true>& mpunt =
+    use_facet<moneypunct<char, true> >(loc_copy);
+  VERIFY( mpunt.decimal_point() == '.' );
+  VERIFY( mpunt.thousands_sep() == ',' );
+
+  const moneypunct<char, false>& mpunf =
+    use_facet<moneypunct<char, false> >(loc_copy);
+  VERIFY( mpunf.decimal_point() == '.' );
+  VERIFY( mpunf.thousands_sep() == ',' );
+
+  const numpunct<char>& npun = use_facet<numpunct<char> >(loc_copy);
+  VERIFY( npun.decimal_point() == '.' );
+  VERIFY( npun.thousands_sep() == ',' );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}