[libcxx-commits] [libcxx] [libc++] Define an internal locale API as a shim on top of the current one (PR #114596)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Tue Nov 5 09:58:39 PST 2024


https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/114596

>From a740a0b5bbb6d5bed93a2ca4dea7b8b904811db1 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Fri, 25 Oct 2024 15:18:19 -0400
Subject: [PATCH 1/5] [libc++] Define an internal locale API as a shim on top
 of the current one

Our current locale base API is a mix of non-reserved system names that
we incorrectly (re)define and internal functions and macros starting
with __libcpp. This patch introduces a function-based internal interface
to isolate the rest of the code base from that mess, so that we can work
on refactoring how each platform implements the base API in subsequent
patches. This makes it possible to refactor how each platform implements
the base localization API without impacting the rest of the code base.
---
 libcxx/include/__locale                       |  10 +-
 libcxx/include/__locale_dir/locale_base_api.h | 301 ++++++++++++++----
 .../locale_base_api/bsd_locale_defaults.h     |   1 +
 libcxx/include/__locale_dir/locale_guard.h    |  10 +-
 libcxx/include/locale                         |  26 +-
 libcxx/src/iostream.cpp                       |   4 +-
 libcxx/src/locale.cpp                         | 286 ++++++++---------
 7 files changed, 406 insertions(+), 232 deletions(-)

diff --git a/libcxx/include/__locale b/libcxx/include/__locale
index 5fb0c19903cd5b..f251eb638af4c0 100644
--- a/libcxx/include/__locale
+++ b/libcxx/include/__locale
@@ -247,7 +247,7 @@ class _LIBCPP_TEMPLATE_VIS collate_byname;
 
 template <>
 class _LIBCPP_EXPORTED_FROM_ABI collate_byname<char> : public collate<char> {
-  locale_t __l_;
+  __locale::__locale_t __l_;
 
 public:
   typedef char char_type;
@@ -266,7 +266,7 @@ protected:
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 template <>
 class _LIBCPP_EXPORTED_FROM_ABI collate_byname<wchar_t> : public collate<wchar_t> {
-  locale_t __l_;
+  __locale::__locale_t __l_;
 
 public:
   typedef wchar_t char_type;
@@ -616,7 +616,7 @@ class _LIBCPP_TEMPLATE_VIS ctype_byname;
 
 template <>
 class _LIBCPP_EXPORTED_FROM_ABI ctype_byname<char> : public ctype<char> {
-  locale_t __l_;
+  __locale::__locale_t __l_;
 
 public:
   explicit ctype_byname(const char*, size_t = 0);
@@ -633,7 +633,7 @@ protected:
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 template <>
 class _LIBCPP_EXPORTED_FROM_ABI ctype_byname<wchar_t> : public ctype<wchar_t> {
-  locale_t __l_;
+  __locale::__locale_t __l_;
 
 public:
   explicit ctype_byname(const char*, size_t = 0);
@@ -824,7 +824,7 @@ protected:
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 template <>
 class _LIBCPP_EXPORTED_FROM_ABI codecvt<wchar_t, char, mbstate_t> : public locale::facet, public codecvt_base {
-  locale_t __l_;
+  __locale::__locale_t __l_;
 
 public:
   typedef wchar_t intern_type;
diff --git a/libcxx/include/__locale_dir/locale_base_api.h b/libcxx/include/__locale_dir/locale_base_api.h
index bef10db1e1e59b..253799a049ceee 100644
--- a/libcxx/include/__locale_dir/locale_base_api.h
+++ b/libcxx/include/__locale_dir/locale_base_api.h
@@ -11,6 +11,93 @@
 
 #include <__config>
 
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+// The platform-specific headers have to provide the following interface.
+//
+// These functions are equivalent to their C counterparts, except that __locale::__locale_t
+// is used instead of the current global locale.
+//
+// Variadic functions may be implemented as templates with a parameter pack instead
+// of C-style variadic functions.
+//
+// TODO: I think __uselocale() is not necessary if we refactor a bit.
+// TODO: __localeconv shouldn't take a reference, but the Windows implementation doesn't allow copying __locale_t
+//
+// Locale management
+// -----------------
+// namespace __locale {
+//  using __locale_t = implementation-defined;
+//  __locale_t  __uselocale(__locale_t);
+//  __locale_t  __newlocale(int, const char*, __locale_t);
+//  void        __freelocale(__locale_t);
+//  lconv*      __localeconv(__locale_t&);
+// }
+//
+// Strtonum functions
+// ------------------
+// namespace __locale {
+//  float               __strtof(const char*, char**, __locale_t);
+//  double              __strtod(const char*, char**, __locale_t);
+//  long double         __strtold(const char*, char**, __locale_t);
+//  long long           __strtoll(const char*, char**, __locale_t);
+//  unsigned long long  __strtoull(const char*, char**, __locale_t);
+// }
+//
+// Character manipulation functions
+// --------------------------------
+// namespace __locale {
+//  int     __islower(int, __locale_t);
+//  int     __isupper(int, __locale_t);
+//  int     __isdigit(int, __locale_t);
+//  int     __isxdigit(int, __locale_t);
+//  int     __toupper(int, __locale_t);
+//  int     __tolower(int, __locale_t);
+//  int     __strcoll(const char*, const char*, __locale_t);
+//  size_t  __strxfrm(char*, const char*, size_t, __locale_t);
+//
+//  int     __iswspace(wint_t, __locale_t);
+//  int     __iswprint(wint_t, __locale_t);
+//  int     __iswcntrl(wint_t, __locale_t);
+//  int     __iswupper(wint_t, __locale_t);
+//  int     __iswlower(wint_t, __locale_t);
+//  int     __iswalpha(wint_t, __locale_t);
+//  int     __iswblank(wint_t, __locale_t);
+//  int     __iswdigit(wint_t, __locale_t);
+//  int     __iswpunct(wint_t, __locale_t);
+//  int     __iswxdigit(wint_t, __locale_t);
+//  wint_t  __towupper(wint_t, __locale_t);
+//  wint_t  __towlower(wint_t, __locale_t);
+//  int     __wcscoll(const wchar_t*, const wchar_t*, __locale_t);
+//  size_t  __wcsxfrm(wchar_t*, const wchar_t*, size_t, __locale_t);
+//
+//  size_t  __strftime(char*, size_t, const char*, const tm*, __locale_t);
+// }
+//
+// Other functions
+// ---------------
+// namespace __locale {
+//  implementation-defined __mb_cur_max(__locale_t);
+//  wint_t  __btowc(int, __locale_t);
+//  int     __wctob(wint_t, __locale_t);
+//  size_t  __wcsnrtombs(char*, const wchar_t**, size_t, size_t, mbstate_t*, __locale_t);
+//  size_t  __wcrtomb(char*, wchar_t, mbstate_t*, __locale_t);
+//  size_t  __mbsnrtowcs(wchar_t*, const char**, size_t, size_t, mbstate_t*, __locale_t);
+//  size_t  __mbrtowc(wchar_t*, const char*, size_t, mbstate_t*, __locale_t);
+//  int     __mbtowc(wchar_t*, const char*, size_t, __locale_t);
+//  size_t  __mbrlen(const char*, size_t, mbstate_t*, __locale_t);
+//  size_t  __mbsrtowcs(wchar_t*, const char**, size_t, mbstate_t*, __locale_t);
+//  int     __snprintf(char*, size_t, __locale_t, const char*, ...);
+//  int     __asprintf(char**, __locale_t, const char*, ...);
+//  int     __sscanf(const char*, __locale_t, const char*, ...);
+// }
+
+// TODO: This is a temporary definition to bridge between the old way we defined the locale base API
+//       (by providing global non-reserved names) and the new API. As we move individual platforms
+//       towards the new way of defining the locale base API, this should disappear since each platform
+//       will define those directly.
 #if defined(_LIBCPP_MSVCRT_LIKE)
 #  include <__locale_dir/locale_base_api/win32.h>
 #elif defined(_AIX) || defined(__MVS__)
@@ -35,71 +122,157 @@
 #  include <__locale_dir/locale_base_api/bsd_locale_fallbacks.h>
 #endif
 
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-#  pragma GCC system_header
+#include <__cstddef/size_t.h>
+#include <__utility/forward.h>
+#include <string.h>
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+#  include <wctype.h>
+#endif
+_LIBCPP_BEGIN_NAMESPACE_STD
+namespace __locale {
+//
+// Locale management
+//
+using __locale_t = locale_t;
+
+inline _LIBCPP_HIDE_FROM_ABI __locale_t __uselocale(__locale_t __loc) { return uselocale(__loc); }
+
+inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __name, __locale_t __loc) {
+  return newlocale(__category_mask, __name, __loc);
+}
+
+inline _LIBCPP_HIDE_FROM_ABI void __freelocale(__locale_t __loc) { freelocale(__loc); }
+
+inline _LIBCPP_HIDE_FROM_ABI lconv* __localeconv(__locale_t& __loc) { return __libcpp_localeconv_l(__loc); }
+
+//
+// Strtonum functions
+//
+inline _LIBCPP_HIDE_FROM_ABI float __strtof(const char* __nptr, char** __endptr, __locale_t __loc) {
+  return strtof_l(__nptr, __endptr, __loc);
+}
+
+inline _LIBCPP_HIDE_FROM_ABI double __strtod(const char* __nptr, char** __endptr, __locale_t __loc) {
+  return strtod_l(__nptr, __endptr, __loc);
+}
+
+inline _LIBCPP_HIDE_FROM_ABI long double __strtold(const char* __nptr, char** __endptr, __locale_t __loc) {
+  return strtold_l(__nptr, __endptr, __loc);
+}
+
+inline _LIBCPP_HIDE_FROM_ABI long long __strtoll(const char* __nptr, char** __endptr, int __base, __locale_t __loc) {
+  return strtoll_l(__nptr, __endptr, __base, __loc);
+}
+
+inline _LIBCPP_HIDE_FROM_ABI unsigned long long
+__strtoull(const char* __nptr, char** __endptr, int __base, __locale_t __loc) {
+  return strtoull_l(__nptr, __endptr, __base, __loc);
+}
+
+//
+// Character manipulation functions
+//
+inline _LIBCPP_HIDE_FROM_ABI int __islower(int __ch, __locale_t __loc) { return islower_l(__ch, __loc); }
+inline _LIBCPP_HIDE_FROM_ABI int __isupper(int __ch, __locale_t __loc) { return isupper_l(__ch, __loc); }
+inline _LIBCPP_HIDE_FROM_ABI int __isdigit(int __ch, __locale_t __loc) { return isdigit_l(__ch, __loc); }
+inline _LIBCPP_HIDE_FROM_ABI int __isxdigit(int __ch, __locale_t __loc) { return isxdigit_l(__ch, __loc); }
+inline _LIBCPP_HIDE_FROM_ABI int __strcoll(const char* __s1, const char* __s2, __locale_t __loc) {
+  return strcoll_l(__s1, __s2, __loc);
+}
+inline _LIBCPP_HIDE_FROM_ABI size_t __strxfrm(char* __dest, const char* __src, size_t __n, __locale_t __loc) {
+  return strxfrm_l(__dest, __src, __n, __loc);
+}
+inline _LIBCPP_HIDE_FROM_ABI int __toupper(int __ch, __locale_t __loc) { return toupper_l(__ch, __loc); }
+inline _LIBCPP_HIDE_FROM_ABI int __tolower(int __ch, __locale_t __loc) { return tolower_l(__ch, __loc); }
+
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+inline _LIBCPP_HIDE_FROM_ABI int __wcscoll(const wchar_t* __s1, const wchar_t* __s2, __locale_t __loc) {
+  return wcscoll_l(__s1, __s2, __loc);
+}
+inline _LIBCPP_HIDE_FROM_ABI size_t __wcsxfrm(wchar_t* __dest, const wchar_t* __src, size_t __n, __locale_t __loc) {
+  return wcsxfrm_l(__dest, __src, __n, __loc);
+}
+inline _LIBCPP_HIDE_FROM_ABI int __iswspace(wint_t __ch, __locale_t __loc) { return iswspace_l(__ch, __loc); }
+inline _LIBCPP_HIDE_FROM_ABI int __iswprint(wint_t __ch, __locale_t __loc) { return iswprint_l(__ch, __loc); }
+inline _LIBCPP_HIDE_FROM_ABI int __iswcntrl(wint_t __ch, __locale_t __loc) { return iswcntrl_l(__ch, __loc); }
+inline _LIBCPP_HIDE_FROM_ABI int __iswupper(wint_t __ch, __locale_t __loc) { return iswupper_l(__ch, __loc); }
+inline _LIBCPP_HIDE_FROM_ABI int __iswlower(wint_t __ch, __locale_t __loc) { return iswlower_l(__ch, __loc); }
+inline _LIBCPP_HIDE_FROM_ABI int __iswalpha(wint_t __ch, __locale_t __loc) { return iswalpha_l(__ch, __loc); }
+inline _LIBCPP_HIDE_FROM_ABI int __iswblank(wint_t __ch, __locale_t __loc) { return iswblank_l(__ch, __loc); }
+inline _LIBCPP_HIDE_FROM_ABI int __iswdigit(wint_t __ch, __locale_t __loc) { return iswdigit_l(__ch, __loc); }
+inline _LIBCPP_HIDE_FROM_ABI int __iswpunct(wint_t __ch, __locale_t __loc) { return iswpunct_l(__ch, __loc); }
+inline _LIBCPP_HIDE_FROM_ABI int __iswxdigit(wint_t __ch, __locale_t __loc) { return iswxdigit_l(__ch, __loc); }
+inline _LIBCPP_HIDE_FROM_ABI wint_t __towupper(wint_t __ch, __locale_t __loc) { return towupper_l(__ch, __loc); }
+inline _LIBCPP_HIDE_FROM_ABI wint_t __towlower(wint_t __ch, __locale_t __loc) { return towlower_l(__ch, __loc); }
+#endif
+
+inline _LIBCPP_HIDE_FROM_ABI size_t
+__strftime(char* __s, size_t __max, const char* __format, const tm* __tm, __locale_t __loc) {
+  return strftime_l(__s, __max, __format, __tm, __loc);
+}
+
+//
+// Other functions
+//
+inline _LIBCPP_HIDE_FROM_ABI decltype(__libcpp_mb_cur_max_l(__locale_t())) __mb_cur_max(__locale_t __loc) {
+  return __libcpp_mb_cur_max_l(__loc);
+}
+inline _LIBCPP_HIDE_FROM_ABI wint_t __btowc(int __ch, __locale_t __loc) { return __libcpp_btowc_l(__ch, __loc); }
+inline _LIBCPP_HIDE_FROM_ABI int __wctob(wint_t __ch, __locale_t __loc) { return __libcpp_wctob_l(__ch, __loc); }
+inline _LIBCPP_HIDE_FROM_ABI size_t
+__wcsnrtombs(char* __dest, const wchar_t** __src, size_t __nwc, size_t __len, mbstate_t* __ps, __locale_t __loc) {
+  return __libcpp_wcsnrtombs_l(__dest, __src, __nwc, __len, __ps, __loc);
+}
+inline _LIBCPP_HIDE_FROM_ABI size_t __wcrtomb(char* __s, wchar_t __ch, mbstate_t* __ps, __locale_t __loc) {
+  return __libcpp_wcrtomb_l(__s, __ch, __ps, __loc);
+}
+inline _LIBCPP_HIDE_FROM_ABI size_t
+__mbsnrtowcs(wchar_t* __dest, const char** __src, size_t __nms, size_t __len, mbstate_t* __ps, __locale_t __loc) {
+  return __libcpp_mbsnrtowcs_l(__dest, __src, __nms, __len, __ps, __loc);
+}
+inline _LIBCPP_HIDE_FROM_ABI size_t
+__mbrtowc(wchar_t* __pwc, const char* __s, size_t __n, mbstate_t* __ps, __locale_t __loc) {
+  return __libcpp_mbrtowc_l(__pwc, __s, __n, __ps, __loc);
+}
+inline _LIBCPP_HIDE_FROM_ABI int __mbtowc(wchar_t* __pwc, const char* __pmb, size_t __max, __locale_t __loc) {
+  return __libcpp_mbtowc_l(__pwc, __pmb, __max, __loc);
+}
+inline _LIBCPP_HIDE_FROM_ABI size_t __mbrlen(const char* __s, size_t __n, mbstate_t* __ps, __locale_t __loc) {
+  return __libcpp_mbrlen_l(__s, __n, __ps, __loc);
+}
+inline _LIBCPP_HIDE_FROM_ABI size_t
+__mbsrtowcs(wchar_t* __dest, const char** __src, size_t __len, mbstate_t* __ps, __locale_t __loc) {
+  return __libcpp_mbsrtowcs_l(__dest, __src, __len, __ps, __loc);
+}
+
+_LIBCPP_DIAGNOSTIC_PUSH
+_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wgcc-compat")
+_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wformat-nonliteral") // GCC doesn't support [[gnu::format]] on variadic templates
+#ifdef _LIBCPP_COMPILER_CLANG_BASED
+#  define _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(...) _LIBCPP_ATTRIBUTE_FORMAT(__VA_ARGS__)
+#else
+#  define _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT
 #endif
 
-/*
-The platform-specific headers have to provide the following interface:
-
-// TODO: rename this to __libcpp_locale_t
-using locale_t = implementation-defined;
-
-implementation-defined __libcpp_mb_cur_max_l(locale_t);
-wint_t __libcpp_btowc_l(int, locale_t);
-int __libcpp_wctob_l(wint_t, locale_t);
-size_t __libcpp_wcsnrtombs_l(char* dest, const wchar_t** src, size_t wide_char_count, size_t len, mbstate_t, locale_t);
-size_t __libcpp_wcrtomb_l(char* str, wchar_t wide_char, mbstate_t*, locale_t);
-size_t __libcpp_mbsnrtowcs_l(wchar_t* dest, const char** src, size_t max_out, size_t len, mbstate_t*, locale_t);
-size_t __libcpp_mbrtowc_l(wchar_t* dest, cosnt char* src, size_t count, mbstate_t*, locale_t);
-int __libcpp_mbtowc_l(wchar_t* dest, const char* src, size_t count, locale_t);
-size_t __libcpp_mbrlen_l(const char* str, size_t count, mbstate_t*, locale_t);
-// TODO: __libcpp_localeconv_l shouldn't take a reference, but the Windows implementation doesn't allow copying locale_t
-lconv* __libcpp_localeconv_l(locale_t&);
-size_t __libcpp_mbsrtowcs_l(wchar_t* dest, const char** src, size_t len, mbstate_t*, locale_t);
-int __libcpp_snprintf_l(char* dest, size_t buff_size, locale_t, const char* format, ...);
-int __libcpp_asprintf_l(char** dest, locale_t, const char* format, ...);
-int __libcpp_sscanf_l(const char* dest, locale_t, const char* format, ...);
-
-// TODO: change these to reserved names
-float strtof_l(const char* str, char** str_end, locale_t);
-double strtod_l(const char* str, char** str_end, locale_t);
-long double strtold_l(const char* str, char** str_end, locale_t);
-long long strtoll_l(const char* str, char** str_end, locale_t);
-unsigned long long strtoull_l(const char* str, char** str_end, locale_t);
-
-locale_t newlocale(int category_mask, const char* locale, locale_t base);
-void freelocale(locale_t);
-
-int islower_l(int ch, locale_t);
-int isupper_l(int ch, locale_t);
-int isdigit_l(int ch, locale_t);
-int isxdigit_l(int ch, locale_t);
-int strcoll_l(const char* lhs, const char* rhs, locale_t);
-size_t strxfrm_l(char* dst, const char* src, size_t n, locale_t);
-int wcscoll_l(const char* lhs, const char* rhs, locale_t);
-size_t wcsxfrm_l(wchar_t* dst, const wchar_t* src, size_t n, locale_t);
-int toupper_l(int ch, locale_t);
-int tolower_l(int ch, locale_t);
-int iswspace_l(wint_t ch, locale_t);
-int iswprint_l(wint_t ch, locale_t);
-int iswcntrl_l(wint_t ch, locale_t);
-int iswupper_l(wint_t ch, locale_t);
-int iswlower_l(wint_t ch, locale_t);
-int iswalpha_l(wint_t ch, locale_t);
-int iswblank_l(wint_t ch, locale_t);
-int iswdigit_l(wint_t ch, locale_t);
-int iswpunct_l(wint_t ch, locale_t);
-int iswxdigit_l(wint_t ch, locale_t);
-wint_t towupper_l(wint_t ch, locale_t);
-wint_t towlower_l(wint_t ch, locale_t);
-size_t strftime_l(char* str, size_t len, const char* format, const tm*, locale_t);
-
-
-These functions are equivalent to their C counterparts,
-except that locale_t is used instead of the current global locale.
-
-The variadic functions may be implemented as templates with a parameter pack instead of variadic functions.
-*/
+template <class... _Args>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(__printf__, 4, 5) int __snprintf(
+    char* __s, size_t __n, __locale_t __loc, const char* __format, _Args&&... __args) {
+  return __libcpp_snprintf_l(__s, __n, __loc, __format, std::forward<_Args>(__args)...);
+}
+template <class... _Args>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(__printf__, 3, 4) int __asprintf(
+    char** __s, __locale_t __loc, const char* __format, _Args&&... __args) {
+  return __libcpp_asprintf_l(__s, __loc, __format, std::forward<_Args>(__args)...);
+}
+template <class... _Args>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(__scanf__, 3, 4) int __sscanf(
+    const char* __s, __locale_t __loc, const char* __format, _Args&&... __args) {
+  return __libcpp_sscanf_l(__s, __loc, __format, std::forward<_Args>(__args)...);
+}
+_LIBCPP_DIAGNOSTIC_POP
+#undef _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT
+
+} // namespace __locale
+_LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_H
diff --git a/libcxx/include/__locale_dir/locale_base_api/bsd_locale_defaults.h b/libcxx/include/__locale_dir/locale_base_api/bsd_locale_defaults.h
index 52f31fb37236c1..33009606aa923e 100644
--- a/libcxx/include/__locale_dir/locale_base_api/bsd_locale_defaults.h
+++ b/libcxx/include/__locale_dir/locale_base_api/bsd_locale_defaults.h
@@ -109,6 +109,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(__scanf__, 3, 4) int __l
   return ::sscanf_l(__s, __loc, __format, std::forward<_Args>(__args)...);
 }
 _LIBCPP_DIAGNOSTIC_POP
+#undef _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT
 
 _LIBCPP_END_NAMESPACE_STD
 
diff --git a/libcxx/include/__locale_dir/locale_guard.h b/libcxx/include/__locale_dir/locale_guard.h
index e0c414c001c41f..82b263de1f7f4c 100644
--- a/libcxx/include/__locale_dir/locale_guard.h
+++ b/libcxx/include/__locale_dir/locale_guard.h
@@ -10,7 +10,7 @@
 #define _LIBCPP___LOCALE_DIR_LOCALE_GUARD_H
 
 #include <__config>
-#include <__locale> // for locale_t
+#include <__locale>
 #include <clocale>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if defined(_LIBCPP_MSVCRT_LIKE)
 struct __locale_guard {
-  __locale_guard(locale_t __l) : __status(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)) {
+  __locale_guard(__locale::__locale_t __l) : __status(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)) {
     // Setting the locale can be expensive even when the locale given is
     // already the current locale, so do an explicit check to see if the
     // current locale is already the one we want.
@@ -59,14 +59,14 @@ struct __locale_guard {
 };
 #else
 struct __locale_guard {
-  _LIBCPP_HIDE_FROM_ABI __locale_guard(locale_t& __loc) : __old_loc_(uselocale(__loc)) {}
+  _LIBCPP_HIDE_FROM_ABI __locale_guard(__locale::__locale_t& __loc) : __old_loc_(__locale::__uselocale(__loc)) {}
 
   _LIBCPP_HIDE_FROM_ABI ~__locale_guard() {
     if (__old_loc_)
-      uselocale(__old_loc_);
+      __locale::__uselocale(__old_loc_);
   }
 
-  locale_t __old_loc_;
+  __locale::__locale_t __old_loc_;
 
   __locale_guard(__locale_guard const&)            = delete;
   __locale_guard& operator=(__locale_guard const&) = delete;
diff --git a/libcxx/include/locale b/libcxx/include/locale
index 4706515b0a6c86..d6f1e3595f2da3 100644
--- a/libcxx/include/locale
+++ b/libcxx/include/locale
@@ -246,7 +246,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 #  else
 #    define _LIBCPP_GET_C_LOCALE __cloc()
 // Get the C locale object
-_LIBCPP_EXPORTED_FROM_ABI locale_t __cloc();
+_LIBCPP_EXPORTED_FROM_ABI __locale::__locale_t __cloc();
 #    define __cloc_defined
 #  endif
 
@@ -1042,7 +1042,7 @@ _InputIterator num_get<_CharT, _InputIterator>::do_get(
   }
   // Stage 3
   __buf.resize(__a_end - __a);
-  if (__libcpp_sscanf_l(__buf.c_str(), _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)
+  if (__locale::__sscanf(__buf.c_str(), _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)
     __err = ios_base::failbit;
   // EOF checked
   if (__b == __e)
@@ -1125,11 +1125,11 @@ void __num_put<_CharT>::__widen_and_group_float(
     *__oe++ = __ct.widen(*__nf++);
     *__oe++ = __ct.widen(*__nf++);
     for (__ns = __nf; __ns < __ne; ++__ns)
-      if (!isxdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
+      if (!__locale::__isxdigit(*__ns, _LIBCPP_GET_C_LOCALE))
         break;
   } else {
     for (__ns = __nf; __ns < __ne; ++__ns)
-      if (!isdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
+      if (!__locale::__isdigit(*__ns, _LIBCPP_GET_C_LOCALE))
         break;
   }
   if (__grouping.empty()) {
@@ -1330,7 +1330,7 @@ _LIBCPP_HIDE_FROM_ABI inline _OutputIterator num_put<_CharT, _OutputIterator>::_
   _LIBCPP_DIAGNOSTIC_PUSH
   _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
   _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
-  int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
+  int __nc = __locale::__snprintf(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
   _LIBCPP_DIAGNOSTIC_POP
   char* __ne = __nar + __nc;
   char* __np = this->__identify_padding(__nar, __ne, __iob);
@@ -1383,15 +1383,15 @@ _LIBCPP_HIDE_FROM_ABI inline _OutputIterator num_put<_CharT, _OutputIterator>::_
   _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
   _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
   if (__specify_precision)
-    __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
+    __nc = __locale::__snprintf(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
   else
-    __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
+    __nc = __locale::__snprintf(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
   unique_ptr<char, void (*)(void*)> __nbh(nullptr, free);
   if (__nc > static_cast<int>(__nbuf - 1)) {
     if (__specify_precision)
-      __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
+      __nc = __locale::__asprintf(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
     else
-      __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
+      __nc = __locale::__asprintf(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
     if (__nc == -1)
       __throw_bad_alloc();
     __nbh.reset(__nb);
@@ -1436,7 +1436,7 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_ty
   // Stage 1 - Get pointer in narrow char
   const unsigned __nbuf = 20;
   char __nar[__nbuf];
-  int __nc   = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, "%p", __v);
+  int __nc   = __locale::__snprintf(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, "%p", __v);
   char* __ne = __nar + __nc;
   char* __np = this->__identify_padding(__nar, __ne, __iob);
   // Stage 2 - Widen __nar
@@ -1998,7 +1998,7 @@ extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<wchar_t>;
 
 class _LIBCPP_EXPORTED_FROM_ABI __time_get {
 protected:
-  locale_t __loc_;
+  __locale::__locale_t __loc_;
 
   __time_get(const char* __nm);
   __time_get(const string& __nm);
@@ -2093,7 +2093,7 @@ extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<wchar_t>;
 #  endif
 
 class _LIBCPP_EXPORTED_FROM_ABI __time_put {
-  locale_t __loc_;
+  __locale::__locale_t __loc_;
 
 protected:
   _LIBCPP_HIDE_FROM_ABI __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
@@ -2926,7 +2926,7 @@ _OutputIterator money_put<_CharT, _OutputIterator>::do_put(
   unique_ptr<char_type, void (*)(void*)> __hd(0, free);
   // secure memory for digit storage
   if (static_cast<size_t>(__n) > __bs - 1) {
-    __n = __libcpp_asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units);
+    __n = __locale::__asprintf(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units);
     if (__n == -1)
       __throw_bad_alloc();
     __hn.reset(__bb);
diff --git a/libcxx/src/iostream.cpp b/libcxx/src/iostream.cpp
index 48d2fdb866a332..ed7ea207b813c5 100644
--- a/libcxx/src/iostream.cpp
+++ b/libcxx/src/iostream.cpp
@@ -107,12 +107,12 @@ alignas(wostream) _LIBCPP_EXPORTED_FROM_ABI char wclog[sizeof(wostream)]
 static void force_locale_initialization() {
 #if defined(_LIBCPP_MSVCRT_LIKE)
   static bool once = []() {
-    auto loc = newlocale(LC_ALL_MASK, "C", 0);
+    auto loc = __locale::__newlocale(LC_ALL_MASK, "C", 0);
     {
       __locale_guard g(loc); // forces initialization of locale TLS
       ((void)g);
     }
-    freelocale(loc);
+    __locale::__freelocale(loc);
     return true;
   }();
   ((void)once);
diff --git a/libcxx/src/locale.cpp b/libcxx/src/locale.cpp
index 99a2d50f207ed1..78172728432418 100644
--- a/libcxx/src/locale.cpp
+++ b/libcxx/src/locale.cpp
@@ -51,18 +51,18 @@ _LIBCPP_PUSH_MACROS
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 struct __libcpp_unique_locale {
-  __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
+  __libcpp_unique_locale(const char* nm) : __loc_(__locale::__newlocale(LC_ALL_MASK, nm, 0)) {}
 
   ~__libcpp_unique_locale() {
     if (__loc_)
-      freelocale(__loc_);
+      __locale::__freelocale(__loc_);
   }
 
   explicit operator bool() const { return __loc_; }
 
-  locale_t& get() { return __loc_; }
+  __locale::__locale_t& get() { return __loc_; }
 
-  locale_t __loc_;
+  __locale::__locale_t __loc_;
 
 private:
   __libcpp_unique_locale(__libcpp_unique_locale const&);
@@ -70,11 +70,11 @@ struct __libcpp_unique_locale {
 };
 
 #ifdef __cloc_defined
-locale_t __cloc() {
+__locale::__locale_t __cloc() {
   // In theory this could create a race condition. In practice
   // the race condition is non-fatal since it will just create
   // a little resource leak. Better approach would be appreciated.
-  static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
+  static __locale::__locale_t result = __locale::__newlocale(LC_ALL_MASK, "C", 0);
   return result;
 }
 #endif // __cloc_defined
@@ -600,7 +600,7 @@ long locale::id::__get() {
 // template <> class collate_byname<char>
 
 collate_byname<char>::collate_byname(const char* n, size_t refs)
-    : collate<char>(refs), __l_(newlocale(LC_ALL_MASK, n, 0)) {
+    : collate<char>(refs), __l_(__locale::__newlocale(LC_ALL_MASK, n, 0)) {
   if (__l_ == 0)
     __throw_runtime_error(
         ("collate_byname<char>::collate_byname"
@@ -610,7 +610,7 @@ collate_byname<char>::collate_byname(const char* n, size_t refs)
 }
 
 collate_byname<char>::collate_byname(const string& name, size_t refs)
-    : collate<char>(refs), __l_(newlocale(LC_ALL_MASK, name.c_str(), 0)) {
+    : collate<char>(refs), __l_(__locale::__newlocale(LC_ALL_MASK, name.c_str(), 0)) {
   if (__l_ == 0)
     __throw_runtime_error(
         ("collate_byname<char>::collate_byname"
@@ -619,13 +619,13 @@ collate_byname<char>::collate_byname(const string& name, size_t refs)
             .c_str());
 }
 
-collate_byname<char>::~collate_byname() { freelocale(__l_); }
+collate_byname<char>::~collate_byname() { __locale::__freelocale(__l_); }
 
 int collate_byname<char>::do_compare(
     const char_type* __lo1, const char_type* __hi1, const char_type* __lo2, const char_type* __hi2) const {
   string_type lhs(__lo1, __hi1);
   string_type rhs(__lo2, __hi2);
-  int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l_);
+  int r = __locale::__strcoll(lhs.c_str(), rhs.c_str(), __l_);
   if (r < 0)
     return -1;
   if (r > 0)
@@ -635,8 +635,8 @@ int collate_byname<char>::do_compare(
 
 collate_byname<char>::string_type collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const {
   const string_type in(lo, hi);
-  string_type out(strxfrm_l(0, in.c_str(), 0, __l_), char());
-  strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size() + 1, __l_);
+  string_type out(__locale::__strxfrm(0, in.c_str(), 0, __l_), char());
+  __locale::__strxfrm(const_cast<char*>(out.c_str()), in.c_str(), out.size() + 1, __l_);
   return out;
 }
 
@@ -644,7 +644,7 @@ collate_byname<char>::string_type collate_byname<char>::do_transform(const char_
 
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
-    : collate<wchar_t>(refs), __l_(newlocale(LC_ALL_MASK, n, 0)) {
+    : collate<wchar_t>(refs), __l_(__locale::__newlocale(LC_ALL_MASK, n, 0)) {
   if (__l_ == 0)
     __throw_runtime_error(
         ("collate_byname<wchar_t>::collate_byname(size_t refs)"
@@ -654,7 +654,7 @@ collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
 }
 
 collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
-    : collate<wchar_t>(refs), __l_(newlocale(LC_ALL_MASK, name.c_str(), 0)) {
+    : collate<wchar_t>(refs), __l_(__locale::__newlocale(LC_ALL_MASK, name.c_str(), 0)) {
   if (__l_ == 0)
     __throw_runtime_error(
         ("collate_byname<wchar_t>::collate_byname(size_t refs)"
@@ -663,13 +663,13 @@ collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
             .c_str());
 }
 
-collate_byname<wchar_t>::~collate_byname() { freelocale(__l_); }
+collate_byname<wchar_t>::~collate_byname() { __locale::__freelocale(__l_); }
 
 int collate_byname<wchar_t>::do_compare(
     const char_type* __lo1, const char_type* __hi1, const char_type* __lo2, const char_type* __hi2) const {
   string_type lhs(__lo1, __hi1);
   string_type rhs(__lo2, __hi2);
-  int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l_);
+  int r = __locale::__wcscoll(lhs.c_str(), rhs.c_str(), __l_);
   if (r < 0)
     return -1;
   if (r > 0)
@@ -680,8 +680,8 @@ int collate_byname<wchar_t>::do_compare(
 collate_byname<wchar_t>::string_type
 collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const {
   const string_type in(lo, hi);
-  string_type out(wcsxfrm_l(0, in.c_str(), 0, __l_), wchar_t());
-  wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size() + 1, __l_);
+  string_type out(__locale::__wcsxfrm(0, in.c_str(), 0, __l_), wchar_t());
+  __locale::__wcsxfrm(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size() + 1, __l_);
   return out;
 }
 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
@@ -736,7 +736,7 @@ wchar_t ctype<wchar_t>::do_toupper(char_type c) const {
 #  elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) || defined(__MVS__)
   return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
 #  else
-  return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c - L'a' + L'A' : c;
+  return (isascii(c) && __locale::__iswlower(c, _LIBCPP_GET_C_LOCALE)) ? c - L'a' + L'A' : c;
 #  endif
 }
 
@@ -747,7 +747,7 @@ const wchar_t* ctype<wchar_t>::do_toupper(char_type* low, const char_type* high)
 #  elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) || defined(__MVS__)
     *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low] : *low;
 #  else
-    *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low - L'a' + L'A') : *low;
+    *low = (isascii(*low) && __locale::__islower(*low, _LIBCPP_GET_C_LOCALE)) ? (*low - L'a' + L'A') : *low;
 #  endif
   return low;
 }
@@ -758,7 +758,7 @@ wchar_t ctype<wchar_t>::do_tolower(char_type c) const {
 #  elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) || defined(__MVS__)
   return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
 #  else
-  return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c - L'A' + 'a' : c;
+  return (isascii(c) && __locale::__isupper(c, _LIBCPP_GET_C_LOCALE)) ? c - L'A' + 'a' : c;
 #  endif
 }
 
@@ -769,7 +769,7 @@ const wchar_t* ctype<wchar_t>::do_tolower(char_type* low, const char_type* high)
 #  elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) || defined(__MVS__)
     *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low] : *low;
 #  else
-    *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low - L'A' + L'a' : *low;
+    *low = (isascii(*low) && __locale::__isupper(*low, _LIBCPP_GET_C_LOCALE)) ? *low - L'A' + L'a' : *low;
 #  endif
   return low;
 }
@@ -822,7 +822,7 @@ char ctype<char>::do_toupper(char_type c) const {
 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
   return isascii(c) ? static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
 #else
-  return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c - 'a' + 'A' : c;
+  return (isascii(c) && __locale::__islower(c, _LIBCPP_GET_C_LOCALE)) ? c - 'a' + 'A' : c;
 #endif
 }
 
@@ -835,7 +835,7 @@ const char* ctype<char>::do_toupper(char_type* low, const char_type* high) const
 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
     *low = isascii(*low) ? static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
 #else
-    *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low - 'a' + 'A' : *low;
+    *low = (isascii(*low) && __locale::__islower(*low, _LIBCPP_GET_C_LOCALE)) ? *low - 'a' + 'A' : *low;
 #endif
   return low;
 }
@@ -848,7 +848,7 @@ char ctype<char>::do_tolower(char_type c) const {
 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
   return isascii(c) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
 #else
-  return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c - 'A' + 'a' : c;
+  return (isascii(c) && __locale::__isupper(c, _LIBCPP_GET_C_LOCALE)) ? c - 'A' + 'a' : c;
 #endif
 }
 
@@ -861,7 +861,7 @@ const char* ctype<char>::do_tolower(char_type* low, const char_type* high) const
 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
     *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
 #else
-    *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low - 'A' + 'a' : *low;
+    *low = (isascii(*low) && __locale::__isupper(*low, _LIBCPP_GET_C_LOCALE)) ? *low - 'A' + 'a' : *low;
 #endif
   return low;
 }
@@ -1042,7 +1042,7 @@ const unsigned short* ctype<char>::__classic_upper_table() _NOEXCEPT {
 // template <> class ctype_byname<char>
 
 ctype_byname<char>::ctype_byname(const char* name, size_t refs)
-    : ctype<char>(0, false, refs), __l_(newlocale(LC_ALL_MASK, name, 0)) {
+    : ctype<char>(0, false, refs), __l_(__locale::__newlocale(LC_ALL_MASK, name, 0)) {
   if (__l_ == 0)
     __throw_runtime_error(
         ("ctype_byname<char>::ctype_byname"
@@ -1052,7 +1052,7 @@ ctype_byname<char>::ctype_byname(const char* name, size_t refs)
 }
 
 ctype_byname<char>::ctype_byname(const string& name, size_t refs)
-    : ctype<char>(0, false, refs), __l_(newlocale(LC_ALL_MASK, name.c_str(), 0)) {
+    : ctype<char>(0, false, refs), __l_(__locale::__newlocale(LC_ALL_MASK, name.c_str(), 0)) {
   if (__l_ == 0)
     __throw_runtime_error(
         ("ctype_byname<char>::ctype_byname"
@@ -1061,25 +1061,25 @@ ctype_byname<char>::ctype_byname(const string& name, size_t refs)
             .c_str());
 }
 
-ctype_byname<char>::~ctype_byname() { freelocale(__l_); }
+ctype_byname<char>::~ctype_byname() { __locale::__freelocale(__l_); }
 
 char ctype_byname<char>::do_toupper(char_type c) const {
-  return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l_));
+  return static_cast<char>(__locale::__toupper(static_cast<unsigned char>(c), __l_));
 }
 
 const char* ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const {
   for (; low != high; ++low)
-    *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l_));
+    *low = static_cast<char>(__locale::__toupper(static_cast<unsigned char>(*low), __l_));
   return low;
 }
 
 char ctype_byname<char>::do_tolower(char_type c) const {
-  return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l_));
+  return static_cast<char>(__locale::__tolower(static_cast<unsigned char>(c), __l_));
 }
 
 const char* ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const {
   for (; low != high; ++low)
-    *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l_));
+    *low = static_cast<char>(__locale::__tolower(static_cast<unsigned char>(*low), __l_));
   return low;
 }
 
@@ -1087,7 +1087,7 @@ const char* ctype_byname<char>::do_tolower(char_type* low, const char_type* high
 
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
-    : ctype<wchar_t>(refs), __l_(newlocale(LC_ALL_MASK, name, 0)) {
+    : ctype<wchar_t>(refs), __l_(__locale::__newlocale(LC_ALL_MASK, name, 0)) {
   if (__l_ == 0)
     __throw_runtime_error(
         ("ctype_byname<wchar_t>::ctype_byname"
@@ -1097,7 +1097,7 @@ ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
 }
 
 ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
-    : ctype<wchar_t>(refs), __l_(newlocale(LC_ALL_MASK, name.c_str(), 0)) {
+    : ctype<wchar_t>(refs), __l_(__locale::__newlocale(LC_ALL_MASK, name.c_str(), 0)) {
   if (__l_ == 0)
     __throw_runtime_error(
         ("ctype_byname<wchar_t>::ctype_byname"
@@ -1106,7 +1106,7 @@ ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
             .c_str());
 }
 
-ctype_byname<wchar_t>::~ctype_byname() { freelocale(__l_); }
+ctype_byname<wchar_t>::~ctype_byname() { __locale::__freelocale(__l_); }
 
 bool ctype_byname<wchar_t>::do_is(mask m, char_type c) const {
 #  ifdef _LIBCPP_WCTYPE_IS_MASK
@@ -1115,25 +1115,25 @@ bool ctype_byname<wchar_t>::do_is(mask m, char_type c) const {
   bool result = false;
   wint_t ch   = static_cast<wint_t>(c);
   if ((m & space) == space)
-    result |= (iswspace_l(ch, __l_) != 0);
+    result |= (__locale::__iswspace(ch, __l_) != 0);
   if ((m & print) == print)
-    result |= (iswprint_l(ch, __l_) != 0);
+    result |= (__locale::__iswprint(ch, __l_) != 0);
   if ((m & cntrl) == cntrl)
-    result |= (iswcntrl_l(ch, __l_) != 0);
+    result |= (__locale::__iswcntrl(ch, __l_) != 0);
   if ((m & upper) == upper)
-    result |= (iswupper_l(ch, __l_) != 0);
+    result |= (__locale::__iswupper(ch, __l_) != 0);
   if ((m & lower) == lower)
-    result |= (iswlower_l(ch, __l_) != 0);
+    result |= (__locale::__iswlower(ch, __l_) != 0);
   if ((m & alpha) == alpha)
-    result |= (iswalpha_l(ch, __l_) != 0);
+    result |= (__locale::__iswalpha(ch, __l_) != 0);
   if ((m & digit) == digit)
-    result |= (iswdigit_l(ch, __l_) != 0);
+    result |= (__locale::__iswdigit(ch, __l_) != 0);
   if ((m & punct) == punct)
-    result |= (iswpunct_l(ch, __l_) != 0);
+    result |= (__locale::__iswpunct(ch, __l_) != 0);
   if ((m & xdigit) == xdigit)
-    result |= (iswxdigit_l(ch, __l_) != 0);
+    result |= (__locale::__iswxdigit(ch, __l_) != 0);
   if ((m & blank) == blank)
-    result |= (iswblank_l(ch, __l_) != 0);
+    result |= (__locale::__iswblank(ch, __l_) != 0);
   return result;
 #  endif
 }
@@ -1145,31 +1145,31 @@ const wchar_t* ctype_byname<wchar_t>::do_is(const char_type* low, const char_typ
     else {
       *vec      = 0;
       wint_t ch = static_cast<wint_t>(*low);
-      if (iswspace_l(ch, __l_))
+      if (__locale::__iswspace(ch, __l_))
         *vec |= space;
 #  ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
-      if (iswprint_l(ch, __l_))
+      if (__locale::__iswprint(ch, __l_))
         *vec |= print;
 #  endif
-      if (iswcntrl_l(ch, __l_))
+      if (__locale::__iswcntrl(ch, __l_))
         *vec |= cntrl;
-      if (iswupper_l(ch, __l_))
+      if (__locale::__iswupper(ch, __l_))
         *vec |= upper;
-      if (iswlower_l(ch, __l_))
+      if (__locale::__iswlower(ch, __l_))
         *vec |= lower;
 #  ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
-      if (iswalpha_l(ch, __l_))
+      if (__locale::__iswalpha(ch, __l_))
         *vec |= alpha;
 #  endif
-      if (iswdigit_l(ch, __l_))
+      if (__locale::__iswdigit(ch, __l_))
         *vec |= digit;
-      if (iswpunct_l(ch, __l_))
+      if (__locale::__iswpunct(ch, __l_))
         *vec |= punct;
 #  ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
-      if (iswxdigit_l(ch, __l_))
+      if (__locale::__iswxdigit(ch, __l_))
         *vec |= xdigit;
 #  endif
-      if (iswblank_l(ch, __l_))
+      if (__locale::__iswblank(ch, __l_))
         *vec |= blank;
     }
   }
@@ -1183,25 +1183,25 @@ const wchar_t* ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, c
       break;
 #  else
     wint_t ch = static_cast<wint_t>(*low);
-    if ((m & space) == space && iswspace_l(ch, __l_))
+    if ((m & space) == space && __locale::__iswspace(ch, __l_))
       break;
-    if ((m & print) == print && iswprint_l(ch, __l_))
+    if ((m & print) == print && __locale::__iswprint(ch, __l_))
       break;
-    if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l_))
+    if ((m & cntrl) == cntrl && __locale::__iswcntrl(ch, __l_))
       break;
-    if ((m & upper) == upper && iswupper_l(ch, __l_))
+    if ((m & upper) == upper && __locale::__iswupper(ch, __l_))
       break;
-    if ((m & lower) == lower && iswlower_l(ch, __l_))
+    if ((m & lower) == lower && __locale::__iswlower(ch, __l_))
       break;
-    if ((m & alpha) == alpha && iswalpha_l(ch, __l_))
+    if ((m & alpha) == alpha && __locale::__iswalpha(ch, __l_))
       break;
-    if ((m & digit) == digit && iswdigit_l(ch, __l_))
+    if ((m & digit) == digit && __locale::__iswdigit(ch, __l_))
       break;
-    if ((m & punct) == punct && iswpunct_l(ch, __l_))
+    if ((m & punct) == punct && __locale::__iswpunct(ch, __l_))
       break;
-    if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l_))
+    if ((m & xdigit) == xdigit && __locale::__iswxdigit(ch, __l_))
       break;
-    if ((m & blank) == blank && iswblank_l(ch, __l_))
+    if ((m & blank) == blank && __locale::__iswblank(ch, __l_))
       break;
 #  endif
   }
@@ -1215,25 +1215,25 @@ const wchar_t* ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low,
       break;
 #  else
     wint_t ch = static_cast<wint_t>(*low);
-    if ((m & space) == space && iswspace_l(ch, __l_))
+    if ((m & space) == space && __locale::__iswspace(ch, __l_))
       continue;
-    if ((m & print) == print && iswprint_l(ch, __l_))
+    if ((m & print) == print && __locale::__iswprint(ch, __l_))
       continue;
-    if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l_))
+    if ((m & cntrl) == cntrl && __locale::__iswcntrl(ch, __l_))
       continue;
-    if ((m & upper) == upper && iswupper_l(ch, __l_))
+    if ((m & upper) == upper && __locale::__iswupper(ch, __l_))
       continue;
-    if ((m & lower) == lower && iswlower_l(ch, __l_))
+    if ((m & lower) == lower && __locale::__iswlower(ch, __l_))
       continue;
-    if ((m & alpha) == alpha && iswalpha_l(ch, __l_))
+    if ((m & alpha) == alpha && __locale::__iswalpha(ch, __l_))
       continue;
-    if ((m & digit) == digit && iswdigit_l(ch, __l_))
+    if ((m & digit) == digit && __locale::__iswdigit(ch, __l_))
       continue;
-    if ((m & punct) == punct && iswpunct_l(ch, __l_))
+    if ((m & punct) == punct && __locale::__iswpunct(ch, __l_))
       continue;
-    if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l_))
+    if ((m & xdigit) == xdigit && __locale::__iswxdigit(ch, __l_))
       continue;
-    if ((m & blank) == blank && iswblank_l(ch, __l_))
+    if ((m & blank) == blank && __locale::__iswblank(ch, __l_))
       continue;
     break;
 #  endif
@@ -1241,39 +1241,39 @@ const wchar_t* ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low,
   return low;
 }
 
-wchar_t ctype_byname<wchar_t>::do_toupper(char_type c) const { return towupper_l(c, __l_); }
+wchar_t ctype_byname<wchar_t>::do_toupper(char_type c) const { return __locale::__towupper(c, __l_); }
 
 const wchar_t* ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const {
   for (; low != high; ++low)
-    *low = towupper_l(*low, __l_);
+    *low = __locale::__towupper(*low, __l_);
   return low;
 }
 
-wchar_t ctype_byname<wchar_t>::do_tolower(char_type c) const { return towlower_l(c, __l_); }
+wchar_t ctype_byname<wchar_t>::do_tolower(char_type c) const { return __locale::__towlower(c, __l_); }
 
 const wchar_t* ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const {
   for (; low != high; ++low)
-    *low = towlower_l(*low, __l_);
+    *low = __locale::__towlower(*low, __l_);
   return low;
 }
 
-wchar_t ctype_byname<wchar_t>::do_widen(char c) const { return __libcpp_btowc_l(c, __l_); }
+wchar_t ctype_byname<wchar_t>::do_widen(char c) const { return __locale::__btowc(c, __l_); }
 
 const char* ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const {
   for (; low != high; ++low, ++dest)
-    *dest = __libcpp_btowc_l(*low, __l_);
+    *dest = __locale::__btowc(*low, __l_);
   return low;
 }
 
 char ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const {
-  int r = __libcpp_wctob_l(c, __l_);
+  int r = __locale::__wctob(c, __l_);
   return (r != EOF) ? static_cast<char>(r) : dfault;
 }
 
 const wchar_t*
 ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const {
   for (; low != high; ++low, ++dest) {
-    int r = __libcpp_wctob_l(*low, __l_);
+    int r = __locale::__wctob(*low, __l_);
     *dest = (r != EOF) ? static_cast<char>(r) : dfault;
   }
   return low;
@@ -1337,7 +1337,7 @@ constinit locale::id codecvt<wchar_t, char, mbstate_t>::id;
 codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs) : locale::facet(refs), __l_(_LIBCPP_GET_C_LOCALE) {}
 
 codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
-    : locale::facet(refs), __l_(newlocale(LC_ALL_MASK, nm, 0)) {
+    : locale::facet(refs), __l_(__locale::__newlocale(LC_ALL_MASK, nm, 0)) {
   if (__l_ == 0)
     __throw_runtime_error(
         ("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
@@ -1348,7 +1348,7 @@ codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
 
 codecvt<wchar_t, char, mbstate_t>::~codecvt() {
   if (__l_ != _LIBCPP_GET_C_LOCALE)
-    freelocale(__l_);
+    __locale::__freelocale(__l_);
 }
 
 codecvt<wchar_t, char, mbstate_t>::result codecvt<wchar_t, char, mbstate_t>::do_out(
@@ -1369,12 +1369,12 @@ codecvt<wchar_t, char, mbstate_t>::result codecvt<wchar_t, char, mbstate_t>::do_
   for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt) {
     // save state in case it is needed to recover to_nxt on error
     mbstate_t save_state = st;
-    size_t n             = __libcpp_wcsnrtombs_l(
+    size_t n             = __locale::__wcsnrtombs(
         to, &frm_nxt, static_cast<size_t>(fend - frm), static_cast<size_t>(to_end - to), &st, __l_);
     if (n == size_t(-1)) {
       // need to recover to_nxt
       for (to_nxt = to; frm != frm_nxt; ++frm) {
-        n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l_);
+        n = __locale::__wcrtomb(to_nxt, *frm, &save_state, __l_);
         if (n == size_t(-1))
           break;
         to_nxt += n;
@@ -1391,7 +1391,7 @@ codecvt<wchar_t, char, mbstate_t>::result codecvt<wchar_t, char, mbstate_t>::do_
     {
       // Try to write the terminating null
       extern_type tmp[MB_LEN_MAX];
-      n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l_);
+      n = __locale::__wcrtomb(tmp, intern_type(), &st, __l_);
       if (n == size_t(-1)) // on error
         return error;
       if (n > static_cast<size_t>(to_end - to_nxt)) // is there room?
@@ -1426,12 +1426,12 @@ codecvt<wchar_t, char, mbstate_t>::result codecvt<wchar_t, char, mbstate_t>::do_
   for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt) {
     // save state in case it is needed to recover to_nxt on error
     mbstate_t save_state = st;
-    size_t n             = __libcpp_mbsnrtowcs_l(
+    size_t n             = __locale::__mbsnrtowcs(
         to, &frm_nxt, static_cast<size_t>(fend - frm), static_cast<size_t>(to_end - to), &st, __l_);
     if (n == size_t(-1)) {
       // need to recover to_nxt
       for (to_nxt = to; frm != frm_nxt; ++to_nxt) {
-        n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend - frm), &save_state, __l_);
+        n = __locale::__mbrtowc(to_nxt, frm, static_cast<size_t>(fend - frm), &save_state, __l_);
         switch (n) {
         case 0:
           ++frm;
@@ -1458,7 +1458,7 @@ codecvt<wchar_t, char, mbstate_t>::result codecvt<wchar_t, char, mbstate_t>::do_
     if (fend != frm_end) // set up next null terminated sequence
     {
       // Try to write the terminating null
-      n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l_);
+      n = __locale::__mbrtowc(to_nxt, frm_nxt, 1, &st, __l_);
       if (n != 0) // on error
         return error;
       ++to_nxt;
@@ -1476,7 +1476,7 @@ codecvt<wchar_t, char, mbstate_t>::result codecvt<wchar_t, char, mbstate_t>::do_
     state_type& st, extern_type* to, extern_type* to_end, extern_type*& to_nxt) const {
   to_nxt = to;
   extern_type tmp[MB_LEN_MAX];
-  size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l_);
+  size_t n = __locale::__wcrtomb(tmp, intern_type(), &st, __l_);
   if (n == size_t(-1) || n == 0) // on error
     return error;
   --n;
@@ -1488,12 +1488,12 @@ codecvt<wchar_t, char, mbstate_t>::result codecvt<wchar_t, char, mbstate_t>::do_
 }
 
 int codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept {
-  if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l_) != 0)
+  if (__locale::__mbtowc(nullptr, nullptr, MB_LEN_MAX, __l_) != 0)
     return -1;
 
   // stateless encoding
-  if (__l_ == 0 || __libcpp_mb_cur_max_l(__l_) == 1) // there are no known constant length encodings
-    return 1;                                        // which take more than 1 char to form a wchar_t
+  if (__l_ == 0 || __locale::__mb_cur_max(__l_) == 1) // there are no known constant length encodings
+    return 1;                                         // which take more than 1 char to form a wchar_t
   return 0;
 }
 
@@ -1503,7 +1503,7 @@ int codecvt<wchar_t, char, mbstate_t>::do_length(
     state_type& st, const extern_type* frm, const extern_type* frm_end, size_t mx) const {
   int nbytes = 0;
   for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t) {
-    size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end - frm), &st, __l_);
+    size_t n = __locale::__mbrlen(frm, static_cast<size_t>(frm_end - frm), &st, __l_);
     switch (n) {
     case 0:
       ++nbytes;
@@ -1522,7 +1522,7 @@ int codecvt<wchar_t, char, mbstate_t>::do_length(
 }
 
 int codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept {
-  return __l_ == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l_));
+  return __l_ == 0 ? 1 : static_cast<int>(__locale::__mb_cur_max(__l_));
 }
 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
 
@@ -3931,12 +3931,12 @@ __widen_from_utf8<16>::~__widen_from_utf8() {}
 __widen_from_utf8<32>::~__widen_from_utf8() {}
 
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
-static bool checked_string_to_wchar_convert(wchar_t& dest, const char* ptr, locale_t loc) {
+static bool checked_string_to_wchar_convert(wchar_t& dest, const char* ptr, __locale::__locale_t loc) {
   if (*ptr == '\0')
     return false;
   mbstate_t mb = {};
   wchar_t out;
-  size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
+  size_t ret = __locale::__mbrtowc(&out, ptr, strlen(ptr), &mb, loc);
   if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
     return false;
   }
@@ -3957,7 +3957,7 @@ static bool is_non_breaking_space(const char* ptr) {
 }
 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
 
-static bool checked_string_to_char_convert(char& dest, const char* ptr, locale_t __loc) {
+static bool checked_string_to_char_convert(char& dest, const char* ptr, __locale::__locale_t __loc) {
   if (*ptr == '\0')
     return false;
   if (!ptr[1]) {
@@ -3972,7 +3972,7 @@ static bool checked_string_to_char_convert(char& dest, const char* ptr, locale_t
   if (!checked_string_to_wchar_convert(wout, ptr, __loc))
     return false;
   int res;
-  if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
+  if ((res = __locale::__wctob(wout, __loc)) != char_traits<char>::eof()) {
     dest = res;
     return true;
   }
@@ -4062,7 +4062,7 @@ void numpunct_byname<char>::__init(const char* nm) {
            string(nm))
               .c_str());
 
-    lconv* lc = __libcpp_localeconv_l(loc.get());
+    lconv* lc = __locale::__localeconv(loc.get());
     if (!checked_string_to_char_convert(__decimal_point_, lc->decimal_point, loc.get()))
       __decimal_point_ = base::do_decimal_point();
     if (!checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep, loc.get()))
@@ -4093,7 +4093,7 @@ void numpunct_byname<wchar_t>::__init(const char* nm) {
            string(nm))
               .c_str());
 
-    lconv* lc = __libcpp_localeconv_l(loc.get());
+    lconv* lc = __locale::__localeconv(loc.get());
     checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point, loc.get());
     checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep, loc.get());
     __grouping_ = lc->grouping;
@@ -4437,17 +4437,17 @@ const wstring& __time_get_c_storage<wchar_t>::__r() const {
 
 // time_get_byname
 
-__time_get::__time_get(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {
+__time_get::__time_get(const char* nm) : __loc_(__locale::__newlocale(LC_ALL_MASK, nm, 0)) {
   if (__loc_ == 0)
     __throw_runtime_error(("time_get_byname failed to construct for " + string(nm)).c_str());
 }
 
-__time_get::__time_get(const string& nm) : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0)) {
+__time_get::__time_get(const string& nm) : __loc_(__locale::__newlocale(LC_ALL_MASK, nm.c_str(), 0)) {
   if (__loc_ == 0)
     __throw_runtime_error(("time_get_byname failed to construct for " + nm).c_str());
 }
 
-__time_get::~__time_get() { freelocale(__loc_); }
+__time_get::~__time_get() { __locale::__freelocale(__loc_); }
 
 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmissing-field-initializers")
 
@@ -4467,7 +4467,7 @@ string __time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct) {
   char f[3] = {0};
   f[0]      = '%';
   f[1]      = fmt;
-  size_t n  = strftime_l(buf, countof(buf), f, &t, __loc_);
+  size_t n  = __locale::__strftime(buf, countof(buf), f, &t, __loc_);
   char* bb  = buf;
   char* be  = buf + n;
   string result;
@@ -4598,12 +4598,12 @@ wstring __time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& c
   char f[3] = {0};
   f[0]      = '%';
   f[1]      = fmt;
-  strftime_l(buf, countof(buf), f, &t, __loc_);
+  __locale::__strftime(buf, countof(buf), f, &t, __loc_);
   wchar_t wbuf[100];
   wchar_t* wbb   = wbuf;
   mbstate_t mb   = {0};
   const char* bb = buf;
-  size_t j       = __libcpp_mbsrtowcs_l(wbb, &bb, countof(wbuf), &mb, __loc_);
+  size_t j       = __locale::__mbsrtowcs(wbb, &bb, countof(wbuf), &mb, __loc_);
   if (j == size_t(-1))
     __throw_runtime_error("locale not supported");
   wchar_t* wbe = wbb + j;
@@ -4724,25 +4724,25 @@ void __time_get_storage<char>::init(const ctype<char>& ct) {
   // __weeks_
   for (int i = 0; i < 7; ++i) {
     t.tm_wday = i;
-    strftime_l(buf, countof(buf), "%A", &t, __loc_);
+    __locale::__strftime(buf, countof(buf), "%A", &t, __loc_);
     __weeks_[i] = buf;
-    strftime_l(buf, countof(buf), "%a", &t, __loc_);
+    __locale::__strftime(buf, countof(buf), "%a", &t, __loc_);
     __weeks_[i + 7] = buf;
   }
   // __months_
   for (int i = 0; i < 12; ++i) {
     t.tm_mon = i;
-    strftime_l(buf, countof(buf), "%B", &t, __loc_);
+    __locale::__strftime(buf, countof(buf), "%B", &t, __loc_);
     __months_[i] = buf;
-    strftime_l(buf, countof(buf), "%b", &t, __loc_);
+    __locale::__strftime(buf, countof(buf), "%b", &t, __loc_);
     __months_[i + 12] = buf;
   }
   // __am_pm_
   t.tm_hour = 1;
-  strftime_l(buf, countof(buf), "%p", &t, __loc_);
+  __locale::__strftime(buf, countof(buf), "%p", &t, __loc_);
   __am_pm_[0] = buf;
   t.tm_hour   = 13;
-  strftime_l(buf, countof(buf), "%p", &t, __loc_);
+  __locale::__strftime(buf, countof(buf), "%p", &t, __loc_);
   __am_pm_[1] = buf;
   __c_        = __analyze('c', ct);
   __r_        = __analyze('r', ct);
@@ -4761,18 +4761,18 @@ void __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct) {
   // __weeks_
   for (int i = 0; i < 7; ++i) {
     t.tm_wday = i;
-    strftime_l(buf, countof(buf), "%A", &t, __loc_);
+    __locale::__strftime(buf, countof(buf), "%A", &t, __loc_);
     mb             = mbstate_t();
     const char* bb = buf;
-    size_t j       = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
+    size_t j       = __locale::__mbsrtowcs(wbuf, &bb, countof(wbuf), &mb, __loc_);
     if (j == size_t(-1) || j == 0)
       __throw_runtime_error("locale not supported");
     wbe = wbuf + j;
     __weeks_[i].assign(wbuf, wbe);
-    strftime_l(buf, countof(buf), "%a", &t, __loc_);
+    __locale::__strftime(buf, countof(buf), "%a", &t, __loc_);
     mb = mbstate_t();
     bb = buf;
-    j  = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
+    j  = __locale::__mbsrtowcs(wbuf, &bb, countof(wbuf), &mb, __loc_);
     if (j == size_t(-1) || j == 0)
       __throw_runtime_error("locale not supported");
     wbe = wbuf + j;
@@ -4781,18 +4781,18 @@ void __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct) {
   // __months_
   for (int i = 0; i < 12; ++i) {
     t.tm_mon = i;
-    strftime_l(buf, countof(buf), "%B", &t, __loc_);
+    __locale::__strftime(buf, countof(buf), "%B", &t, __loc_);
     mb             = mbstate_t();
     const char* bb = buf;
-    size_t j       = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
+    size_t j       = __locale::__mbsrtowcs(wbuf, &bb, countof(wbuf), &mb, __loc_);
     if (j == size_t(-1) || j == 0)
       __throw_runtime_error("locale not supported");
     wbe = wbuf + j;
     __months_[i].assign(wbuf, wbe);
-    strftime_l(buf, countof(buf), "%b", &t, __loc_);
+    __locale::__strftime(buf, countof(buf), "%b", &t, __loc_);
     mb = mbstate_t();
     bb = buf;
-    j  = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
+    j  = __locale::__mbsrtowcs(wbuf, &bb, countof(wbuf), &mb, __loc_);
     if (j == size_t(-1) || j == 0)
       __throw_runtime_error("locale not supported");
     wbe = wbuf + j;
@@ -4800,19 +4800,19 @@ void __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct) {
   }
   // __am_pm_
   t.tm_hour = 1;
-  strftime_l(buf, countof(buf), "%p", &t, __loc_);
+  __locale::__strftime(buf, countof(buf), "%p", &t, __loc_);
   mb             = mbstate_t();
   const char* bb = buf;
-  size_t j       = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
+  size_t j       = __locale::__mbsrtowcs(wbuf, &bb, countof(wbuf), &mb, __loc_);
   if (j == size_t(-1))
     __throw_runtime_error("locale not supported");
   wbe = wbuf + j;
   __am_pm_[0].assign(wbuf, wbe);
   t.tm_hour = 13;
-  strftime_l(buf, countof(buf), "%p", &t, __loc_);
+  __locale::__strftime(buf, countof(buf), "%p", &t, __loc_);
   mb = mbstate_t();
   bb = buf;
-  j  = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
+  j  = __locale::__mbsrtowcs(wbuf, &bb, countof(wbuf), &mb, __loc_);
   if (j == size_t(-1))
     __throw_runtime_error("locale not supported");
   wbe = wbuf + j;
@@ -5022,26 +5022,26 @@ time_base::dateorder __time_get_storage<wchar_t>::__do_date_order() const {
 
 // time_put
 
-__time_put::__time_put(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {
+__time_put::__time_put(const char* nm) : __loc_(__locale::__newlocale(LC_ALL_MASK, nm, 0)) {
   if (__loc_ == 0)
     __throw_runtime_error(("time_put_byname failed to construct for " + string(nm)).c_str());
 }
 
-__time_put::__time_put(const string& nm) : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0)) {
+__time_put::__time_put(const string& nm) : __loc_(__locale::__newlocale(LC_ALL_MASK, nm.c_str(), 0)) {
   if (__loc_ == 0)
     __throw_runtime_error(("time_put_byname failed to construct for " + nm).c_str());
 }
 
 __time_put::~__time_put() {
   if (__loc_ != _LIBCPP_GET_C_LOCALE)
-    freelocale(__loc_);
+    __locale::__freelocale(__loc_);
 }
 
 void __time_put::__do_put(char* __nb, char*& __ne, const tm* __tm, char __fmt, char __mod) const {
   char fmt[] = {'%', __fmt, __mod, 0};
   if (__mod != 0)
     swap(fmt[1], fmt[2]);
-  size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
+  size_t n = __locale::__strftime(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
   __ne     = __nb + n;
 }
 
@@ -5052,7 +5052,7 @@ void __time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm, char __
   __do_put(__nar, __ne, __tm, __fmt, __mod);
   mbstate_t mb     = {0};
   const char* __nb = __nar;
-  size_t j         = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
+  size_t j         = __locale::__mbsrtowcs(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
   if (j == size_t(-1))
     __throw_runtime_error("locale not supported");
   __we = __wb + j;
@@ -5428,7 +5428,7 @@ void moneypunct_byname<char, false>::init(const char* nm) {
   if (!loc)
     __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
 
-  lconv* lc = __libcpp_localeconv_l(loc.get());
+  lconv* lc = __locale::__localeconv(loc.get());
   if (!checked_string_to_char_convert(__decimal_point_, lc->mon_decimal_point, loc.get()))
     __decimal_point_ = base::do_decimal_point();
   if (!checked_string_to_char_convert(__thousands_sep_, lc->mon_thousands_sep, loc.get()))
@@ -5463,7 +5463,7 @@ void moneypunct_byname<char, true>::init(const char* nm) {
   if (!loc)
     __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
 
-  lconv* lc = __libcpp_localeconv_l(loc.get());
+  lconv* lc = __locale::__localeconv(loc.get());
   if (!checked_string_to_char_convert(__decimal_point_, lc->mon_decimal_point, loc.get()))
     __decimal_point_ = base::do_decimal_point();
   if (!checked_string_to_char_convert(__thousands_sep_, lc->mon_thousands_sep, loc.get()))
@@ -5518,7 +5518,7 @@ void moneypunct_byname<wchar_t, false>::init(const char* nm) {
   __libcpp_unique_locale loc(nm);
   if (!loc)
     __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
-  lconv* lc = __libcpp_localeconv_l(loc.get());
+  lconv* lc = __locale::__localeconv(loc.get());
   if (!checked_string_to_wchar_convert(__decimal_point_, lc->mon_decimal_point, loc.get()))
     __decimal_point_ = base::do_decimal_point();
   if (!checked_string_to_wchar_convert(__thousands_sep_, lc->mon_thousands_sep, loc.get()))
@@ -5527,7 +5527,7 @@ void moneypunct_byname<wchar_t, false>::init(const char* nm) {
   wchar_t wbuf[100];
   mbstate_t mb   = {0};
   const char* bb = lc->currency_symbol;
-  size_t j       = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
+  size_t j       = __locale::__mbsrtowcs(wbuf, &bb, countof(wbuf), &mb, loc.get());
   if (j == size_t(-1))
     __throw_runtime_error("locale not supported");
   wchar_t* wbe = wbuf + j;
@@ -5541,7 +5541,7 @@ void moneypunct_byname<wchar_t, false>::init(const char* nm) {
   else {
     mb = mbstate_t();
     bb = lc->positive_sign;
-    j  = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
+    j  = __locale::__mbsrtowcs(wbuf, &bb, countof(wbuf), &mb, loc.get());
     if (j == size_t(-1))
       __throw_runtime_error("locale not supported");
     wbe = wbuf + j;
@@ -5552,7 +5552,7 @@ void moneypunct_byname<wchar_t, false>::init(const char* nm) {
   else {
     mb = mbstate_t();
     bb = lc->negative_sign;
-    j  = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
+    j  = __locale::__mbsrtowcs(wbuf, &bb, countof(wbuf), &mb, loc.get());
     if (j == size_t(-1))
       __throw_runtime_error("locale not supported");
     wbe = wbuf + j;
@@ -5573,7 +5573,7 @@ void moneypunct_byname<wchar_t, true>::init(const char* nm) {
   if (!loc)
     __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
 
-  lconv* lc = __libcpp_localeconv_l(loc.get());
+  lconv* lc = __locale::__localeconv(loc.get());
   if (!checked_string_to_wchar_convert(__decimal_point_, lc->mon_decimal_point, loc.get()))
     __decimal_point_ = base::do_decimal_point();
   if (!checked_string_to_wchar_convert(__thousands_sep_, lc->mon_thousands_sep, loc.get()))
@@ -5582,7 +5582,7 @@ void moneypunct_byname<wchar_t, true>::init(const char* nm) {
   wchar_t wbuf[100];
   mbstate_t mb   = {0};
   const char* bb = lc->int_curr_symbol;
-  size_t j       = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
+  size_t j       = __locale::__mbsrtowcs(wbuf, &bb, countof(wbuf), &mb, loc.get());
   if (j == size_t(-1))
     __throw_runtime_error("locale not supported");
   wchar_t* wbe = wbuf + j;
@@ -5600,7 +5600,7 @@ void moneypunct_byname<wchar_t, true>::init(const char* nm) {
   else {
     mb = mbstate_t();
     bb = lc->positive_sign;
-    j  = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
+    j  = __locale::__mbsrtowcs(wbuf, &bb, countof(wbuf), &mb, loc.get());
     if (j == size_t(-1))
       __throw_runtime_error("locale not supported");
     wbe = wbuf + j;
@@ -5615,7 +5615,7 @@ void moneypunct_byname<wchar_t, true>::init(const char* nm) {
   else {
     mb = mbstate_t();
     bb = lc->negative_sign;
-    j  = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
+    j  = __locale::__mbsrtowcs(wbuf, &bb, countof(wbuf), &mb, loc.get());
     if (j == size_t(-1))
       __throw_runtime_error("locale not supported");
     wbe = wbuf + j;

>From b866292750ac2b837445e690196180adcec35401 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Mon, 4 Nov 2024 10:26:28 -0500
Subject: [PATCH 2/5] Add missing include and don't modify locale_guard for now

---
 libcxx/include/__locale_dir/locale_base_api.h |  1 +
 libcxx/include/__locale_dir/locale_guard.h    | 10 +++++-----
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/libcxx/include/__locale_dir/locale_base_api.h b/libcxx/include/__locale_dir/locale_base_api.h
index 253799a049ceee..38727dfb2c666a 100644
--- a/libcxx/include/__locale_dir/locale_base_api.h
+++ b/libcxx/include/__locale_dir/locale_base_api.h
@@ -125,6 +125,7 @@
 #include <__cstddef/size_t.h>
 #include <__utility/forward.h>
 #include <string.h>
+#include <time.h>
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 #  include <wctype.h>
 #endif
diff --git a/libcxx/include/__locale_dir/locale_guard.h b/libcxx/include/__locale_dir/locale_guard.h
index 82b263de1f7f4c..e0c414c001c41f 100644
--- a/libcxx/include/__locale_dir/locale_guard.h
+++ b/libcxx/include/__locale_dir/locale_guard.h
@@ -10,7 +10,7 @@
 #define _LIBCPP___LOCALE_DIR_LOCALE_GUARD_H
 
 #include <__config>
-#include <__locale>
+#include <__locale> // for locale_t
 #include <clocale>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if defined(_LIBCPP_MSVCRT_LIKE)
 struct __locale_guard {
-  __locale_guard(__locale::__locale_t __l) : __status(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)) {
+  __locale_guard(locale_t __l) : __status(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)) {
     // Setting the locale can be expensive even when the locale given is
     // already the current locale, so do an explicit check to see if the
     // current locale is already the one we want.
@@ -59,14 +59,14 @@ struct __locale_guard {
 };
 #else
 struct __locale_guard {
-  _LIBCPP_HIDE_FROM_ABI __locale_guard(__locale::__locale_t& __loc) : __old_loc_(__locale::__uselocale(__loc)) {}
+  _LIBCPP_HIDE_FROM_ABI __locale_guard(locale_t& __loc) : __old_loc_(uselocale(__loc)) {}
 
   _LIBCPP_HIDE_FROM_ABI ~__locale_guard() {
     if (__old_loc_)
-      __locale::__uselocale(__old_loc_);
+      uselocale(__old_loc_);
   }
 
-  __locale::__locale_t __old_loc_;
+  locale_t __old_loc_;
 
   __locale_guard(__locale_guard const&)            = delete;
   __locale_guard& operator=(__locale_guard const&) = delete;

>From f4b9f313846bd45d05f6dd7e656f884606db6320 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 5 Nov 2024 10:50:46 -0500
Subject: [PATCH 3/5] Fix incorrect macro definition on GCC

---
 libcxx/include/__locale_dir/locale_base_api.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/__locale_dir/locale_base_api.h b/libcxx/include/__locale_dir/locale_base_api.h
index 38727dfb2c666a..905bfbb52714f2 100644
--- a/libcxx/include/__locale_dir/locale_base_api.h
+++ b/libcxx/include/__locale_dir/locale_base_api.h
@@ -252,7 +252,7 @@ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wformat-nonliteral") // GCC doesn't support [[g
 #ifdef _LIBCPP_COMPILER_CLANG_BASED
 #  define _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(...) _LIBCPP_ATTRIBUTE_FORMAT(__VA_ARGS__)
 #else
-#  define _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT
+#  define _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(...) /* nothing */
 #endif
 
 template <class... _Args>

>From 827f7491a97819450d07109997f3e9c8a1acd7b7 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 5 Nov 2024 10:56:11 -0500
Subject: [PATCH 4/5] Fix missing includes on Apple and FreeBSD

---
 libcxx/include/__locale_dir/locale_base_api/apple.h   | 7 +++++++
 libcxx/include/__locale_dir/locale_base_api/freebsd.h | 7 +++++++
 2 files changed, 14 insertions(+)

diff --git a/libcxx/include/__locale_dir/locale_base_api/apple.h b/libcxx/include/__locale_dir/locale_base_api/apple.h
index ec5986c3a19f10..b10059e0169e2f 100644
--- a/libcxx/include/__locale_dir/locale_base_api/apple.h
+++ b/libcxx/include/__locale_dir/locale_base_api/apple.h
@@ -10,6 +10,13 @@
 #ifndef _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_APPLE_H
 #define _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_APPLE_H
 
+#include <__config>
+#include <string.h>
+#include <time.h>
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+#  include <wctype.h>
+#endif
+
 #include <xlocale.h>
 
 #endif // _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_APPLE_H
diff --git a/libcxx/include/__locale_dir/locale_base_api/freebsd.h b/libcxx/include/__locale_dir/locale_base_api/freebsd.h
index 45ecf1977471b8..f244ecdf7cf5cf 100644
--- a/libcxx/include/__locale_dir/locale_base_api/freebsd.h
+++ b/libcxx/include/__locale_dir/locale_base_api/freebsd.h
@@ -10,6 +10,13 @@
 #ifndef _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_FREEBSD_H
 #define _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_FREEBSD_H
 
+#include <__config>
+#include <string.h>
+#include <time.h>
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+#  include <wctype.h>
+#endif
+
 #include <xlocale.h>
 
 #endif // _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_FREEBSD_H

>From 39fd6799e4b5b0f5d6d0c4e53254a67085d46f65 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 5 Nov 2024 12:58:17 -0500
Subject: [PATCH 5/5] Avoid uselocale on Win32

---
 libcxx/include/__locale_dir/locale_base_api.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libcxx/include/__locale_dir/locale_base_api.h b/libcxx/include/__locale_dir/locale_base_api.h
index 905bfbb52714f2..5725f2e191e590 100644
--- a/libcxx/include/__locale_dir/locale_base_api.h
+++ b/libcxx/include/__locale_dir/locale_base_api.h
@@ -136,7 +136,9 @@ namespace __locale {
 //
 using __locale_t = locale_t;
 
+#ifndef _LIBCPP_MSVCRT_LIKE
 inline _LIBCPP_HIDE_FROM_ABI __locale_t __uselocale(__locale_t __loc) { return uselocale(__loc); }
+#endif
 
 inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __name, __locale_t __loc) {
   return newlocale(__category_mask, __name, __loc);



More information about the libcxx-commits mailing list