aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2024-01-30 14:48:28 +0000
committerJonathan Wakely <jwakely@redhat.com>2024-05-22 23:10:05 +0100
commit947a9c801e818f412ad4c669a49297c3512b3a6e (patch)
tree5e5b648687959794040c3d605e33aaf410ba5f0a
parentb2fdd508d7e63158e9d2a6dd04f901d02900def3 (diff)
downloadgcc-947a9c801e818f412ad4c669a49297c3512b3a6e.zip
gcc-947a9c801e818f412ad4c669a49297c3512b3a6e.tar.gz
gcc-947a9c801e818f412ad4c669a49297c3512b3a6e.tar.bz2
libstdc++: Fix effects of combining locales [PR108323]
This fixes a bug in locale::combine where we fail to meet the standard's requirement that the result is unnamed. It also implements two library issues related to the names of combined locales (2295 and 3676). libstdc++-v3/ChangeLog: PR libstdc++/108323 * include/bits/locale_classes.tcc (locale(const locale&, Facet*)): Return a copy of the first argument when the facet pointer is null, as per LWG 2295. (locale::combine): Ensure the result is unnamed. * src/c++11/localename.cc (_M_replace_categories): Ignore whether the second locale has a name when cat == none, as per LWG 3676. * src/c++98/locale.cc (_M_install_facet): Use __builtin_expect to predict that the facet pointer is non-null. * testsuite/22_locale/locale/cons/names.cc: New test.
-rw-r--r--libstdc++-v3/include/bits/locale_classes.tcc13
-rw-r--r--libstdc++-v3/src/c++11/localename.cc4
-rw-r--r--libstdc++-v3/src/c++98/locale.cc2
-rw-r--r--libstdc++-v3/testsuite/22_locale/locale/cons/names.cc61
4 files changed, 77 insertions, 3 deletions
diff --git a/libstdc++-v3/include/bits/locale_classes.tcc b/libstdc++-v3/include/bits/locale_classes.tcc
index 6309758..00eeb7d 100644
--- a/libstdc++-v3/include/bits/locale_classes.tcc
+++ b/libstdc++-v3/include/bits/locale_classes.tcc
@@ -44,6 +44,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
locale::
locale(const locale& __other, _Facet* __f)
{
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2295. Locale name when the provided Facet is a nullptr
+ if (__builtin_expect(!__f, 0))
+ {
+ _M_impl = __other._M_impl;
+ _M_impl->_M_add_reference();
+ return;
+ }
+
_M_impl = new _Impl(*__other._M_impl, 1);
__try
@@ -72,6 +81,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__tmp->_M_remove_reference();
__throw_exception_again;
}
+ delete[] __tmp->_M_names[0];
+ __tmp->_M_names[0] = 0; // Unnamed.
return locale(__tmp);
}
@@ -163,7 +174,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
template<typename _Facet>
inline bool
- has_facet(const locale& __loc) throw()
+ has_facet(const locale& __loc) _GLIBCXX_USE_NOEXCEPT
{
#if __cplusplus >= 201103L
static_assert(__is_base_of(locale::facet, _Facet),
diff --git a/libstdc++-v3/src/c++11/localename.cc b/libstdc++-v3/src/c++11/localename.cc
index cde94ec..909cf4c 100644
--- a/libstdc++-v3/src/c++11/localename.cc
+++ b/libstdc++-v3/src/c++11/localename.cc
@@ -326,7 +326,9 @@ const int num_facets = (
_M_replace_categories(const _Impl* __imp, category __cat)
{
category __mask = 1;
- if (!_M_names[0] || !__imp->_M_names[0])
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3676. Name of locale composed using std::locale::none
+ if (!_M_names[0] || (__cat != none && !__imp->_M_names[0]))
{
if (_M_names[0])
{
diff --git a/libstdc++-v3/src/c++98/locale.cc b/libstdc++-v3/src/c++98/locale.cc
index 3749408..0e7533e 100644
--- a/libstdc++-v3/src/c++98/locale.cc
+++ b/libstdc++-v3/src/c++98/locale.cc
@@ -323,7 +323,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
locale::_Impl::
_M_install_facet(const locale::id* __idp, const facet* __fp)
{
- if (__fp)
+ if (__builtin_expect(__fp != 0, 1))
{
size_t __index = __idp->_M_id();
diff --git a/libstdc++-v3/testsuite/22_locale/locale/cons/names.cc b/libstdc++-v3/testsuite/22_locale/locale/cons/names.cc
new file mode 100644
index 0000000..2a9cfe4
--- /dev/null
+++ b/libstdc++-v3/testsuite/22_locale/locale/cons/names.cc
@@ -0,0 +1,61 @@
+// { dg-do run }
+
+#include <locale>
+#include <testsuite_hooks.h>
+
+void
+test_pr108323()
+{
+ std::locale named = std::locale::classic();
+ std::locale unnamed = named.combine<std::ctype<char> >(named);
+
+ // Bug libstdc++/108323 - combine does not change the locale name
+ VERIFY( unnamed.name() == "*" );
+}
+
+void
+test_lwg2295()
+{
+ std::locale named = std::locale::classic();
+ std::locale unnamed(named, &std::use_facet<std::ctype<char> >(named));
+ VERIFY( unnamed.name() == "*" );
+
+ // LWG 2295. Locale name when the provided Facet is a nullptr
+ std::locale loc(named, (std::ctype<char>*)0);
+ VERIFY( loc.name() != "*" );
+ VERIFY( loc.name() == named.name() );
+}
+
+void
+test_lwg3676()
+{
+ std::locale named = std::locale::classic();
+ std::locale unnamed = named.combine<std::ctype<char> >(named);
+ std::locale combo;
+
+ // LWG 3676. Name of locale composed using std::locale::none
+
+ combo = std::locale(named, named, std::locale::numeric);
+ VERIFY( combo.name() != "*" );
+ combo = std::locale(named, named, std::locale::none);
+ VERIFY( combo.name() != "*" );
+ combo = std::locale(named, unnamed, std::locale::numeric);
+ VERIFY( combo.name() == "*" );
+ combo = std::locale(named, unnamed, std::locale::none);
+ VERIFY( combo.name() != "*" );
+ combo = std::locale(unnamed, named, std::locale::numeric);
+ VERIFY( combo.name() == "*" );
+ combo = std::locale(unnamed, named, std::locale::none);
+ VERIFY( combo.name() == "*" );
+ combo = std::locale(unnamed, unnamed, std::locale::numeric);
+ VERIFY( combo.name() == "*" );
+ combo = std::locale(unnamed, unnamed, std::locale::none);
+ VERIFY( combo.name() == "*" );
+}
+
+int main()
+{
+ test_pr108323();
+ test_lwg2295();
+ test_lwg3676();
+}