From dd9a67384e47508111fa7623991d14f01227c114 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Chigot?= <clement.chigot@atos.net>
Date: Tue, 29 Dec 2020 11:08:33 +0100
Subject: [PATCH] libstdc++: implement locale support for XPG7
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Create a new locale model for POSIX operating systems.
The implementation is based on dragonfly one.

There are few known limitations.
std::messages isn't implemented.
Creation std::locale with a string describing each LC_* category
isn't possible (eg std::locale("LC_CTYPE=en_US.UTF-8;LC_NUMERIC=C;...")

libstdc++-v3/ChangeLog:
2020-01-25  Clément Chigot  <clement.chigot@atos.net>

	* acinclude.m4: Add XPG7 model.
	* config.h.in: Regenerate.
	* configure: Regenerate.
	* config/locale/dragonfly/c_locale.cc: Rename to ...
	* config/locale/xpg7/c_locale.cc: ... here.
	* config/locale/dragonfly/c_locale.h: Rename to ...
	* config/locale/xpg7/c_locale.h: ... here.
	(_GLIBCXX_C_LOCALE_XPG7): New define.
	(strtof_l): New function if not provided by the system.
	(strtod_l): Likewise.
	(strtold_l): Likewise.
	* config/locale/dragonfly/ctype_members.cc: Rename to ...
	* config/locale/xpg7/ctype_members.cc: ... here.
	* config/locale/dragonfly/monetary_members.cc: Rename to ...
	* config/locale/xpg7/monetary_members.cc: ... here.
	* config/locale/dragonfly/numeric_members.cc: Rename to ...
	* config/locale/xpg7/numeric_members.cc: ... here.
	* config/locale/dragonfly/time_members.cc: Rename to ...
	* config/locale/xpg7/time_members.cc: ... here.
	* config/os/aix/ctype_configure_char.cc (ctype<char>::ctype):
	Add support for XPG7 model.
	* config/os/solaris/ctype_configure_char.cc (ctype<char>::ctype):
	Likewise.
	* config/os/gnu-linux/ctype_configure_char.cc: Likewise.
	* src/c++98/locale_init.cc (locale::global): Call setlocale
	for each category instead of once when not using gnu model.
	* testsuite/22_locale/codecvt/in/wchar_t/2.cc: Add xfail for
	wchar_t on 16bit.
	* testsuite/22_locale/codecvt/in/wchar_t/3.cc: Likewise.
	* testsuite/22_locale/codecvt/in/wchar_t/4.cc: Likewise.
	* testsuite/22_locale/codecvt/in/wchar_t/7.cc: Likewise.
	* testsuite/22_locale/codecvt/in/wchar_t/8.cc: Likewise.
	* testsuite/22_locale/codecvt/in/wchar_t/9.cc: Likewise.
	* testsuite/22_locale/codecvt/length/wchar_t/4.cc: Likewise.
	* testsuite/22_locale/codecvt/out/wchar_t/4.cc: Likewise.
	* testsuite/22_locale/codecvt/unshift/wchar_t/4.cc: Likewise.
	* testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-1.cc:
	Likewise.
	* testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-2.cc:
	Likewise.
	* testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-3.cc:
	Likewise.
	* testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-4.cc:
	Likewise.
	* testsuite/22_locale/ctype/is/wchar_t/2.cc: Remove xfail
	with xpg7 model.
	* testsuite/22_locale/locale/cons/29217.cc: Add skip when not
	using gnu model.
	* testsuite/22_locale/locale/cons/38368.cc: Likewise.
	* testsuite/22_locale/locale/cons/40184.cc: Likewise.
	* testsuite/22_locale/locale/cons/5.cc: Likewise.
	* testsuite/22_locale/locale/global_locale_objects/14071.cc:
	Likewise.
	* testsuite/22_locale/messages/13631.cc: Likewise.
	* testsuite/22_locale/messages/members/char/1.cc: Likewise.
	* testsuite/22_locale/messages/members/char/2.cc: Likewise.
	* testsuite/22_locale/messages/members/char/3.cc: Likewise.
	* testsuite/22_locale/messages/members/char/wrapped_env.cc:
	Likewise.
	* testsuite/22_locale/messages/members/char/wrapped_locale.cc:
	Likewise.
	* testsuite/22_locale/messages_byname/named_equivalence.cc:
	Likewise.
	* testsuite/lib/dg-options.exp (dg-require-localemodel): New.
	* testsuite/lib/libstdc++.exp (check_v3_target_namedlocale): Add
	AIX support.
	(check_v3_target_localemodel): New.
	* testsuite/util/testsuite_hooks.h (ISO_8859): Add AIX support.
---
 libstdc++-v3/acinclude.m4                     | 46 +++++++------
 libstdc++-v3/config.h.in                      | 15 ++++
 .../locale/{dragonfly => xpg7}/c_locale.cc    |  6 +-
 .../locale/{dragonfly => xpg7}/c_locale.h     | 46 ++++++++++++-
 .../{dragonfly => xpg7}/codecvt_members.cc    |  2 +-
 .../{dragonfly => xpg7}/collate_members.cc    |  2 +-
 .../{dragonfly => xpg7}/ctype_members.cc      | 69 +++++++++++++++++--
 .../{dragonfly => xpg7}/monetary_members.cc   | 45 +++++++++++-
 .../{dragonfly => xpg7}/numeric_members.cc    | 28 +++++++-
 .../{dragonfly => xpg7}/time_members.cc       | 34 ++++++++-
 .../locale/{dragonfly => xpg7}/time_members.h |  2 +-
 .../config/os/aix/ctype_configure_char.cc     | 38 +++++-----
 .../os/gnu-linux/ctype_configure_char.cc      |  6 +-
 .../config/os/solaris/ctype_configure_char.cc | 18 ++---
 libstdc++-v3/src/c++98/locale_init.cc         | 12 ++++
 .../22_locale/codecvt/in/wchar_t/2.cc         |  1 +
 .../22_locale/codecvt/in/wchar_t/3.cc         |  1 +
 .../22_locale/codecvt/in/wchar_t/4.cc         |  1 +
 .../22_locale/codecvt/in/wchar_t/7.cc         |  1 +
 .../22_locale/codecvt/in/wchar_t/8.cc         |  1 +
 .../22_locale/codecvt/in/wchar_t/9.cc         |  1 +
 .../22_locale/codecvt/length/wchar_t/4.cc     |  1 +
 .../22_locale/codecvt/out/wchar_t/4.cc        |  1 +
 .../22_locale/codecvt/unshift/wchar_t/4.cc    |  1 +
 .../testsuite/22_locale/ctype/is/wchar_t/2.cc |  2 +-
 .../testsuite/22_locale/locale/cons/29217.cc  |  1 +
 .../testsuite/22_locale/locale/cons/38368.cc  |  1 +
 .../testsuite/22_locale/locale/cons/40184.cc  |  1 +
 .../testsuite/22_locale/locale/cons/5.cc      |  1 +
 .../locale/global_locale_objects/14071.cc     |  1 +
 .../testsuite/22_locale/messages/13631.cc     |  1 +
 .../22_locale/messages/members/char/1.cc      |  1 +
 .../22_locale/messages/members/char/2.cc      |  1 +
 .../22_locale/messages/members/char/3.cc      |  1 +
 .../messages/members/char/wrapped_env.cc      |  1 +
 .../messages/members/char/wrapped_locale.cc   |  1 +
 .../messages_byname/named_equivalence.cc      |  1 +
 .../basic_filebuf/overflow/wchar_t/11305-1.cc |  1 +
 .../basic_filebuf/overflow/wchar_t/11305-2.cc |  1 +
 .../basic_filebuf/overflow/wchar_t/11305-3.cc |  1 +
 .../basic_filebuf/overflow/wchar_t/11305-4.cc |  1 +
 libstdc++-v3/testsuite/lib/dg-options.exp     |  9 +++
 libstdc++-v3/testsuite/lib/libstdc++.exp      | 31 +++++++++
 libstdc++-v3/testsuite/util/testsuite_hooks.h |  3 +
 44 files changed, 370 insertions(+), 69 deletions(-)
 rename libstdc++-v3/config/locale/{dragonfly => xpg7}/c_locale.cc (97%)
 rename libstdc++-v3/config/locale/{dragonfly => xpg7}/c_locale.h (69%)
 rename libstdc++-v3/config/locale/{dragonfly => xpg7}/codecvt_members.cc (99%)
 rename libstdc++-v3/config/locale/{dragonfly => xpg7}/collate_members.cc (97%)
 rename libstdc++-v3/config/locale/{dragonfly => xpg7}/ctype_members.cc (78%)
 rename libstdc++-v3/config/locale/{dragonfly => xpg7}/monetary_members.cc (95%)
 rename libstdc++-v3/config/locale/{dragonfly => xpg7}/numeric_members.cc (90%)
 rename libstdc++-v3/config/locale/{dragonfly => xpg7}/time_members.cc (92%)
 rename libstdc++-v3/config/locale/{dragonfly => xpg7}/time_members.h (97%)

diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 90ecc4a87a2..8b6a7d612f7 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -2364,7 +2364,7 @@ dnl
 AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
   GLIBCXX_ENABLE(clocale,auto,[[[=MODEL]]],
     [use MODEL for target locale package],
-    [permit generic|gnu|ieee_1003.1-2001|newlib|yes|no|auto])
+    [permit generic|gnu|ieee_1003.1-2001|newlib|xpg7|yes|no|auto])
 
   # Deal with gettext issues.  Default to not using it (=no) until we detect
   # support for it later.  Let the user turn it off via --e/d, but let that
@@ -2394,8 +2394,8 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
       vxworks*)
 	enable_clocale_flag=vxworks
 	;;
-      dragonfly* | freebsd*)
-	enable_clocale_flag=dragonfly
+      aix* | dragonfly* | freebsd*)
+	enable_clocale_flag=xpg7
 	;;
       openbsd*)
 	enable_clocale_flag=newlib
@@ -2504,23 +2504,6 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
       CTIME_CC=config/locale/generic/time_members.cc
       CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
       ;;
-    dragonfly)
-      AC_MSG_RESULT(dragonfly or freebsd)
-
-      CLOCALE_H=config/locale/dragonfly/c_locale.h
-      CLOCALE_CC=config/locale/dragonfly/c_locale.cc
-      CCODECVT_CC=config/locale/dragonfly/codecvt_members.cc
-      CCOLLATE_CC=config/locale/dragonfly/collate_members.cc
-      CCTYPE_CC=config/locale/dragonfly/ctype_members.cc
-      CMESSAGES_H=config/locale/generic/messages_members.h
-      CMESSAGES_CC=config/locale/generic/messages_members.cc
-      CMONEY_CC=config/locale/dragonfly/monetary_members.cc
-      CNUMERIC_CC=config/locale/dragonfly/numeric_members.cc
-      CTIME_H=config/locale/dragonfly/time_members.h
-      CTIME_CC=config/locale/dragonfly/time_members.cc
-      CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
-      ;;
-
     gnu)
       AC_MSG_RESULT(gnu)
 
@@ -2571,6 +2554,23 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
       CTIME_CC=config/locale/generic/time_members.cc
       CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
       ;;
+    xpg7)
+      AC_MSG_RESULT(xpg7)
+
+      CLOCALE_H=config/locale/xpg7/c_locale.h
+      CLOCALE_CC=config/locale/xpg7/c_locale.cc
+      CCODECVT_CC=config/locale/xpg7/codecvt_members.cc
+      CCOLLATE_CC=config/locale/xpg7/collate_members.cc
+      CCTYPE_CC=config/locale/xpg7/ctype_members.cc
+      CMESSAGES_H=config/locale/generic/messages_members.h
+      CMESSAGES_CC=config/locale/generic/messages_members.cc
+      CMONEY_CC=config/locale/xpg7/monetary_members.cc
+      CNUMERIC_CC=config/locale/xpg7/numeric_members.cc
+      CTIME_H=config/locale/xpg7/time_members.h
+      CTIME_CC=config/locale/xpg7/time_members.cc
+      CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+      ;;
+
     newlib)
       AC_MSG_RESULT(newlib)
 
@@ -2617,6 +2617,12 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
   AC_SUBST(CTIME_CC)
   AC_SUBST(CLOCALE_CC)
   AC_SUBST(CLOCALE_INTERNAL_H)
+
+  if test $enable_clocale_flag = xpg7; then
+     AC_CHECK_HEADERS(xlocale.h)
+
+     AC_CHECK_FUNCS([strtof_l localeconv_l mbstowcs_l wcsftime_l strftime_l])
+  fi
 ])
 
 
diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in
index e545488386a..36a6fc97fdf 100644
--- a/libstdc++-v3/config.h.in
+++ b/libstdc++-v3/config.h.in
@@ -216,6 +216,9 @@
 /* Define to 1 if you have the <linux/types.h> header file. */
 #undef HAVE_LINUX_TYPES_H
 
+/* Define to 1 if you have the `localeconv_l' function. */
+#undef HAVE_LOCALECONV_L
+
 /* Define to 1 if you have the <locale.h> header file. */
 #undef HAVE_LOCALE_H
 
@@ -240,6 +243,9 @@
 /* Define if mbstate_t exists in wchar.h. */
 #undef HAVE_MBSTATE_T
 
+/* Define to 1 if you have the `mbstowcs_l' function. */
+#undef HAVE_MBSTOWCS_L
+
 /* Define to 1 if you have the `memalign' function. */
 #undef HAVE_MEMALIGN
 
@@ -355,6 +361,9 @@
 /* Define if strerror_r is available in <string.h>. */
 #undef HAVE_STRERROR_R
 
+/* Define to 1 if you have the `strftime_l' function. */
+#undef HAVE_STRFTIME_L
+
 /* Define to 1 if you have the <strings.h> header file. */
 #undef HAVE_STRINGS_H
 
@@ -364,6 +373,9 @@
 /* Define to 1 if you have the `strtof' function. */
 #undef HAVE_STRTOF
 
+/* Define to 1 if you have the `strtof_l' function. */
+#undef HAVE_STRTOF_L
+
 /* Define to 1 if you have the `strtold' function. */
 #undef HAVE_STRTOLD
 
@@ -485,6 +497,9 @@
 /* Define to 1 if you have the <wchar.h> header file. */
 #undef HAVE_WCHAR_H
 
+/* Define to 1 if you have the `wcsftime_l' function. */
+#undef HAVE_WCSFTIME_L
+
 /* Defined if wcstof exists. */
 #undef HAVE_WCSTOF
 
diff --git a/libstdc++-v3/config/locale/dragonfly/c_locale.cc b/libstdc++-v3/config/locale/xpg7/c_locale.cc
similarity index 97%
rename from libstdc++-v3/config/locale/dragonfly/c_locale.cc
rename to libstdc++-v3/config/locale/xpg7/c_locale.cc
index 02df4605bb5..39ef58ea0a9 100644
--- a/libstdc++-v3/config/locale/dragonfly/c_locale.cc
+++ b/libstdc++-v3/config/locale/xpg7/c_locale.cc
@@ -1,4 +1,4 @@
-// localization implementation details, DragonFly version -*- C++ -*-
+// localization implementation details, XPG7 version -*- C++ -*-
 
 // Copyright (C) 2014-2021 Free Software Foundation, Inc.
 //
@@ -28,13 +28,17 @@
 
 // Written by Benjamin Kosnik <bkoz@redhat.com>
 // Modified for DragonFly by John Marino <gnugcc@marino.st>
+// Modified for XPG7 by Clément Chigot <clement.chigot@atos.net>
 
 #include <cstdlib>
 #include <locale>
 #include <stdexcept>
 #include <limits>
+
 #include <langinfo.h>
+#ifdef _GLIBCXX_HAVE_XLOCALE_H
 #include <xlocale.h>
+#endif
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
diff --git a/libstdc++-v3/config/locale/dragonfly/c_locale.h b/libstdc++-v3/config/locale/xpg7/c_locale.h
similarity index 69%
rename from libstdc++-v3/config/locale/dragonfly/c_locale.h
rename to libstdc++-v3/config/locale/xpg7/c_locale.h
index cf4281cebbf..e030a3368d1 100644
--- a/libstdc++-v3/config/locale/dragonfly/c_locale.h
+++ b/libstdc++-v3/config/locale/xpg7/c_locale.h
@@ -1,4 +1,4 @@
-// localization implementation details, DragonFly version -*- C++ -*-
+// localization implementation details, XPG7 version -*- C++ -*-
 
 // Copyright (C) 2001-2021 Free Software Foundation, Inc.
 //
@@ -33,6 +33,7 @@
 
 // Written by Benjamin Kosnik <bkoz@redhat.com>
 // Modified for DragonFly by John Marino <gnugcc@marino.st>
+// Modified for XPG7 by Clément Chigot <clement.chigot@atos.net>
 
 #ifndef _GLIBCXX_CXX_LOCALE_H
 #define _GLIBCXX_CXX_LOCALE_H 1
@@ -40,7 +41,46 @@
 #pragma GCC system_header
 
 #include <clocale>
+#include <cstdlib>
+#ifdef _GLIBCXX_HAVE_XLOCALE_H
 #include <xlocale.h>
+#endif
+
+#define _GLIBCXX_C_LOCALE_XPG7 1
+
+// Assume that if strtof_l is missing then strtod_l and strold_l
+// are missing too.
+#ifndef _GLIBCXX_HAVE_STRTOF_L
+extern "C" inline
+float strtof_l (const char *__nptr, char **__endptr,
+		locale_t locale)
+{
+  locale_t __old = uselocale(locale);
+  float __res = strtof(__nptr, __endptr);
+  uselocale(__old);
+  return __res;
+}
+
+extern "C" inline
+double strtod_l (const char *__nptr, char **__endptr,
+		 locale_t locale)
+{
+  locale_t __old = uselocale(locale);
+  double __res = strtod(__nptr, __endptr);
+  uselocale(__old);
+  return __res;
+}
+
+extern "C" inline
+long double strtold_l (const char *__nptr, char **__endptr,
+		       locale_t locale)
+{
+  locale_t __old = uselocale(locale);
+  long double __res = strtold(__nptr, __endptr);
+  uselocale(__old);
+  return __res;
+}
+#endif
 
 #define _GLIBCXX_NUM_CATEGORIES 0
 
@@ -48,7 +88,11 @@ namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
+#if defined(__DragonFly__) || defined(__FreeBSD__)
   typedef int*			__c_locale;
+#else
+  typedef locale_t			__c_locale;
+#endif
 
   // Convert numeric value of type double and long double to string and
   // return length of string.  If vsnprintf is available use it, otherwise
diff --git a/libstdc++-v3/config/locale/dragonfly/codecvt_members.cc b/libstdc++-v3/config/locale/xpg7/codecvt_members.cc
similarity index 99%
rename from libstdc++-v3/config/locale/dragonfly/codecvt_members.cc
rename to libstdc++-v3/config/locale/xpg7/codecvt_members.cc
index 11cbcdae59f..3ce047a0851 100644
--- a/libstdc++-v3/config/locale/dragonfly/codecvt_members.cc
+++ b/libstdc++-v3/config/locale/xpg7/codecvt_members.cc
@@ -1,4 +1,4 @@
-// std::codecvt implementation details, DragonFly version -*- C++ -*-
+// std::codecvt implementation details, XPG7 version -*- C++ -*-
 
 // Copyright (C) 2015-2021 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/config/locale/dragonfly/collate_members.cc b/libstdc++-v3/config/locale/xpg7/collate_members.cc
similarity index 97%
rename from libstdc++-v3/config/locale/dragonfly/collate_members.cc
rename to libstdc++-v3/config/locale/xpg7/collate_members.cc
index 64c7d864a61..9a586ce7599 100644
--- a/libstdc++-v3/config/locale/dragonfly/collate_members.cc
+++ b/libstdc++-v3/config/locale/xpg7/collate_members.cc
@@ -1,4 +1,4 @@
-// std::collate implementation details, DragonFly version -*- C++ -*-
+// std::collate implementation details, XPG7 version -*- C++ -*-
 
 // Copyright (C) 2015-2021 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/config/locale/dragonfly/ctype_members.cc b/libstdc++-v3/config/locale/xpg7/ctype_members.cc
similarity index 78%
rename from libstdc++-v3/config/locale/dragonfly/ctype_members.cc
rename to libstdc++-v3/config/locale/xpg7/ctype_members.cc
index 420cb51e07a..a87a603fa27 100644
--- a/libstdc++-v3/config/locale/dragonfly/ctype_members.cc
+++ b/libstdc++-v3/config/locale/xpg7/ctype_members.cc
@@ -1,4 +1,4 @@
-// std::ctype implementation details, DragonFly version -*- C++ -*-
+// std::ctype implementation details, XPG7 version -*- C++ -*-
 
 // Copyright (C) 2014-2021 Free Software Foundation, Inc.
 //
@@ -28,13 +28,18 @@
 
 // Written by Benjamin Kosnik <bkoz@redhat.com>
 // Modified for DragonFly by John Marino <gnugcc@marino.st>
+// Modified for XPG7 by Clément Chigot <clement.chigot@atos.net>
 
 #include <locale>
 #include <cstring>
 #include <cstdio>
 
 #ifndef _ISbit
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 #define _ISbit(bit) ((bit) < 8 ? ((1 << (bit)) << 8) : ((1 << (bit)) >> 8))
+#else
+#define _ISbit(bit) (1 << bit)
+#endif
 #endif
 
 namespace std _GLIBCXX_VISIBILITY(default)
@@ -114,8 +119,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   {
     while (__lo < __hi)
       {
-        *__lo = towupper_l(*__lo, (locale_t)_M_c_locale_ctype);
-        ++__lo;
+	*__lo = towupper_l(*__lo, (locale_t)_M_c_locale_ctype);
+	++__lo;
       }
     return __hi;
   }
@@ -129,12 +134,64 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   {
     while (__lo < __hi)
       {
-        *__lo = towlower_l(*__lo, (locale_t)_M_c_locale_ctype);
-        ++__lo;
+	*__lo = towlower_l(*__lo, (locale_t)_M_c_locale_ctype);
+	++__lo;
+      }
+    return __hi;
+  }
+
+#if !defined(__DragonFly__) && !defined(__FreeBSD__)
+  bool
+  ctype<wchar_t>::
+  do_is(mask __m, char_type __c) const
+  {
+    bool __ret = false;
+    const size_t __bitmasksize = 15;
+    for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
+      if (__m & _M_bit[__bitcur]
+	  && iswctype_l(__c, _M_wmask[__bitcur], (locale_t)_M_c_locale_ctype))
+	{
+	  __ret = true;
+	  break;
+	}
+    return __ret;
+  }
+
+  const wchar_t*
+  ctype<wchar_t>::
+  do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __vec) const
+  {
+    for (;__lo < __hi; ++__vec, ++__lo)
+      {
+	const size_t __bitmasksize = 15;
+	mask __m = 0;
+	for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
+	  if (iswctype_l(*__lo, _M_wmask[__bitcur], (locale_t)_M_c_locale_ctype))
+	    __m |= _M_bit[__bitcur];
+	*__vec = __m;
       }
     return __hi;
   }
 
+  const wchar_t*
+  ctype<wchar_t>::
+  do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const
+  {
+    while (__lo < __hi && !this->do_is(__m, *__lo))
+      ++__lo;
+    return __lo;
+  }
+
+  const wchar_t*
+  ctype<wchar_t>::
+  do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const
+  {
+    while (__lo < __hi && this->do_is(__m, *__lo) != 0)
+      ++__lo;
+    return __lo;
+  }
+#endif
+
   wchar_t
   ctype<wchar_t>::
   do_widen(char __c) const
@@ -217,7 +274,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	 __j < sizeof(_M_widen) / sizeof(wint_t); ++__j)
       _M_widen[__j] = btowc(__j);
 
-    for (size_t __k = 0; __k <= 11; ++__k)
+    for (size_t __k = 0; __k <= 15; ++__k)
       {
 	_M_bit[__k] = static_cast<mask>(_ISbit(__k));
 	_M_wmask[__k] = _M_convert_to_wmask(_M_bit[__k]);
diff --git a/libstdc++-v3/config/locale/dragonfly/monetary_members.cc b/libstdc++-v3/config/locale/xpg7/monetary_members.cc
similarity index 95%
rename from libstdc++-v3/config/locale/dragonfly/monetary_members.cc
rename to libstdc++-v3/config/locale/xpg7/monetary_members.cc
index e1decc61cbf..4dc35633fd2 100644
--- a/libstdc++-v3/config/locale/dragonfly/monetary_members.cc
+++ b/libstdc++-v3/config/locale/xpg7/monetary_members.cc
@@ -1,4 +1,4 @@
-// std::moneypunct implementation details, DragonFly version -*- C++ -*-
+// std::moneypunct implementation details, XPG7 version -*- C++ -*-
 
 // Copyright (C) 2015-2021 Free Software Foundation, Inc.
 //
@@ -28,10 +28,17 @@
 
 // Written by Benjamin Kosnik <bkoz@redhat.com>
 // Modified for DragonFly by John Marino <gnugcc@marino.st>
+// Modified for XPG7 by Clément Chigot <clement.chigot@atos.net>
 
+// Solaris 11.4 doesn't make C99 members of struct lconv visible for C++11
+// without this.
+#define _LCONV_C99
 #include <locale>
 #include <cstring>
+
+#ifdef _GLIBCXX_HAVE_XLOCALE_H
 #include <xlocale.h>
+#endif
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -241,7 +248,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       else
 	{
 	  // Named locale.
+#ifdef _GLIBCXX_HAVE_LOCALECONV_L
 	  lconv* lc = localeconv_l((locale_t) __cloc);
+#else
+	  __c_locale __old = uselocale(__cloc);
+	  lconv* lc = localeconv();
+#endif
 
 	  // Check for NULL, which implies no fractional digits.
 	  if (lc->mon_decimal_point == NULL ||
@@ -348,6 +360,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	      delete [] __group;
 	      delete [] __ps;
 	      delete [] __ns;
+#ifndef _GLIBCXX_HAVE_LOCALECONV_L
+	      uselocale(__old);
+#endif
 	      __throw_exception_again;
 	    }
 
@@ -360,6 +375,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  char __nspace = lc->int_n_sep_by_space;
 	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
 							__nposn);
+#ifndef _GLIBCXX_HAVE_LOCALECONV_L
+	  uselocale(__old);
+#endif
 	}
     }
 
@@ -395,7 +413,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       else
 	{
 	  // Named locale.
+#ifdef _GLIBCXX_HAVE_LOCALECONV_L
 	  lconv* lc = localeconv_l((locale_t) __cloc);
+#else
+	  __c_locale __old = uselocale(__cloc);
+	  lconv* lc = localeconv();
+#endif
 
 	  // Check for NULL, which implies no fractional digits.
 	  if (lc->mon_decimal_point == NULL ||
@@ -502,6 +525,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	      delete [] __group;
 	      delete [] __ps;
 	      delete [] __ns;
+#ifndef _GLIBCXX_HAVE_LOCALECONV_L
+	      uselocale(__old);
+#endif
 	      __throw_exception_again;
 	    }
 
@@ -514,6 +540,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  char __nspace = lc->n_sep_by_space;
 	  _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
 							__nposn);
+#ifndef _GLIBCXX_HAVE_LOCALECONV_L
+	  uselocale(__old);
+#endif
 	}
     }
 
@@ -581,9 +610,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	}
       else
 	{
-	  __c_locale __old = (__c_locale)uselocale((locale_t)__cloc);
 	  // Named locale.
+	  // uselocale is needed for mbsrtowcs.
+	  __c_locale __old = (__c_locale)uselocale((locale_t)__cloc);
+#ifdef _GLIBCXX_HAVE_LOCALECONV_L
 	  lconv* lc = localeconv_l((locale_t) __cloc);
+#else
+	  lconv* lc = localeconv();
+#endif
 
 	  // Check for NULL, which implies no fractional digits.
 	  if (lc->mon_decimal_point == NULL ||
@@ -741,9 +775,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	}
       else
 	{
-	  __c_locale __old = (__c_locale)uselocale((locale_t)__cloc);
 	  // Named locale.
+	  // uselocale is needed for mbsrtowcs.
+	  __c_locale __old = (__c_locale)uselocale((locale_t)__cloc);
+#ifdef _GLIBCXX_HAVE_LOCALECONV_L
 	  lconv* lc = localeconv_l((locale_t) __cloc);
+#else
+	  lconv* lc = localeconv();
+#endif
 
 	  // Check for NULL, which implies no fractional digits.
 	  if (lc->mon_decimal_point == NULL ||
diff --git a/libstdc++-v3/config/locale/dragonfly/numeric_members.cc b/libstdc++-v3/config/locale/xpg7/numeric_members.cc
similarity index 90%
rename from libstdc++-v3/config/locale/dragonfly/numeric_members.cc
rename to libstdc++-v3/config/locale/xpg7/numeric_members.cc
index cac6fe8c710..5ee61f0fbb4 100644
--- a/libstdc++-v3/config/locale/dragonfly/numeric_members.cc
+++ b/libstdc++-v3/config/locale/xpg7/numeric_members.cc
@@ -1,4 +1,4 @@
-// std::numpunct implementation details, DragonFly version -*- C++ -*-
+// std::numpunct implementation details, XPG7 version -*- C++ -*-
 
 // Copyright (C) 2015-2021 Free Software Foundation, Inc.
 //
@@ -28,10 +28,14 @@
 
 // Written by Benjamin Kosnik <bkoz@redhat.com>
 // Modified for DragonFly by John Marino <gnugcc@marino.st>
+// Modified for XPG7 by Clément Chigot <clement.chigot@atos.net>
 
 #include <locale>
 #include <cstring>
+
+#ifdef _GLIBCXX_HAVE_XLOCALE_H
 #include <xlocale.h>
+#endif
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -63,7 +67,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       else
 	{
 	  // Named locale.
+#ifdef _GLIBCXX_HAVE_LOCALECONV_L
 	  lconv* lc = localeconv_l((locale_t) __cloc);
+#else
+	  __c_locale __old = uselocale(__cloc);
+	  lconv* lc = localeconv();
+#endif
 
 	  // Decimal point should always be defined, but check null anyway
 	  if (lc->decimal_point == NULL)
@@ -103,6 +112,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		    {
 		      delete _M_data;
 		      _M_data = 0;
+#ifndef _GLIBCXX_HAVE_LOCALECONV_L
+		      uselocale(__old);
+#endif
 		      __throw_exception_again;
 		    }
 		}
@@ -113,6 +125,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		}
 	      _M_data->_M_grouping_size = __len;
 	    }
+#ifndef _GLIBCXX_HAVE_LOCALECONV_L
+	  uselocale(__old);
+#endif
 	}
 
       // NB: There is no way to extact this info from posix locales.
@@ -162,7 +177,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       else
 	{
 	  // Named locale.
+#ifdef _GLIBCXX_HAVE_LOCALECONV_L
 	  lconv* lc = localeconv_l((locale_t) __cloc);
+#else
+	  __c_locale __old = uselocale(__cloc);
+	  lconv* lc = localeconv();
+#endif
 
 	  // Decimal point should always be defined, but check null anyway
 	  if (lc->decimal_point == NULL)
@@ -201,6 +221,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		    {
 		      delete _M_data;
 		      _M_data = 0;
+#ifndef _GLIBCXX_HAVE_LOCALECONV_L
+		      uselocale(__old);
+#endif
 		      __throw_exception_again;
 		    }
 		}
@@ -211,6 +234,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		}
 	      _M_data->_M_grouping_size = __len;
 	    }
+#ifndef _GLIBCXX_HAVE_LOCALECONV_L
+	  uselocale(__old);
+#endif
 	}
 
       // NB: There is no way to extact this info from posix locales.
diff --git a/libstdc++-v3/config/locale/dragonfly/time_members.cc b/libstdc++-v3/config/locale/xpg7/time_members.cc
similarity index 92%
rename from libstdc++-v3/config/locale/dragonfly/time_members.cc
rename to libstdc++-v3/config/locale/xpg7/time_members.cc
index c8b621a323f..fb287332c44 100644
--- a/libstdc++-v3/config/locale/dragonfly/time_members.cc
+++ b/libstdc++-v3/config/locale/xpg7/time_members.cc
@@ -1,4 +1,4 @@
-// std::time_get, std::time_put implementation, DragonFly version -*- C++ -*-
+// std::time_get, std::time_put implementation, XPG7 version -*- C++ -*-
 
 // Copyright (C) 2001-2021 Free Software Foundation, Inc.
 //
@@ -29,13 +29,17 @@
 
 // Written by Benjamin Kosnik <bkoz@redhat.com>
 // Modified for DragonFly by John Marino <gnugcc@marino.st>
+// Modified for XPG7 by Clément Chigot <clement.chigot@atos.net>
 
 #include <locale>
 #include <ctime>
 #include <cwchar>
 #include <stdlib.h>
 #include <langinfo.h>
+
+#ifdef _GLIBCXX_HAVE_XLOCALE_H
 #include <xlocale.h>
+#endif
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -47,8 +51,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _M_put(char* __s, size_t __maxlen, const char* __format,
 	   const tm* __tm) const throw()
     {
+#ifdef _GLIBCXX_HAVE_STRFTIME_L
       const size_t __len = strftime_l(__s, __maxlen, __format, __tm,
 				      (locale_t)_M_c_locale_timepunct);
+#else
+      __c_locale __old = uselocale(_M_c_locale_timepunct);
+      const size_t __len = strftime(__s, __maxlen, __format, __tm);
+      uselocale(__old);
+#endif
       // Make sure __s is null terminated.
       if (__len == 0)
 	__s[0] = '\0';
@@ -196,15 +206,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _M_put(wchar_t* __s, size_t __maxlen, const wchar_t* __format,
 	   const tm* __tm) const throw()
     {
+#ifdef _GLIBCXX_HAVE_WCSFTIME_L
       const size_t __len = wcsftime_l(__s, __maxlen, __format, __tm,
 				      (locale_t)_M_c_locale_timepunct);
+#else
+      __c_locale __old = uselocale(_M_c_locale_timepunct);
+      const size_t __len = wcsftime(__s, __maxlen, __format, __tm);
+      uselocale(__old);
+#endif
       // Make sure __s is null terminated.
       if (__len == 0)
 	__s[0] = L'\0';
     }
 
+#ifdef _GLIBCXX_HAVE_MBSTOWCS_L
+#define MBSTOWCS_L(WCSTRING, STRING, NUMBER, LOCALE)	\
+  mbstowcs_l (WCSTRING, STRING, NUMBER, LOCALE);
+#else
+  // "uselocale" must be called before using this macro.
+#define MBSTOWCS_L(WCSTRING, STRING, NUMBER, LOCALE)	\
+  mbstowcs (WCSTRING, STRING, NUMBER);
+#endif
 #define WIDE_LANGINFO(M,FMT) \
-	fmtlen = mbstowcs_l (holder, nl_langinfo_l(FMT, (locale_t)__cloc), \
+	fmtlen = MBSTOWCS_L (holder, nl_langinfo_l(FMT, (locale_t)__cloc), \
 		128, (locale_t)__cloc); \
 	langstring = new wchar_t[fmtlen + 1]; \
 	wcsncpy (langstring, holder, fmtlen); \
@@ -281,6 +305,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	}
       else
 	{
+#ifndef _GLIBCXX_HAVE_MBSTOWCS_L
+	  __c_locale __old = uselocale(__cloc);
+#endif
 	  wchar_t *langstring = 0;
 	  wchar_t holder[128];
 	  size_t fmtlen;
@@ -342,6 +369,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  WIDE_LANGINFO(_M_amonth10, ABMON_10)
 	  WIDE_LANGINFO(_M_amonth11, ABMON_11)
 	  WIDE_LANGINFO(_M_amonth12, ABMON_12)
+#ifndef _GLIBCXX_HAVE_MBSTOWCS_L
+	  uselocale(__old);
+#endif
 	}
     }
 
diff --git a/libstdc++-v3/config/locale/dragonfly/time_members.h b/libstdc++-v3/config/locale/xpg7/time_members.h
similarity index 97%
rename from libstdc++-v3/config/locale/dragonfly/time_members.h
rename to libstdc++-v3/config/locale/xpg7/time_members.h
index 04b7e995d6f..1457d4cce32 100644
--- a/libstdc++-v3/config/locale/dragonfly/time_members.h
+++ b/libstdc++-v3/config/locale/xpg7/time_members.h
@@ -1,4 +1,4 @@
-// std::time_get, std::time_put implementation, DragonFly version -*- C++ -*-
+// std::time_get, std::time_put implementation, XPG7 version -*- C++ -*-
 
 // Copyright (C) 2015-2021 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/config/os/aix/ctype_configure_char.cc b/libstdc++-v3/config/os/aix/ctype_configure_char.cc
index b12c0bd435c..9cbfd0317b5 100644
--- a/libstdc++-v3/config/os/aix/ctype_configure_char.cc
+++ b/libstdc++-v3/config/os/aix/ctype_configure_char.cc
@@ -42,28 +42,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   ctype<char>::classic_table() throw()
   { return 0; }
 
-  ctype<char>::ctype(__c_locale, const mask* __table, bool __del,
+  ctype<char>::ctype(__c_locale __cloc, const mask* __table, bool __del,
 		     size_t __refs)
-  : facet(__refs), _M_del(__table != 0 && __del),
-  _M_toupper(NULL), _M_tolower(NULL),
-  _M_table(__table ? __table : classic_table())
-  {
-    memset(_M_widen, 0, sizeof(_M_widen));
-    _M_widen_ok = 0;
-    memset(_M_narrow, 0, sizeof(_M_narrow));
-    _M_narrow_ok = 0;
-  }
+    : facet(__refs), _M_c_locale_ctype(_S_clone_c_locale(__cloc)),
+    _M_del(__table != 0 && __del),
+    _M_toupper(NULL), _M_tolower(NULL),
+    _M_table(__table ? __table : classic_table()),
+    _M_widen_ok(0), _M_narrow_ok(0)
+    {
+      memset(_M_widen, 0, sizeof(_M_widen));
+      memset(_M_narrow, 0, sizeof(_M_narrow));
+    }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs)
-  : facet(__refs), _M_del(__table != 0 && __del),
-  _M_toupper(NULL), _M_tolower(NULL),
-  _M_table(__table ? __table : classic_table())
-  {
-    memset(_M_widen, 0, sizeof(_M_widen));
-    _M_widen_ok = 0;
-    memset(_M_narrow, 0, sizeof(_M_narrow));
-    _M_narrow_ok = 0;
-  }
+    : facet(__refs), _M_c_locale_ctype(_S_get_c_locale()),
+    _M_del(__table != 0 && __del),
+    _M_toupper(NULL), _M_tolower(NULL),
+    _M_table(__table ? __table : classic_table()),
+    _M_widen_ok(0), _M_narrow_ok(0)
+    {
+      memset(_M_widen, 0, sizeof(_M_widen));
+      memset(_M_narrow, 0, sizeof(_M_narrow));
+    }
 
   char
   ctype<char>::do_toupper(char __c) const
diff --git a/libstdc++-v3/config/os/gnu-linux/ctype_configure_char.cc b/libstdc++-v3/config/os/gnu-linux/ctype_configure_char.cc
index d6ab73175b8..d909feefca3 100644
--- a/libstdc++-v3/config/os/gnu-linux/ctype_configure_char.cc
+++ b/libstdc++-v3/config/os/gnu-linux/ctype_configure_char.cc
@@ -38,7 +38,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 // Information as gleaned from /usr/include/ctype.h
 
-#if _GLIBCXX_C_LOCALE_GNU
+#if _GLIBCXX_C_LOCALE_GNU || _GLIBCXX_C_LOCALE_XPG7
   const ctype_base::mask*
   ctype<char>::classic_table() throw()
   { return _S_get_c_locale()->__ctype_b; }
@@ -70,7 +70,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   }
 #endif
 
-#if _GLIBCXX_C_LOCALE_GNU
+#if _GLIBCXX_C_LOCALE_GNU || _GLIBCXX_C_LOCALE_XPG7
   ctype<char>::ctype(__c_locale __cloc, const mask* __table, bool __del,
 		     size_t __refs)
   : facet(__refs), _M_c_locale_ctype(_S_clone_c_locale(__cloc)),
@@ -117,7 +117,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   }
 #endif
 
-#if _GLIBCXX_C_LOCALE_GNU
+#if _GLIBCXX_C_LOCALE_GNU || _GLIBCXX_C_LOCALE_XPG7
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs)
   : facet(__refs), _M_c_locale_ctype(_S_get_c_locale()),
   _M_del(__table != 0 && __del),
diff --git a/libstdc++-v3/config/os/solaris/ctype_configure_char.cc b/libstdc++-v3/config/os/solaris/ctype_configure_char.cc
index 430c007ee2f..a1e0cf2fd31 100644
--- a/libstdc++-v3/config/os/solaris/ctype_configure_char.cc
+++ b/libstdc++-v3/config/os/solaris/ctype_configure_char.cc
@@ -42,27 +42,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   ctype<char>::classic_table() throw()
   { return __ctype_mask; }
 
-  ctype<char>::ctype(__c_locale, const mask* __table, bool __del,
+  ctype<char>::ctype(__c_locale __cloc, const mask* __table, bool __del,
 		     size_t __refs)
-  : facet(__refs), _M_del(__table != 0 && __del),
+  : facet(__refs), _M_c_locale_ctype(_S_clone_c_locale(__cloc)),
+  _M_del(__table != 0 && __del),
   _M_toupper(__trans_upper), _M_tolower(__trans_lower),
-  _M_table(__table ? __table : classic_table())
+  _M_table(__table ? __table : classic_table()),
+  _M_widen_ok(0), _M_narrow_ok(0)
   {
     memset(_M_widen, 0, sizeof(_M_widen));
-    _M_widen_ok = 0;
     memset(_M_narrow, 0, sizeof(_M_narrow));
-    _M_narrow_ok = 0;
   }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs)
-  : facet(__refs), _M_del(__table != 0 && __del),
+  : facet(__refs), _M_c_locale_ctype(_S_get_c_locale()),
+  _M_del(__table != 0 && __del),
   _M_toupper(__trans_upper), _M_tolower(__trans_lower),
-  _M_table(__table ? __table : classic_table())
+  _M_table(__table ? __table : classic_table()),
+  _M_widen_ok(0), _M_narrow_ok(0)
   {
     memset(_M_widen, 0, sizeof(_M_widen));
-    _M_widen_ok = 0;
     memset(_M_narrow, 0, sizeof(_M_narrow));
-    _M_narrow_ok = 0;
   }
 
   char
diff --git a/libstdc++-v3/src/c++98/locale_init.cc b/libstdc++-v3/src/c++98/locale_init.cc
index 4bec50bf595..dcea799aeaf 100644
--- a/libstdc++-v3/src/c++98/locale_init.cc
+++ b/libstdc++-v3/src/c++98/locale_init.cc
@@ -296,7 +296,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _S_global = __other._M_impl;
       const string __other_name = __other.name();
       if (__other_name != "*")
+#ifdef _GLIBCXX_C_LOCALE_GNU
 	setlocale(LC_ALL, __other_name.c_str());
+#else
+        {
+	  // In general, passing "LC_CTYPE=C;LC_NUMERIQUE=C;..." as
+	  // argument to setlocale isn't allowed.
+	  if (__other._M_impl->_M_check_same_name())
+	    setlocale(LC_ALL, __other_name.c_str());
+	  else
+	    for (size_t __i = 0; __i < __other._S_categories_size; ++__i)
+	      setlocale(__i, __other._M_impl->_M_names[__i]);
+	}
+#endif
     }
 
     // Reference count sanity check: one reference removed for the
diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/2.cc b/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/2.cc
index ea0c43a20fc..71e198843d2 100644
--- a/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/2.cc
+++ b/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/2.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "en_US.ISO8859-1" }
+// { dg-excess-errors "wchar_t overflow" { xfail { wchar_t_char16_t_compatible } } }
 
 // 2003-02-06  Petur Runolfsson  <peturr02@ru.is>
 
diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/3.cc b/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/3.cc
index 54206f8000a..ffde94108a1 100644
--- a/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/3.cc
+++ b/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/3.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "en_US.ISO-8859-15" }
+// { dg-excess-errors "wchar_t overflow" { xfail { wchar_t_char16_t_compatible } } }
 
 // 2003-02-06  Petur Runolfsson  <peturr02@ru.is>
 
diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/4.cc b/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/4.cc
index f27d667daf5..9193b598162 100644
--- a/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/4.cc
+++ b/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/4.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "en_US.UTF-8" }
+// { dg-excess-errors "wchar_t overflow" { xfail { wchar_t_char16_t_compatible } } }
 
 // 2003-02-06  Petur Runolfsson  <peturr02@ru.is>
 
diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/7.cc b/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/7.cc
index b5383af657c..e4b428c9fc6 100644
--- a/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/7.cc
+++ b/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/7.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "en_US.UTF-8" }
+// { dg-excess-errors "wchar_t overflow" { xfail { wchar_t_char16_t_compatible } } }
 
 // 2003-02-06  Petur Runolfsson  <peturr02@ru.is>
 
diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/8.cc b/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/8.cc
index 1d40a1723a4..ffbd856640b 100644
--- a/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/8.cc
+++ b/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/8.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "en_US.UTF-8" }
+// { dg-excess-errors "wchar_t overflow" { xfail { wchar_t_char16_t_compatible } } }
 
 // 2003-02-06  Petur Runolfsson  <peturr02@ru.is>
 
diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/9.cc b/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/9.cc
index 9801e085683..5e42a373547 100644
--- a/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/9.cc
+++ b/libstdc++-v3/testsuite/22_locale/codecvt/in/wchar_t/9.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "en_US.UTF-8" }
+// { dg-excess-errors "wchar_t overflow" { xfail { wchar_t_char16_t_compatible } } }
 
 // 2003-02-06  Petur Runolfsson  <peturr02@ru.is>
 
diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/length/wchar_t/4.cc b/libstdc++-v3/testsuite/22_locale/codecvt/length/wchar_t/4.cc
index f70d0fc6c58..01bf1a57917 100644
--- a/libstdc++-v3/testsuite/22_locale/codecvt/length/wchar_t/4.cc
+++ b/libstdc++-v3/testsuite/22_locale/codecvt/length/wchar_t/4.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "en_US.UTF-8" }
+// { dg-excess-errors "wchar_t overflow" { xfail { wchar_t_char16_t_compatible } } }
 
 // 2003-02-06  Petur Runolfsson  <peturr02@ru.is>
 
diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/out/wchar_t/4.cc b/libstdc++-v3/testsuite/22_locale/codecvt/out/wchar_t/4.cc
index 5cde0b66331..25dfa02b99d 100644
--- a/libstdc++-v3/testsuite/22_locale/codecvt/out/wchar_t/4.cc
+++ b/libstdc++-v3/testsuite/22_locale/codecvt/out/wchar_t/4.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "en_US.UTF-8" }
+// { dg-excess-errors "wchar_t overflow" { xfail { wchar_t_char16_t_compatible } } }
 
 // 2003-02-06  Petur Runolfsson  <peturr02@ru.is>
 
diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/unshift/wchar_t/4.cc b/libstdc++-v3/testsuite/22_locale/codecvt/unshift/wchar_t/4.cc
index 1e4ce5a8e3e..5d00a62c9a9 100644
--- a/libstdc++-v3/testsuite/22_locale/codecvt/unshift/wchar_t/4.cc
+++ b/libstdc++-v3/testsuite/22_locale/codecvt/unshift/wchar_t/4.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "en_US.UTF-8" }
+// { dg-excess-errors "wchar_t overflow" { xfail { wchar_t_char16_t_compatible } } }
 
 // 2003-02-06  Petur Runolfsson  <peturr02@ru.is>
 
diff --git a/libstdc++-v3/testsuite/22_locale/ctype/is/wchar_t/2.cc b/libstdc++-v3/testsuite/22_locale/ctype/is/wchar_t/2.cc
index 5254c967018..1f2869e43f6 100644
--- a/libstdc++-v3/testsuite/22_locale/ctype/is/wchar_t/2.cc
+++ b/libstdc++-v3/testsuite/22_locale/ctype/is/wchar_t/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { xfail { ! { *-*-linux* *-*-gnu* } } } }
 // { dg-require-namedlocale "de_DE.ISO8859-15" }
+// { dg-require-localemodel "gnu xpg7" }
 
 // Copyright (C) 2000-2021 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/22_locale/locale/cons/29217.cc b/libstdc++-v3/testsuite/22_locale/locale/cons/29217.cc
index a60e98eee76..0cfcc042b1c 100644
--- a/libstdc++-v3/testsuite/22_locale/locale/cons/29217.cc
+++ b/libstdc++-v3/testsuite/22_locale/locale/cons/29217.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "en_US.UTF-8" }
+// { dg-require-localemodel "gnu" }
 
 // Copyright (C) 2006-2021 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/22_locale/locale/cons/38368.cc b/libstdc++-v3/testsuite/22_locale/locale/cons/38368.cc
index 8d8f07f01cc..94fcfe3ac8b 100644
--- a/libstdc++-v3/testsuite/22_locale/locale/cons/38368.cc
+++ b/libstdc++-v3/testsuite/22_locale/locale/cons/38368.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "en_US.ISO8859-1" }
+// { dg-require-localemodel "gnu" }
 
 // Copyright (C) 2008-2021 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/22_locale/locale/cons/40184.cc b/libstdc++-v3/testsuite/22_locale/locale/cons/40184.cc
index 6a8eff8737b..d41ee12603b 100644
--- a/libstdc++-v3/testsuite/22_locale/locale/cons/40184.cc
+++ b/libstdc++-v3/testsuite/22_locale/locale/cons/40184.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "ja_JP.eucJP" }
+// { dg-require-localemodel "gnu" }
 
 // Copyright (C) 2009-2021 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/22_locale/locale/cons/5.cc b/libstdc++-v3/testsuite/22_locale/locale/cons/5.cc
index 66b939e2228..99abf566b81 100644
--- a/libstdc++-v3/testsuite/22_locale/locale/cons/5.cc
+++ b/libstdc++-v3/testsuite/22_locale/locale/cons/5.cc
@@ -3,6 +3,7 @@
 // { dg-require-namedlocale "es_MX" }
 // { dg-require-namedlocale "fr_FR" }
 // { dg-require-namedlocale "it_IT" }
+// { dg-require-localemodel "gnu" }
 
 // 2000-09-13 Benjamin Kosnik <bkoz@redhat.com>
 
diff --git a/libstdc++-v3/testsuite/22_locale/locale/global_locale_objects/14071.cc b/libstdc++-v3/testsuite/22_locale/locale/global_locale_objects/14071.cc
index ea3992b03f6..30d4a31a64c 100644
--- a/libstdc++-v3/testsuite/22_locale/locale/global_locale_objects/14071.cc
+++ b/libstdc++-v3/testsuite/22_locale/locale/global_locale_objects/14071.cc
@@ -1,5 +1,6 @@
 // { dg-require-namedlocale "is_IS.ISO8859-1" }
 // { dg-require-namedlocale "en_US.ISO8859-1" }
+// { dg-require-localemodel "gnu" }
 
 // 2004-02-09  Petur Runolfsson  <peturr02@ru.is>
 
diff --git a/libstdc++-v3/testsuite/22_locale/messages/13631.cc b/libstdc++-v3/testsuite/22_locale/messages/13631.cc
index b8ae3d4f140..2509bba0845 100644
--- a/libstdc++-v3/testsuite/22_locale/messages/13631.cc
+++ b/libstdc++-v3/testsuite/22_locale/messages/13631.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "fr_FR.ISO8859-15" }
+// { dg-require-localemodel "gnu" }
 
 // Copyright (C) 2014-2021 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/22_locale/messages/members/char/1.cc b/libstdc++-v3/testsuite/22_locale/messages/members/char/1.cc
index c4d972124f0..fdf4a0af018 100644
--- a/libstdc++-v3/testsuite/22_locale/messages/members/char/1.cc
+++ b/libstdc++-v3/testsuite/22_locale/messages/members/char/1.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "de_DE.ISO8859-15" }
+// { dg-require-localemodel "gnu" }
 
 // 2001-07-17 Benjamin Kosnik  <bkoz@redhat.com>
 
diff --git a/libstdc++-v3/testsuite/22_locale/messages/members/char/2.cc b/libstdc++-v3/testsuite/22_locale/messages/members/char/2.cc
index 81d914f5c37..3345f43b342 100644
--- a/libstdc++-v3/testsuite/22_locale/messages/members/char/2.cc
+++ b/libstdc++-v3/testsuite/22_locale/messages/members/char/2.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "fr_FR.ISO8859-15" }
+// { dg-require-localemodel "gnu" }
 
 // 2001-07-17 Benjamin Kosnik  <bkoz@redhat.com>
 
diff --git a/libstdc++-v3/testsuite/22_locale/messages/members/char/3.cc b/libstdc++-v3/testsuite/22_locale/messages/members/char/3.cc
index 5a503ef2c49..1d2f7ad3162 100644
--- a/libstdc++-v3/testsuite/22_locale/messages/members/char/3.cc
+++ b/libstdc++-v3/testsuite/22_locale/messages/members/char/3.cc
@@ -1,5 +1,6 @@
 // { dg-require-namedlocale "en_US.ISO8859-1" }
 // { dg-require-namedlocale "fr_FR.ISO8859-15" }
+// { dg-require-localemodel "gnu" }
 
 // 2001-07-17 Benjamin Kosnik  <bkoz@redhat.com>
 
diff --git a/libstdc++-v3/testsuite/22_locale/messages/members/char/wrapped_env.cc b/libstdc++-v3/testsuite/22_locale/messages/members/char/wrapped_env.cc
index 35e7f6c740c..976b4d9fbf6 100644
--- a/libstdc++-v3/testsuite/22_locale/messages/members/char/wrapped_env.cc
+++ b/libstdc++-v3/testsuite/22_locale/messages/members/char/wrapped_env.cc
@@ -1,6 +1,7 @@
 // { dg-require-namedlocale "de_DE.ISO8859-15" }
 // { dg-require-namedlocale "fr_FR.ISO8859-15" }
 // { dg-require-namedlocale "en_US.ISO8859-1" }
+// { dg-require-localemodel "gnu" }
 
 // 2001-08-15 Benjamin Kosnik  <bkoz@redhat.com>
 
diff --git a/libstdc++-v3/testsuite/22_locale/messages/members/char/wrapped_locale.cc b/libstdc++-v3/testsuite/22_locale/messages/members/char/wrapped_locale.cc
index a44bf1476b2..b143d33a4cc 100644
--- a/libstdc++-v3/testsuite/22_locale/messages/members/char/wrapped_locale.cc
+++ b/libstdc++-v3/testsuite/22_locale/messages/members/char/wrapped_locale.cc
@@ -2,6 +2,7 @@
 // { dg-require-namedlocale "de_DE.ISO8859-15" }
 // { dg-require-namedlocale "fr_FR.ISO8859-15" }
 // { dg-require-namedlocale "en_US.ISO8859-1" }
+// { dg-require-localemodel "gnu" }
 
 // 2001-08-15 Benjamin Kosnik  <bkoz@redhat.com>
 
diff --git a/libstdc++-v3/testsuite/22_locale/messages_byname/named_equivalence.cc b/libstdc++-v3/testsuite/22_locale/messages_byname/named_equivalence.cc
index 1006f20c996..fabf281d3e6 100644
--- a/libstdc++-v3/testsuite/22_locale/messages_byname/named_equivalence.cc
+++ b/libstdc++-v3/testsuite/22_locale/messages_byname/named_equivalence.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "de_DE.ISO8859-15" }
+// { dg-require-localemodel "gnu" }
 
 // 2001-07-17 Benjamin Kosnik  <bkoz@redhat.com>
 
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-1.cc
index c747f7bfb02..46713cca118 100644
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-1.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-1.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "en_US.UTF-8" }
+// { dg-excess-errors "wchar_t overflow" { xfail { wchar_t_char16_t_compatible } } }
 
 // Copyright (C) 2003-2021 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-2.cc
index 76a387768fe..a3a4bbf5833 100644
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-2.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-2.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "en_US.UTF-8" }
+// { dg-excess-errors "wchar_t overflow" { xfail { wchar_t_char16_t_compatible } } }
 
 // Copyright (C) 2003-2021 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-3.cc
index 24d192921cb..2a314589714 100644
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-3.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-3.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "en_US.UTF-8" }
+// { dg-excess-errors "wchar_t overflow" { xfail { wchar_t_char16_t_compatible } } }
 
 // Copyright (C) 2003-2021 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-4.cc
index 2c0a2ab61db..71393bbd255 100644
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-4.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/overflow/wchar_t/11305-4.cc
@@ -1,4 +1,5 @@
 // { dg-require-namedlocale "en_US.UTF-8" }
+// { dg-excess-errors "wchar_t overflow" { xfail { wchar_t_char16_t_compatible } } }
 
 // Copyright (C) 2003-2021 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp b/libstdc++-v3/testsuite/lib/dg-options.exp
index 872768f2620..8474e8df14b 100644
--- a/libstdc++-v3/testsuite/lib/dg-options.exp
+++ b/libstdc++-v3/testsuite/lib/dg-options.exp
@@ -88,6 +88,15 @@ proc dg-require-namedlocale { args } {
     return
 }
 
+proc dg-require-localemodel { args } {
+    if { ![ check_v3_target_localemodel [lindex $args 1] ] } {
+	upvar dg-do-what dg-do-what
+	set dg-do-what [list [lindex ${dg-do-what} 0] "N" "P"]
+	return
+    }
+    return
+}
+
 proc dg-require-sharedlib { args } {
     if { ![ check_v3_target_sharedlib ] } {
 	upvar dg-do-what dg-do-what
diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp
index 73b202ce212..bb3e34400e4 100644
--- a/libstdc++-v3/testsuite/lib/libstdc++.exp
+++ b/libstdc++-v3/testsuite/lib/libstdc++.exp
@@ -895,6 +895,11 @@ proc check_v3_target_namedlocale { args } {
 	puts $f "    strcpy(result, name);"
 	puts $f "#if defined __FreeBSD__ || defined __DragonFly__ || defined __NetBSD__"
 	puts $f "    /* fall-through */"
+	puts $f "#elif defined _AIX"
+	puts $f "    char *p = strstr(result, \"ISO8859-15\");"
+	puts $f "    if (p) {"
+	puts $f "       strcpy(p, \"8859-15\");"
+	puts $f "    }"
 	puts $f "#else"
 	puts $f "    if (strstr(result, \"ISO8859-15\")) {"
 	puts $f "        strcat(result, \"@euro\");"
@@ -945,6 +950,32 @@ proc check_v3_target_namedlocale { args } {
     }]
 }
 
+# Return 1 if the locale model is implemented.
+proc check_v3_target_localemodel { args } {
+    set key "et_locale $args"
+    return [check_v3_target_prop_cached $key {
+	global cxxflags
+	global DEFAULT_CXXFLAGS
+
+	set cond "0"
+	if [string match "*gnu*" $args] {
+	    set cond " $cond || defined _GLIBCXX_C_LOCALE_GNU"
+	}
+	if [string match "*xpg7*" $args] {
+	    set cond " $cond || defined _GLIBCXX_C_LOCALE_XPG7"
+	}
+
+	set code "
+	#include <bits/c++locale.h>
+	#if ! ($cond)
+	#error '$cond' is false
+	#endif
+	"
+	set flags "$cxxflags $DEFAULT_CXXFLAGS -Werror"
+	return [v3_try_preprocess name $code $flags]
+    }]
+}
+
 # Returns 1 if the tokens in CODE can be preprocessed successfully using FLAGS,
 # returns 0 otherwise.
 proc v3_try_preprocess { name code flags } {
diff --git a/libstdc++-v3/testsuite/util/testsuite_hooks.h b/libstdc++-v3/testsuite/util/testsuite_hooks.h
index b5e0767211a..a632f5f31f8 100644
--- a/libstdc++-v3/testsuite/util/testsuite_hooks.h
+++ b/libstdc++-v3/testsuite/util/testsuite_hooks.h
@@ -77,6 +77,9 @@
 
 #if defined __FreeBSD__ || defined __DragonFly__ || defined __NetBSD__
 # define ISO_8859(part,langTERR) #langTERR ".ISO8859-" #part
+#elif defined _AIX
+# define ISO_8859(part,langTERR) ((part) == 15 ?\
+         #langTERR ".8859-" #part : #langTERR ".ISO8859-" #part)
 #else
 # define ISO_8859(part,langTERR) ((part) == 15 ?\
          #langTERR ".ISO8859-" #part "@euro" : #langTERR ".ISO8859-" #part)
-- 
2.31.1

