Skip to content

Commit 34e0f9c

Browse files
authored
[libc++] Remove the need for uselocale() (llvm#120158)
Instead of requiring `uselocale()` as part of the base locale API, define __locale_guard in the few places that need it directly, without making __locale_guard part of the base API. In practice, most mainstream platforms never used __locale_guard, so they also didn't need to define uselocale(), and after this patch they actually don't define it anymore.
1 parent 5b5b241 commit 34e0f9c

File tree

10 files changed

+68
-118
lines changed

10 files changed

+68
-118
lines changed

libcxx/include/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,6 @@ set(files
503503
__locale_dir/locale_base_api/ibm.h
504504
__locale_dir/locale_base_api/musl.h
505505
__locale_dir/locale_base_api/openbsd.h
506-
__locale_dir/locale_guard.h
507506
__locale_dir/pad_and_output.h
508507
__locale_dir/support/apple.h
509508
__locale_dir/support/bsd_like.h

libcxx/include/__locale_dir/locale_base_api.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,12 @@
2323
// Variadic functions may be implemented as templates with a parameter pack instead
2424
// of C-style variadic functions.
2525
//
26-
// TODO: I think __uselocale() is not necessary if we refactor a bit.
2726
// TODO: __localeconv shouldn't take a reference, but the Windows implementation doesn't allow copying __locale_t
2827
//
2928
// Locale management
3029
// -----------------
3130
// namespace __locale {
3231
// using __locale_t = implementation-defined;
33-
// __locale_t __uselocale(__locale_t);
3432
// __locale_t __newlocale(int, const char*, __locale_t);
3533
// void __freelocale(__locale_t);
3634
// lconv* __localeconv(__locale_t&);
@@ -139,10 +137,6 @@ namespace __locale {
139137
//
140138
using __locale_t = locale_t;
141139

142-
# ifndef _LIBCPP_MSVCRT_LIKE
143-
inline _LIBCPP_HIDE_FROM_ABI __locale_t __uselocale(__locale_t __loc) { return uselocale(__loc); }
144-
# endif
145-
146140
inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __name, __locale_t __loc) {
147141
return newlocale(__category_mask, __name, __loc);
148142
}

libcxx/include/__locale_dir/locale_base_api/bsd_locale_fallbacks.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
#define _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_BSD_LOCALE_FALLBACKS_H
1515

1616
#include <locale.h>
17-
18-
#include <__locale_dir/locale_guard.h>
1917
#include <stdarg.h>
2018
#include <stdio.h>
2119
#include <stdlib.h>
@@ -30,6 +28,20 @@
3028

3129
_LIBCPP_BEGIN_NAMESPACE_STD
3230

31+
struct __locale_guard {
32+
_LIBCPP_HIDE_FROM_ABI __locale_guard(locale_t& __loc) : __old_loc_(::uselocale(__loc)) {}
33+
34+
_LIBCPP_HIDE_FROM_ABI ~__locale_guard() {
35+
if (__old_loc_)
36+
::uselocale(__old_loc_);
37+
}
38+
39+
locale_t __old_loc_;
40+
41+
__locale_guard(__locale_guard const&) = delete;
42+
__locale_guard& operator=(__locale_guard const&) = delete;
43+
};
44+
3345
inline _LIBCPP_HIDE_FROM_ABI decltype(MB_CUR_MAX) __libcpp_mb_cur_max_l(locale_t __l) {
3446
__locale_guard __current(__l);
3547
return MB_CUR_MAX;

libcxx/include/__locale_dir/locale_guard.h

Lines changed: 0 additions & 78 deletions
This file was deleted.

libcxx/include/__locale_dir/support/bsd_like.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ namespace __locale {
3838
//
3939
using __locale_t = ::locale_t;
4040

41-
inline _LIBCPP_HIDE_FROM_ABI __locale_t __uselocale(__locale_t __loc) { return ::uselocale(__loc); }
42-
4341
inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __locale, __locale_t __base) {
4442
return ::newlocale(__category_mask, __locale, __base);
4543
}

libcxx/include/__locale_dir/support/windows.h

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,6 @@ class __locale_t {
149149
__lconv_storage* __lc_ = nullptr;
150150
};
151151

152-
// __uselocale can't be implemented on Windows because Windows allows partial modification
153-
// of thread-local locale and so _get_current_locale() returns a copy while __uselocale does
154-
// not create any copies. We can still implement RAII even without __uselocale though.
155-
__locale_t __uselocale(__locale_t) = delete;
156152
_LIBCPP_EXPORTED_FROM_ABI __locale_t __newlocale(int __mask, const char* __locale, __locale_t __base);
157153
inline _LIBCPP_HIDE_FROM_ABI void __freelocale(__locale_t __loc) { ::_free_locale(__loc); }
158154
_LIBCPP_EXPORTED_FROM_ABI lconv* __localeconv(__locale_t& __loc);
@@ -288,6 +284,44 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(__scanf__, 3, 4) int __s
288284
_LIBCPP_DIAGNOSTIC_POP
289285
#undef _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT
290286

287+
struct __locale_guard {
288+
_LIBCPP_HIDE_FROM_ABI __locale_guard(__locale_t __l) : __status(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)) {
289+
// Setting the locale can be expensive even when the locale given is
290+
// already the current locale, so do an explicit check to see if the
291+
// current locale is already the one we want.
292+
const char* __lc = __setlocale(nullptr);
293+
// If every category is the same, the locale string will simply be the
294+
// locale name, otherwise it will be a semicolon-separated string listing
295+
// each category. In the second case, we know at least one category won't
296+
// be what we want, so we only have to check the first case.
297+
if (std::strcmp(__l.__get_locale(), __lc) != 0) {
298+
__locale_all = _strdup(__lc);
299+
if (__locale_all == nullptr)
300+
__throw_bad_alloc();
301+
__setlocale(__l.__get_locale());
302+
}
303+
}
304+
_LIBCPP_HIDE_FROM_ABI ~__locale_guard() {
305+
// The CRT documentation doesn't explicitly say, but setlocale() does the
306+
// right thing when given a semicolon-separated list of locale settings
307+
// for the different categories in the same format as returned by
308+
// setlocale(LC_ALL, nullptr).
309+
if (__locale_all != nullptr) {
310+
__setlocale(__locale_all);
311+
free(__locale_all);
312+
}
313+
_configthreadlocale(__status);
314+
}
315+
_LIBCPP_HIDE_FROM_ABI static const char* __setlocale(const char* __locale) {
316+
const char* __new_locale = setlocale(LC_ALL, __locale);
317+
if (__new_locale == nullptr)
318+
__throw_bad_alloc();
319+
return __new_locale;
320+
}
321+
int __status;
322+
char* __locale_all = nullptr;
323+
};
324+
291325
} // namespace __locale
292326
_LIBCPP_END_NAMESPACE_STD
293327

libcxx/include/__support/xlocale/__nop_locale_mgmt.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ inline _LIBCPP_HIDE_FROM_ABI void freelocale(locale_t) {}
2121

2222
inline _LIBCPP_HIDE_FROM_ABI locale_t newlocale(int, const char*, locale_t) { return nullptr; }
2323

24-
inline _LIBCPP_HIDE_FROM_ABI locale_t uselocale(locale_t) { return nullptr; }
25-
2624
#define LC_COLLATE_MASK (1 << LC_COLLATE)
2725
#define LC_CTYPE_MASK (1 << LC_CTYPE)
2826
#define LC_MESSAGES_MASK (1 << LC_MESSAGES)

libcxx/include/module.modulemap

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,8 +1466,6 @@ module std [system] {
14661466

14671467
module locale {
14681468
header "locale"
1469-
1470-
module locale_guard { header "__locale_dir/locale_guard.h" }
14711469
module pad_and_output { header "__locale_dir/pad_and_output.h" }
14721470

14731471
module support {

libcxx/src/iostream.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@
1111
#include <new>
1212
#include <string>
1313

14-
#ifdef _LIBCPP_MSVCRT_LIKE
15-
# include <__locale_dir/locale_guard.h>
16-
#endif
17-
1814
#define _str(s) #s
1915
#define str(s) _str(s)
2016
#define _LIBCPP_ABI_NAMESPACE_STR str(_LIBCPP_ABI_NAMESPACE)
@@ -109,7 +105,7 @@ static void force_locale_initialization() {
109105
static bool once = []() {
110106
auto loc = __locale::__newlocale(LC_ALL_MASK, "C", 0);
111107
{
112-
__locale_guard g(loc); // forces initialization of locale TLS
108+
__locale::__locale_guard g(loc); // forces initialization of locale TLS
113109
((void)g);
114110
}
115111
__locale::__freelocale(loc);

libcxx/src/support/win32/locale_win32.cpp

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#include <__locale_dir/locale_guard.h>
109
#include <__locale_dir/support/windows.h>
1110
#include <clocale> // std::localeconv() & friends
1211
#include <cstdarg> // va_start & friends
@@ -28,7 +27,7 @@ __locale_t __newlocale(int /*mask*/, const char* locale, __locale_t /*base*/) {
2827
}
2928

3029
lconv* __localeconv(__locale_t& loc) {
31-
std::__locale_guard __current(loc);
30+
__locale_guard __current(loc);
3231
lconv* lc = std::localeconv();
3332
if (!lc)
3433
return lc;
@@ -40,12 +39,12 @@ lconv* __localeconv(__locale_t& loc) {
4039
//
4140
#if !defined(_LIBCPP_MSVCRT)
4241
float __strtof(const char* nptr, char** endptr, __locale_t loc) {
43-
std::__locale_guard __current(loc);
42+
__locale_guard __current(loc);
4443
return std::strtof(nptr, endptr);
4544
}
4645

4746
long double __strtold(const char* nptr, char** endptr, __locale_t loc) {
48-
std::__locale_guard __current(loc);
47+
__locale_guard __current(loc);
4948
return std::strtold(nptr, endptr);
5049
}
5150
#endif
@@ -55,7 +54,7 @@ long double __strtold(const char* nptr, char** endptr, __locale_t loc) {
5554
//
5655
#if defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x0800
5756
size_t __strftime(char* ret, size_t n, const char* format, const struct tm* tm, __locale_t loc) {
58-
std::__locale_guard __current(loc);
57+
__locale_guard __current(loc);
5958
return std::strftime(ret, n, format, tm);
6059
}
6160
#endif
@@ -67,18 +66,18 @@ decltype(MB_CUR_MAX) __mb_len_max(__locale_t __l) {
6766
#if defined(_LIBCPP_MSVCRT)
6867
return ::___mb_cur_max_l_func(__l);
6968
#else
70-
std::__locale_guard __current(__l);
69+
__locale_guard __current(__l);
7170
return MB_CUR_MAX;
7271
#endif
7372
}
7473

7574
wint_t __btowc(int c, __locale_t loc) {
76-
std::__locale_guard __current(loc);
75+
__locale_guard __current(loc);
7776
return std::btowc(c);
7877
}
7978

8079
int __wctob(wint_t c, __locale_t loc) {
81-
std::__locale_guard __current(loc);
80+
__locale_guard __current(loc);
8281
return std::wctob(c);
8382
}
8483

@@ -88,12 +87,12 @@ size_t __wcsnrtombs(char* __restrict dst,
8887
size_t len,
8988
mbstate_t* __restrict ps,
9089
__locale_t loc) {
91-
std::__locale_guard __current(loc);
90+
__locale_guard __current(loc);
9291
return ::wcsnrtombs(dst, src, nwc, len, ps);
9392
}
9493

9594
size_t __wcrtomb(char* __restrict s, wchar_t wc, mbstate_t* __restrict ps, __locale_t loc) {
96-
std::__locale_guard __current(loc);
95+
__locale_guard __current(loc);
9796
return std::wcrtomb(s, wc, ps);
9897
}
9998

@@ -103,24 +102,24 @@ size_t __mbsnrtowcs(wchar_t* __restrict dst,
103102
size_t len,
104103
mbstate_t* __restrict ps,
105104
__locale_t loc) {
106-
std::__locale_guard __current(loc);
105+
__locale_guard __current(loc);
107106
return ::mbsnrtowcs(dst, src, nms, len, ps);
108107
}
109108

110109
size_t
111110
__mbrtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n, mbstate_t* __restrict ps, __locale_t loc) {
112-
std::__locale_guard __current(loc);
111+
__locale_guard __current(loc);
113112
return std::mbrtowc(pwc, s, n, ps);
114113
}
115114

116115
size_t __mbrlen(const char* __restrict s, size_t n, mbstate_t* __restrict ps, __locale_t loc) {
117-
std::__locale_guard __current(loc);
116+
__locale_guard __current(loc);
118117
return std::mbrlen(s, n, ps);
119118
}
120119

121120
size_t __mbsrtowcs(
122121
wchar_t* __restrict dst, const char** __restrict src, size_t len, mbstate_t* __restrict ps, __locale_t loc) {
123-
std::__locale_guard __current(loc);
122+
__locale_guard __current(loc);
124123
return std::mbsrtowcs(dst, src, len, ps);
125124
}
126125

@@ -132,7 +131,7 @@ int __snprintf(char* ret, size_t n, __locale_t loc, const char* format, ...) {
132131
int result = ::__stdio_common_vsprintf(
133132
_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS | _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, ret, n, format, loc, ap);
134133
#else
135-
std::__locale_guard __current(loc);
134+
__locale_guard __current(loc);
136135
_LIBCPP_DIAGNOSTIC_PUSH
137136
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
138137
int result = std::vsnprintf(ret, n, format, ap);
@@ -178,7 +177,7 @@ int __libcpp_vasprintf(char** sptr, const char* __restrict format, va_list ap) {
178177
int __asprintf(char** ret, __locale_t loc, const char* format, ...) {
179178
va_list ap;
180179
va_start(ap, format);
181-
std::__locale_guard __current(loc);
180+
__locale_guard __current(loc);
182181
return __libcpp_vasprintf(ret, format, ap);
183182
}
184183

0 commit comments

Comments
 (0)