Skip to content

Commit 5d8be4c

Browse files
authored
[libc++] Define an internal locale API as a shim on top of the current one (#114596)
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.
1 parent 9b016e3 commit 5d8be4c

File tree

8 files changed

+423
-227
lines changed

8 files changed

+423
-227
lines changed

libcxx/include/__locale

+5-5
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ class _LIBCPP_TEMPLATE_VIS collate_byname;
247247

248248
template <>
249249
class _LIBCPP_EXPORTED_FROM_ABI collate_byname<char> : public collate<char> {
250-
locale_t __l_;
250+
__locale::__locale_t __l_;
251251

252252
public:
253253
typedef char char_type;
@@ -266,7 +266,7 @@ protected:
266266
#if _LIBCPP_HAS_WIDE_CHARACTERS
267267
template <>
268268
class _LIBCPP_EXPORTED_FROM_ABI collate_byname<wchar_t> : public collate<wchar_t> {
269-
locale_t __l_;
269+
__locale::__locale_t __l_;
270270

271271
public:
272272
typedef wchar_t char_type;
@@ -616,7 +616,7 @@ class _LIBCPP_TEMPLATE_VIS ctype_byname;
616616

617617
template <>
618618
class _LIBCPP_EXPORTED_FROM_ABI ctype_byname<char> : public ctype<char> {
619-
locale_t __l_;
619+
__locale::__locale_t __l_;
620620

621621
public:
622622
explicit ctype_byname(const char*, size_t = 0);
@@ -633,7 +633,7 @@ protected:
633633
#if _LIBCPP_HAS_WIDE_CHARACTERS
634634
template <>
635635
class _LIBCPP_EXPORTED_FROM_ABI ctype_byname<wchar_t> : public ctype<wchar_t> {
636-
locale_t __l_;
636+
__locale::__locale_t __l_;
637637

638638
public:
639639
explicit ctype_byname(const char*, size_t = 0);
@@ -824,7 +824,7 @@ protected:
824824
#if _LIBCPP_HAS_WIDE_CHARACTERS
825825
template <>
826826
class _LIBCPP_EXPORTED_FROM_ABI codecvt<wchar_t, char, mbstate_t> : public locale::facet, public codecvt_base {
827-
locale_t __l_;
827+
__locale::__locale_t __l_;
828828

829829
public:
830830
typedef wchar_t intern_type;

libcxx/include/__locale_dir/locale_base_api.h

+243-64
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,93 @@
1111

1212
#include <__config>
1313

14+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
15+
# pragma GCC system_header
16+
#endif
17+
18+
// The platform-specific headers have to provide the following interface.
19+
//
20+
// These functions are equivalent to their C counterparts, except that __locale::__locale_t
21+
// is used instead of the current global locale.
22+
//
23+
// Variadic functions may be implemented as templates with a parameter pack instead
24+
// of C-style variadic functions.
25+
//
26+
// TODO: I think __uselocale() is not necessary if we refactor a bit.
27+
// TODO: __localeconv shouldn't take a reference, but the Windows implementation doesn't allow copying __locale_t
28+
//
29+
// Locale management
30+
// -----------------
31+
// namespace __locale {
32+
// using __locale_t = implementation-defined;
33+
// __locale_t __uselocale(__locale_t);
34+
// __locale_t __newlocale(int, const char*, __locale_t);
35+
// void __freelocale(__locale_t);
36+
// lconv* __localeconv(__locale_t&);
37+
// }
38+
//
39+
// Strtonum functions
40+
// ------------------
41+
// namespace __locale {
42+
// float __strtof(const char*, char**, __locale_t);
43+
// double __strtod(const char*, char**, __locale_t);
44+
// long double __strtold(const char*, char**, __locale_t);
45+
// long long __strtoll(const char*, char**, __locale_t);
46+
// unsigned long long __strtoull(const char*, char**, __locale_t);
47+
// }
48+
//
49+
// Character manipulation functions
50+
// --------------------------------
51+
// namespace __locale {
52+
// int __islower(int, __locale_t);
53+
// int __isupper(int, __locale_t);
54+
// int __isdigit(int, __locale_t);
55+
// int __isxdigit(int, __locale_t);
56+
// int __toupper(int, __locale_t);
57+
// int __tolower(int, __locale_t);
58+
// int __strcoll(const char*, const char*, __locale_t);
59+
// size_t __strxfrm(char*, const char*, size_t, __locale_t);
60+
//
61+
// int __iswspace(wint_t, __locale_t);
62+
// int __iswprint(wint_t, __locale_t);
63+
// int __iswcntrl(wint_t, __locale_t);
64+
// int __iswupper(wint_t, __locale_t);
65+
// int __iswlower(wint_t, __locale_t);
66+
// int __iswalpha(wint_t, __locale_t);
67+
// int __iswblank(wint_t, __locale_t);
68+
// int __iswdigit(wint_t, __locale_t);
69+
// int __iswpunct(wint_t, __locale_t);
70+
// int __iswxdigit(wint_t, __locale_t);
71+
// wint_t __towupper(wint_t, __locale_t);
72+
// wint_t __towlower(wint_t, __locale_t);
73+
// int __wcscoll(const wchar_t*, const wchar_t*, __locale_t);
74+
// size_t __wcsxfrm(wchar_t*, const wchar_t*, size_t, __locale_t);
75+
//
76+
// size_t __strftime(char*, size_t, const char*, const tm*, __locale_t);
77+
// }
78+
//
79+
// Other functions
80+
// ---------------
81+
// namespace __locale {
82+
// implementation-defined __mb_len_max(__locale_t);
83+
// wint_t __btowc(int, __locale_t);
84+
// int __wctob(wint_t, __locale_t);
85+
// size_t __wcsnrtombs(char*, const wchar_t**, size_t, size_t, mbstate_t*, __locale_t);
86+
// size_t __wcrtomb(char*, wchar_t, mbstate_t*, __locale_t);
87+
// size_t __mbsnrtowcs(wchar_t*, const char**, size_t, size_t, mbstate_t*, __locale_t);
88+
// size_t __mbrtowc(wchar_t*, const char*, size_t, mbstate_t*, __locale_t);
89+
// int __mbtowc(wchar_t*, const char*, size_t, __locale_t);
90+
// size_t __mbrlen(const char*, size_t, mbstate_t*, __locale_t);
91+
// size_t __mbsrtowcs(wchar_t*, const char**, size_t, mbstate_t*, __locale_t);
92+
// int __snprintf(char*, size_t, __locale_t, const char*, ...);
93+
// int __asprintf(char**, __locale_t, const char*, ...);
94+
// int __sscanf(const char*, __locale_t, const char*, ...);
95+
// }
96+
97+
// TODO: This is a temporary definition to bridge between the old way we defined the locale base API
98+
// (by providing global non-reserved names) and the new API. As we move individual platforms
99+
// towards the new way of defining the locale base API, this should disappear since each platform
100+
// will define those directly.
14101
#if defined(_LIBCPP_MSVCRT_LIKE)
15102
# include <__locale_dir/locale_base_api/win32.h>
16103
#elif defined(_AIX) || defined(__MVS__)
@@ -35,71 +122,163 @@
35122
# include <__locale_dir/locale_base_api/bsd_locale_fallbacks.h>
36123
#endif
37124

38-
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
39-
# pragma GCC system_header
125+
#include <__cstddef/size_t.h>
126+
#include <__utility/forward.h>
127+
#include <ctype.h>
128+
#include <string.h>
129+
#include <time.h>
130+
#if _LIBCPP_HAS_WIDE_CHARACTERS
131+
# include <wctype.h>
132+
#endif
133+
_LIBCPP_BEGIN_NAMESPACE_STD
134+
namespace __locale {
135+
//
136+
// Locale management
137+
//
138+
using __locale_t = locale_t;
139+
140+
#ifndef _LIBCPP_MSVCRT_LIKE
141+
inline _LIBCPP_HIDE_FROM_ABI __locale_t __uselocale(__locale_t __loc) { return uselocale(__loc); }
142+
#endif
143+
144+
inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __name, __locale_t __loc) {
145+
return newlocale(__category_mask, __name, __loc);
146+
}
147+
148+
inline _LIBCPP_HIDE_FROM_ABI void __freelocale(__locale_t __loc) { freelocale(__loc); }
149+
150+
inline _LIBCPP_HIDE_FROM_ABI lconv* __localeconv(__locale_t& __loc) { return __libcpp_localeconv_l(__loc); }
151+
152+
//
153+
// Strtonum functions
154+
//
155+
inline _LIBCPP_HIDE_FROM_ABI float __strtof(const char* __nptr, char** __endptr, __locale_t __loc) {
156+
return strtof_l(__nptr, __endptr, __loc);
157+
}
158+
159+
inline _LIBCPP_HIDE_FROM_ABI double __strtod(const char* __nptr, char** __endptr, __locale_t __loc) {
160+
return strtod_l(__nptr, __endptr, __loc);
161+
}
162+
163+
inline _LIBCPP_HIDE_FROM_ABI long double __strtold(const char* __nptr, char** __endptr, __locale_t __loc) {
164+
return strtold_l(__nptr, __endptr, __loc);
165+
}
166+
167+
inline _LIBCPP_HIDE_FROM_ABI long long __strtoll(const char* __nptr, char** __endptr, int __base, __locale_t __loc) {
168+
return strtoll_l(__nptr, __endptr, __base, __loc);
169+
}
170+
171+
inline _LIBCPP_HIDE_FROM_ABI unsigned long long
172+
__strtoull(const char* __nptr, char** __endptr, int __base, __locale_t __loc) {
173+
return strtoull_l(__nptr, __endptr, __base, __loc);
174+
}
175+
176+
//
177+
// Character manipulation functions
178+
//
179+
inline _LIBCPP_HIDE_FROM_ABI int __islower(int __ch, __locale_t __loc) { return islower_l(__ch, __loc); }
180+
inline _LIBCPP_HIDE_FROM_ABI int __isupper(int __ch, __locale_t __loc) { return isupper_l(__ch, __loc); }
181+
inline _LIBCPP_HIDE_FROM_ABI int __isdigit(int __ch, __locale_t __loc) { return isdigit_l(__ch, __loc); }
182+
inline _LIBCPP_HIDE_FROM_ABI int __isxdigit(int __ch, __locale_t __loc) { return isxdigit_l(__ch, __loc); }
183+
inline _LIBCPP_HIDE_FROM_ABI int __strcoll(const char* __s1, const char* __s2, __locale_t __loc) {
184+
return strcoll_l(__s1, __s2, __loc);
185+
}
186+
inline _LIBCPP_HIDE_FROM_ABI size_t __strxfrm(char* __dest, const char* __src, size_t __n, __locale_t __loc) {
187+
return strxfrm_l(__dest, __src, __n, __loc);
188+
}
189+
inline _LIBCPP_HIDE_FROM_ABI int __toupper(int __ch, __locale_t __loc) { return toupper_l(__ch, __loc); }
190+
inline _LIBCPP_HIDE_FROM_ABI int __tolower(int __ch, __locale_t __loc) { return tolower_l(__ch, __loc); }
191+
192+
#if _LIBCPP_HAS_WIDE_CHARACTERS
193+
inline _LIBCPP_HIDE_FROM_ABI int __wcscoll(const wchar_t* __s1, const wchar_t* __s2, __locale_t __loc) {
194+
return wcscoll_l(__s1, __s2, __loc);
195+
}
196+
inline _LIBCPP_HIDE_FROM_ABI size_t __wcsxfrm(wchar_t* __dest, const wchar_t* __src, size_t __n, __locale_t __loc) {
197+
return wcsxfrm_l(__dest, __src, __n, __loc);
198+
}
199+
inline _LIBCPP_HIDE_FROM_ABI int __iswspace(wint_t __ch, __locale_t __loc) { return iswspace_l(__ch, __loc); }
200+
inline _LIBCPP_HIDE_FROM_ABI int __iswprint(wint_t __ch, __locale_t __loc) { return iswprint_l(__ch, __loc); }
201+
inline _LIBCPP_HIDE_FROM_ABI int __iswcntrl(wint_t __ch, __locale_t __loc) { return iswcntrl_l(__ch, __loc); }
202+
inline _LIBCPP_HIDE_FROM_ABI int __iswupper(wint_t __ch, __locale_t __loc) { return iswupper_l(__ch, __loc); }
203+
inline _LIBCPP_HIDE_FROM_ABI int __iswlower(wint_t __ch, __locale_t __loc) { return iswlower_l(__ch, __loc); }
204+
inline _LIBCPP_HIDE_FROM_ABI int __iswalpha(wint_t __ch, __locale_t __loc) { return iswalpha_l(__ch, __loc); }
205+
inline _LIBCPP_HIDE_FROM_ABI int __iswblank(wint_t __ch, __locale_t __loc) { return iswblank_l(__ch, __loc); }
206+
inline _LIBCPP_HIDE_FROM_ABI int __iswdigit(wint_t __ch, __locale_t __loc) { return iswdigit_l(__ch, __loc); }
207+
inline _LIBCPP_HIDE_FROM_ABI int __iswpunct(wint_t __ch, __locale_t __loc) { return iswpunct_l(__ch, __loc); }
208+
inline _LIBCPP_HIDE_FROM_ABI int __iswxdigit(wint_t __ch, __locale_t __loc) { return iswxdigit_l(__ch, __loc); }
209+
inline _LIBCPP_HIDE_FROM_ABI wint_t __towupper(wint_t __ch, __locale_t __loc) { return towupper_l(__ch, __loc); }
210+
inline _LIBCPP_HIDE_FROM_ABI wint_t __towlower(wint_t __ch, __locale_t __loc) { return towlower_l(__ch, __loc); }
40211
#endif
41212

42-
/*
43-
The platform-specific headers have to provide the following interface:
44-
45-
// TODO: rename this to __libcpp_locale_t
46-
using locale_t = implementation-defined;
47-
48-
implementation-defined __libcpp_mb_cur_max_l(locale_t);
49-
wint_t __libcpp_btowc_l(int, locale_t);
50-
int __libcpp_wctob_l(wint_t, locale_t);
51-
size_t __libcpp_wcsnrtombs_l(char* dest, const wchar_t** src, size_t wide_char_count, size_t len, mbstate_t, locale_t);
52-
size_t __libcpp_wcrtomb_l(char* str, wchar_t wide_char, mbstate_t*, locale_t);
53-
size_t __libcpp_mbsnrtowcs_l(wchar_t* dest, const char** src, size_t max_out, size_t len, mbstate_t*, locale_t);
54-
size_t __libcpp_mbrtowc_l(wchar_t* dest, cosnt char* src, size_t count, mbstate_t*, locale_t);
55-
int __libcpp_mbtowc_l(wchar_t* dest, const char* src, size_t count, locale_t);
56-
size_t __libcpp_mbrlen_l(const char* str, size_t count, mbstate_t*, locale_t);
57-
// TODO: __libcpp_localeconv_l shouldn't take a reference, but the Windows implementation doesn't allow copying locale_t
58-
lconv* __libcpp_localeconv_l(locale_t&);
59-
size_t __libcpp_mbsrtowcs_l(wchar_t* dest, const char** src, size_t len, mbstate_t*, locale_t);
60-
int __libcpp_snprintf_l(char* dest, size_t buff_size, locale_t, const char* format, ...);
61-
int __libcpp_asprintf_l(char** dest, locale_t, const char* format, ...);
62-
int __libcpp_sscanf_l(const char* dest, locale_t, const char* format, ...);
63-
64-
// TODO: change these to reserved names
65-
float strtof_l(const char* str, char** str_end, locale_t);
66-
double strtod_l(const char* str, char** str_end, locale_t);
67-
long double strtold_l(const char* str, char** str_end, locale_t);
68-
long long strtoll_l(const char* str, char** str_end, locale_t);
69-
unsigned long long strtoull_l(const char* str, char** str_end, locale_t);
70-
71-
locale_t newlocale(int category_mask, const char* locale, locale_t base);
72-
void freelocale(locale_t);
73-
74-
int islower_l(int ch, locale_t);
75-
int isupper_l(int ch, locale_t);
76-
int isdigit_l(int ch, locale_t);
77-
int isxdigit_l(int ch, locale_t);
78-
int strcoll_l(const char* lhs, const char* rhs, locale_t);
79-
size_t strxfrm_l(char* dst, const char* src, size_t n, locale_t);
80-
int wcscoll_l(const char* lhs, const char* rhs, locale_t);
81-
size_t wcsxfrm_l(wchar_t* dst, const wchar_t* src, size_t n, locale_t);
82-
int toupper_l(int ch, locale_t);
83-
int tolower_l(int ch, locale_t);
84-
int iswspace_l(wint_t ch, locale_t);
85-
int iswprint_l(wint_t ch, locale_t);
86-
int iswcntrl_l(wint_t ch, locale_t);
87-
int iswupper_l(wint_t ch, locale_t);
88-
int iswlower_l(wint_t ch, locale_t);
89-
int iswalpha_l(wint_t ch, locale_t);
90-
int iswblank_l(wint_t ch, locale_t);
91-
int iswdigit_l(wint_t ch, locale_t);
92-
int iswpunct_l(wint_t ch, locale_t);
93-
int iswxdigit_l(wint_t ch, locale_t);
94-
wint_t towupper_l(wint_t ch, locale_t);
95-
wint_t towlower_l(wint_t ch, locale_t);
96-
size_t strftime_l(char* str, size_t len, const char* format, const tm*, locale_t);
97-
98-
99-
These functions are equivalent to their C counterparts,
100-
except that locale_t is used instead of the current global locale.
101-
102-
The variadic functions may be implemented as templates with a parameter pack instead of variadic functions.
103-
*/
213+
inline _LIBCPP_HIDE_FROM_ABI size_t
214+
__strftime(char* __s, size_t __max, const char* __format, const tm* __tm, __locale_t __loc) {
215+
return strftime_l(__s, __max, __format, __tm, __loc);
216+
}
217+
218+
//
219+
// Other functions
220+
//
221+
inline _LIBCPP_HIDE_FROM_ABI decltype(__libcpp_mb_cur_max_l(__locale_t())) __mb_len_max(__locale_t __loc) {
222+
return __libcpp_mb_cur_max_l(__loc);
223+
}
224+
#if _LIBCPP_HAS_WIDE_CHARACTERS
225+
inline _LIBCPP_HIDE_FROM_ABI wint_t __btowc(int __ch, __locale_t __loc) { return __libcpp_btowc_l(__ch, __loc); }
226+
inline _LIBCPP_HIDE_FROM_ABI int __wctob(wint_t __ch, __locale_t __loc) { return __libcpp_wctob_l(__ch, __loc); }
227+
inline _LIBCPP_HIDE_FROM_ABI size_t
228+
__wcsnrtombs(char* __dest, const wchar_t** __src, size_t __nwc, size_t __len, mbstate_t* __ps, __locale_t __loc) {
229+
return __libcpp_wcsnrtombs_l(__dest, __src, __nwc, __len, __ps, __loc);
230+
}
231+
inline _LIBCPP_HIDE_FROM_ABI size_t __wcrtomb(char* __s, wchar_t __ch, mbstate_t* __ps, __locale_t __loc) {
232+
return __libcpp_wcrtomb_l(__s, __ch, __ps, __loc);
233+
}
234+
inline _LIBCPP_HIDE_FROM_ABI size_t
235+
__mbsnrtowcs(wchar_t* __dest, const char** __src, size_t __nms, size_t __len, mbstate_t* __ps, __locale_t __loc) {
236+
return __libcpp_mbsnrtowcs_l(__dest, __src, __nms, __len, __ps, __loc);
237+
}
238+
inline _LIBCPP_HIDE_FROM_ABI size_t
239+
__mbrtowc(wchar_t* __pwc, const char* __s, size_t __n, mbstate_t* __ps, __locale_t __loc) {
240+
return __libcpp_mbrtowc_l(__pwc, __s, __n, __ps, __loc);
241+
}
242+
inline _LIBCPP_HIDE_FROM_ABI int __mbtowc(wchar_t* __pwc, const char* __pmb, size_t __max, __locale_t __loc) {
243+
return __libcpp_mbtowc_l(__pwc, __pmb, __max, __loc);
244+
}
245+
inline _LIBCPP_HIDE_FROM_ABI size_t __mbrlen(const char* __s, size_t __n, mbstate_t* __ps, __locale_t __loc) {
246+
return __libcpp_mbrlen_l(__s, __n, __ps, __loc);
247+
}
248+
inline _LIBCPP_HIDE_FROM_ABI size_t
249+
__mbsrtowcs(wchar_t* __dest, const char** __src, size_t __len, mbstate_t* __ps, __locale_t __loc) {
250+
return __libcpp_mbsrtowcs_l(__dest, __src, __len, __ps, __loc);
251+
}
252+
#endif
253+
254+
_LIBCPP_DIAGNOSTIC_PUSH
255+
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wgcc-compat")
256+
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wformat-nonliteral") // GCC doesn't support [[gnu::format]] on variadic templates
257+
#ifdef _LIBCPP_COMPILER_CLANG_BASED
258+
# define _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(...) _LIBCPP_ATTRIBUTE_FORMAT(__VA_ARGS__)
259+
#else
260+
# define _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(...) /* nothing */
261+
#endif
262+
263+
template <class... _Args>
264+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(__printf__, 4, 5) int __snprintf(
265+
char* __s, size_t __n, __locale_t __loc, const char* __format, _Args&&... __args) {
266+
return __libcpp_snprintf_l(__s, __n, __loc, __format, std::forward<_Args>(__args)...);
267+
}
268+
template <class... _Args>
269+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(__printf__, 3, 4) int __asprintf(
270+
char** __s, __locale_t __loc, const char* __format, _Args&&... __args) {
271+
return __libcpp_asprintf_l(__s, __loc, __format, std::forward<_Args>(__args)...);
272+
}
273+
template <class... _Args>
274+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(__scanf__, 3, 4) int __sscanf(
275+
const char* __s, __locale_t __loc, const char* __format, _Args&&... __args) {
276+
return __libcpp_sscanf_l(__s, __loc, __format, std::forward<_Args>(__args)...);
277+
}
278+
_LIBCPP_DIAGNOSTIC_POP
279+
#undef _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT
280+
281+
} // namespace __locale
282+
_LIBCPP_END_NAMESPACE_STD
104283

105284
#endif // _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_H

libcxx/include/__locale_dir/locale_base_api/apple.h

+8
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010
#ifndef _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_APPLE_H
1111
#define _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_APPLE_H
1212

13+
#include <__config>
14+
#include <ctype.h>
15+
#include <string.h>
16+
#include <time.h>
17+
#if _LIBCPP_HAS_WIDE_CHARACTERS
18+
# include <wctype.h>
19+
#endif
20+
1321
#include <xlocale.h>
1422

1523
#endif // _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_APPLE_H

libcxx/include/__locale_dir/locale_base_api/bsd_locale_defaults.h

+1
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(__scanf__, 3, 4) int __l
109109
return ::sscanf_l(__s, __loc, __format, std::forward<_Args>(__args)...);
110110
}
111111
_LIBCPP_DIAGNOSTIC_POP
112+
#undef _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT
112113

113114
_LIBCPP_END_NAMESPACE_STD
114115

0 commit comments

Comments
 (0)