This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[v3] libstdc++/40184
- From: Paolo Carlini <paolo dot carlini at oracle dot com>
- To: Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Cc: libstdc++ <libstdc++ at gcc dot gnu dot org>
- Date: Tue, 19 May 2009 20:24:10 +0200
- Subject: [v3] libstdc++/40184
Hi,
I think it's good enough, for now. I may revisit the issue when we'll
allow for an arbitrary order of the categories in the locale constructor
taking a C string. Tested x86_64-linux, committed to mainline.
Paolo.
///////////////////
2009-05-19 Paolo Carlini <paolo.carlini@oracle.com>
PR libstdc++/40184
* include/bits/locale_classes.h (locale::facet::_S_lc_ctype_c_locale):
Declare...
* config/locale/gnu/c_locale.cc: ... and define.
* config/locale/generic/c_locale.cc: Define.
* src/localename.cc (locale::_Impl::_Impl(const char*, size_t)):
Use it.
* testsuite/22_locale/locale/cons/40184.cc: New.
Index: src/localename.cc
===================================================================
--- src/localename.cc (revision 147710)
+++ src/localename.cc (working copy)
@@ -180,6 +180,7 @@
// see if the given name is valid.
__c_locale __cloc;
locale::facet::_S_create_c_locale(__cloc, __s);
+ __c_locale __clocm = __cloc;
__try
{
@@ -194,15 +195,19 @@
_M_names[__k] = 0;
// Name the categories.
+ const char* __smon = __s;
const size_t __len = std::strlen(__s);
if (!std::memchr(__s, ';', __len))
{
_M_names[0] = new char[__len + 1];
- std::memcpy(_M_names[0], __s, __len + 1);
+ std::memcpy(_M_names[0], __s, __len + 1);
}
else
{
const char* __end = __s;
+ bool __found_ctype = false;
+ bool __found_monetary = false;
+ size_t __ci = 0, __mi = 0;
for (size_t __i = 0; __i < _S_categories_size; ++__i)
{
const char* __beg = std::strchr(__end + 1, '=') + 1;
@@ -212,6 +217,24 @@
_M_names[__i] = new char[__end - __beg + 1];
std::memcpy(_M_names[__i], __beg, __end - __beg);
_M_names[__i][__end - __beg] = '\0';
+ if (!__found_ctype
+ && *(__beg - 2) == 'E' && *(__beg - 3) == 'P')
+ {
+ __found_ctype = true;
+ __ci = __i;
+ }
+ else if (!__found_monetary && *(__beg - 2) == 'Y')
+ {
+ __found_monetary = true;
+ __mi = __i;
+ }
+ }
+
+ if (std::strcmp(_M_names[__ci], _M_names[__mi]))
+ {
+ __smon = _M_names[__mi];
+ __clocm = locale::facet::_S_lc_ctype_c_locale(__cloc,
+ __smon);
}
}
@@ -222,8 +245,8 @@
_M_init_facet(new num_get<char>);
_M_init_facet(new num_put<char>);
_M_init_facet(new std::collate<char>(__cloc));
- _M_init_facet(new moneypunct<char, false>(__cloc, __s));
- _M_init_facet(new moneypunct<char, true>(__cloc, __s));
+ _M_init_facet(new moneypunct<char, false>(__cloc, 0));
+ _M_init_facet(new moneypunct<char, true>(__cloc, 0));
_M_init_facet(new money_get<char>);
_M_init_facet(new money_put<char>);
_M_init_facet(new __timepunct<char>(__cloc, __s));
@@ -238,8 +261,8 @@
_M_init_facet(new num_get<wchar_t>);
_M_init_facet(new num_put<wchar_t>);
_M_init_facet(new std::collate<wchar_t>(__cloc));
- _M_init_facet(new moneypunct<wchar_t, false>(__cloc, __s));
- _M_init_facet(new moneypunct<wchar_t, true>(__cloc, __s));
+ _M_init_facet(new moneypunct<wchar_t, false>(__clocm, __smon));
+ _M_init_facet(new moneypunct<wchar_t, true>(__clocm, __smon));
_M_init_facet(new money_get<wchar_t>);
_M_init_facet(new money_put<wchar_t>);
_M_init_facet(new __timepunct<wchar_t>(__cloc, __s));
@@ -248,10 +271,14 @@
_M_init_facet(new std::messages<wchar_t>(__cloc, __s));
#endif
locale::facet::_S_destroy_c_locale(__cloc);
+ if (__clocm != __cloc)
+ locale::facet::_S_destroy_c_locale(__clocm);
}
__catch(...)
{
locale::facet::_S_destroy_c_locale(__cloc);
+ if (__clocm != __cloc)
+ locale::facet::_S_destroy_c_locale(__clocm);
this->~_Impl();
__throw_exception_again;
}
Index: include/bits/locale_classes.h
===================================================================
--- include/bits/locale_classes.h (revision 147710)
+++ include/bits/locale_classes.h (working copy)
@@ -381,6 +381,9 @@
static void
_S_destroy_c_locale(__c_locale& __cloc);
+ static __c_locale
+ _S_lc_ctype_c_locale(__c_locale __cloc, const char* __s);
+
// Returns data from the underlying "C" library data for the
// classic locale.
static __c_locale
Index: testsuite/22_locale/locale/cons/40184.cc
===================================================================
--- testsuite/22_locale/locale/cons/40184.cc (revision 0)
+++ testsuite/22_locale/locale/cons/40184.cc (revision 0)
@@ -0,0 +1,60 @@
+// { dg-require-namedlocale "" }
+
+// Copyright (C) 2009 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 3, 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 COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 22.1.1.2 locale constructors and destructors [lib.locale.cons]
+
+#include <locale>
+#include <testsuite_hooks.h>
+
+// libstdc++/40184
+void test01()
+{
+#ifdef _GLIBCXX_USE_WCHAR_T
+ using namespace std;
+ bool test __attribute__((unused)) = true;
+
+ locale locf(locale("C"), "ja_JP.eucjp", locale::monetary);
+
+ const moneypunct<wchar_t, false>& mpf =
+ use_facet<moneypunct<wchar_t, false> >(locf);
+
+ locale locf_copy(locf.name().c_str());
+ const moneypunct<wchar_t, false>& mpf_copy =
+ use_facet<moneypunct<wchar_t, false> >(locf_copy);
+
+ VERIFY( mpf.curr_symbol() == mpf_copy.curr_symbol() );
+
+ locale loct(locale("C"), "ja_JP.eucjp", locale::monetary);
+
+ const moneypunct<wchar_t, true>& mpt =
+ use_facet<moneypunct<wchar_t, true> >(loct);
+
+ locale loct_copy(loct.name().c_str());
+ const moneypunct<wchar_t, true>& mpt_copy =
+ use_facet<moneypunct<wchar_t, true> >(loct_copy);
+
+ VERIFY( mpt.curr_symbol() == mpt_copy.curr_symbol() );
+#endif
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: config/locale/gnu/c_locale.cc
===================================================================
--- config/locale/gnu/c_locale.cc (revision 147710)
+++ config/locale/gnu/c_locale.cc (working copy)
@@ -133,10 +133,10 @@
{
// This named locale is not supported by the underlying OS.
__throw_runtime_error(__N("locale::facet::_S_create_c_locale "
- "name not valid"));
+ "name not valid"));
}
}
-
+
void
locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
{
@@ -148,6 +148,23 @@
locale::facet::_S_clone_c_locale(__c_locale& __cloc)
{ return __duplocale(__cloc); }
+ __c_locale
+ locale::facet::_S_lc_ctype_c_locale(__c_locale __cloc, const char* __s)
+ {
+ __c_locale __dup = __duplocale(__cloc);
+ if (__dup == __c_locale(0))
+ __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale "
+ "duplocale error"));
+ __c_locale __changed = __newlocale(LC_CTYPE_MASK, __s, __dup);
+ if (__changed == __c_locale(0))
+ {
+ __freelocale(__dup);
+ __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale "
+ "newlocale error"));
+ }
+ return __changed;
+ }
+
_GLIBCXX_END_NAMESPACE
_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
Index: config/locale/generic/c_locale.cc
===================================================================
--- config/locale/generic/c_locale.cc (revision 147710)
+++ config/locale/generic/c_locale.cc (working copy)
@@ -226,6 +226,10 @@
locale::facet::_S_clone_c_locale(__c_locale&)
{ return __c_locale(); }
+ __c_locale
+ locale::facet::_S_lc_ctype_c_locale(__c_locale, const char*)
+ { return __c_locale(); }
+
_GLIBCXX_END_NAMESPACE
_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)