[libcxx-commits] [libcxx] [libc++] Don't export ABI tagged __str_to_float_c_locale specializations on MinGW (PR #229456)
via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Oct 15 21:50:14 PDT 2026
https://github.com/Himadhith updated https://github.com/llvm/llvm-project/pull/229456
>From 63000e0de9cdfade694b3f4c134e0ebe3c06e556 Mon Sep 17 00:00:00 2001
From: himadhith <himadhith.v at ibm.com>
Date: Tue, 6 Oct 2026 11:18:24 -0400
Subject: [PATCH 1/4] [libc++] Fix ABI tag on __str_to_float_c_locale exported
specialisations on MinGW
---
libcxx/include/__locale_dir/support/windows.h | 20 +++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/libcxx/include/__locale_dir/support/windows.h b/libcxx/include/__locale_dir/support/windows.h
index e4a030c72e701b..2d264c86655717 100644
--- a/libcxx/include/__locale_dir/support/windows.h
+++ b/libcxx/include/__locale_dir/support/windows.h
@@ -175,32 +175,40 @@ _LIBCPP_EXPORTED_FROM_ABI const char* __get_locale_encoding(__locale_t __loc);
//
// the *_l functions are prefixed on Windows, only available for msvcr80+, VS2005+
+#if defined(_LIBCPP_MSVCRT)
template <class _FloatT>
_LIBCPP_HIDE_FROM_ABI _FloatT __str_to_float_c_locale(const char* __nptr, char** __endptr);
-#if defined(_LIBCPP_MSVCRT)
template <>
inline _LIBCPP_HIDE_FROM_ABI float __str_to_float_c_locale<float>(const char* __nptr, char** __endptr) {
return ::_strtof_l(__nptr, __endptr, __get_c_locale());
}
+template <>
+inline _LIBCPP_HIDE_FROM_ABI double __str_to_float_c_locale<double>(const char* __nptr, char** __endptr) {
+ return ::_strtod_l(__nptr, __endptr, __get_c_locale());
+}
+
template <>
inline _LIBCPP_HIDE_FROM_ABI long double __str_to_float_c_locale<long double>(const char* __nptr, char** __endptr) {
return ::_strtold_l(__nptr, __endptr, __get_c_locale());
}
#else
-template <>
-_LIBCPP_EXPORTED_FROM_ABI float __str_to_float_c_locale<float>(const char*, char**);
+template <class _FloatT>
+_FloatT __str_to_float_c_locale(const char* __nptr, char** __endptr);
template <>
-_LIBCPP_EXPORTED_FROM_ABI long double __str_to_float_c_locale<long double>(const char*, char**);
-#endif
+_LIBCPP_EXPORTED_FROM_ABI float __str_to_float_c_locale<float>(const char*, char**);
template <>
-inline _LIBCPP_HIDE_FROM_ABI double __str_to_float_c_locale<double>(const char* __nptr, char** __endptr) {
+_LIBCPP_HIDDEN inline double __str_to_float_c_locale<double>(const char* __nptr, char** __endptr) {
return ::_strtod_l(__nptr, __endptr, __get_c_locale());
}
+template <>
+_LIBCPP_EXPORTED_FROM_ABI long double __str_to_float_c_locale<long double>(const char*, char**);
+#endif
+
//
// Character manipulation functions
//
>From e8734033c320198f86d8ef2255750e7606b73a76 Mon Sep 17 00:00:00 2001
From: himadhith <himadhith.v at ibm.com>
Date: Thu, 8 Oct 2026 00:56:29 -0400
Subject: [PATCH 2/4] Add comments with concise explanations
---
libcxx/include/__locale_dir/support/windows.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libcxx/include/__locale_dir/support/windows.h b/libcxx/include/__locale_dir/support/windows.h
index 2d264c86655717..2920fab3f8472c 100644
--- a/libcxx/include/__locale_dir/support/windows.h
+++ b/libcxx/include/__locale_dir/support/windows.h
@@ -194,12 +194,14 @@ inline _LIBCPP_HIDE_FROM_ABI long double __str_to_float_c_locale<long double>(co
return ::_strtold_l(__nptr, __endptr, __get_c_locale());
}
#else
+// No _LIBCPP_HIDE_FROM_ABI as exported specialisations must not inherit abi_tag.
template <class _FloatT>
_FloatT __str_to_float_c_locale(const char* __nptr, char** __endptr);
template <>
_LIBCPP_EXPORTED_FROM_ABI float __str_to_float_c_locale<float>(const char*, char**);
+// _LIBCPP_HIDDEN not _LIBCPP_HIDE_FROM_ABI, can't add abi_tag when primary has none.
template <>
_LIBCPP_HIDDEN inline double __str_to_float_c_locale<double>(const char* __nptr, char** __endptr) {
return ::_strtod_l(__nptr, __endptr, __get_c_locale());
>From d5615fb2a741eae5d425c90b11999dedc44fddd5 Mon Sep 17 00:00:00 2001
From: himadhith <himadhith.v at ibm.com>
Date: Fri, 9 Oct 2026 09:25:55 -0400
Subject: [PATCH 3/4] collapse Collapse __str_to_float_c_locale<float> and
<double> to inline _strtof_l/_strtod_l on MinGW
---
libcxx/include/__locale_dir/support/windows.h | 17 +++--------------
libcxx/src/support/win32/locale_win32.cpp | 7 +------
2 files changed, 4 insertions(+), 20 deletions(-)
diff --git a/libcxx/include/__locale_dir/support/windows.h b/libcxx/include/__locale_dir/support/windows.h
index 2920fab3f8472c..60cc5ac1317865 100644
--- a/libcxx/include/__locale_dir/support/windows.h
+++ b/libcxx/include/__locale_dir/support/windows.h
@@ -175,7 +175,7 @@ _LIBCPP_EXPORTED_FROM_ABI const char* __get_locale_encoding(__locale_t __loc);
//
// the *_l functions are prefixed on Windows, only available for msvcr80+, VS2005+
-#if defined(_LIBCPP_MSVCRT)
+// _strtold_l is not available on MinGW, so long double must be split.
template <class _FloatT>
_LIBCPP_HIDE_FROM_ABI _FloatT __str_to_float_c_locale(const char* __nptr, char** __endptr);
@@ -189,24 +189,13 @@ inline _LIBCPP_HIDE_FROM_ABI double __str_to_float_c_locale<double>(const char*
return ::_strtod_l(__nptr, __endptr, __get_c_locale());
}
+#if defined(_LIBCPP_MSVCRT)
template <>
inline _LIBCPP_HIDE_FROM_ABI long double __str_to_float_c_locale<long double>(const char* __nptr, char** __endptr) {
return ::_strtold_l(__nptr, __endptr, __get_c_locale());
}
#else
-// No _LIBCPP_HIDE_FROM_ABI as exported specialisations must not inherit abi_tag.
-template <class _FloatT>
-_FloatT __str_to_float_c_locale(const char* __nptr, char** __endptr);
-
-template <>
-_LIBCPP_EXPORTED_FROM_ABI float __str_to_float_c_locale<float>(const char*, char**);
-
-// _LIBCPP_HIDDEN not _LIBCPP_HIDE_FROM_ABI, can't add abi_tag when primary has none.
-template <>
-_LIBCPP_HIDDEN inline double __str_to_float_c_locale<double>(const char* __nptr, char** __endptr) {
- return ::_strtod_l(__nptr, __endptr, __get_c_locale());
-}
-
+// No _LIBCPP_HIDE_FROM_ABI as exported specialisation must not inherit abi_tag.
template <>
_LIBCPP_EXPORTED_FROM_ABI long double __str_to_float_c_locale<long double>(const char*, char**);
#endif
diff --git a/libcxx/src/support/win32/locale_win32.cpp b/libcxx/src/support/win32/locale_win32.cpp
index a09f219e7f1bd4..7c66c22aeb1b80 100644
--- a/libcxx/src/support/win32/locale_win32.cpp
+++ b/libcxx/src/support/win32/locale_win32.cpp
@@ -298,13 +298,8 @@ const char* __get_locale_encoding(__locale_t loc) {
//
// Strtonum functions
//
+// Fallback, as long double has no _strtold_l on MinGW.
#if !defined(_LIBCPP_MSVCRT)
-template <>
-float __str_to_float_c_locale<float>(const char* nptr, char** endptr) {
- __locale_guard __current(__get_c_locale());
- return std::strtof(nptr, endptr);
-}
-
template <>
long double __str_to_float_c_locale<long double>(const char* nptr, char** endptr) {
__locale_guard __current(__get_c_locale());
>From f05b4bc53c6b7bbdf74e7c201e9d8856d1db23f7 Mon Sep 17 00:00:00 2001
From: himadhith <himadhith.v at ibm.com>
Date: Wed, 14 Oct 2026 05:46:54 -0400
Subject: [PATCH 4/4] move template funnction to plain helper and keep the ld
template to catch unsupported types
---
libcxx/include/__locale_dir/support/windows.h | 10 +++++++---
libcxx/src/support/win32/locale_win32.cpp | 6 +++---
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/libcxx/include/__locale_dir/support/windows.h b/libcxx/include/__locale_dir/support/windows.h
index 60cc5ac1317865..a72aaccccef159 100644
--- a/libcxx/include/__locale_dir/support/windows.h
+++ b/libcxx/include/__locale_dir/support/windows.h
@@ -175,7 +175,6 @@ _LIBCPP_EXPORTED_FROM_ABI const char* __get_locale_encoding(__locale_t __loc);
//
// the *_l functions are prefixed on Windows, only available for msvcr80+, VS2005+
-// _strtold_l is not available on MinGW, so long double must be split.
template <class _FloatT>
_LIBCPP_HIDE_FROM_ABI _FloatT __str_to_float_c_locale(const char* __nptr, char** __endptr);
@@ -195,9 +194,14 @@ inline _LIBCPP_HIDE_FROM_ABI long double __str_to_float_c_locale<long double>(co
return ::_strtold_l(__nptr, __endptr, __get_c_locale());
}
#else
-// No _LIBCPP_HIDE_FROM_ABI as exported specialisation must not inherit abi_tag.
+// _strtold_l is unavailable on MinGW. Export a plain (non-template) helper so
+// that no abi_tag is inherited from the primary template, then delegate to it.
+_LIBCPP_EXPORTED_FROM_ABI long double __strtold_c_locale(const char*, char**);
+
template <>
-_LIBCPP_EXPORTED_FROM_ABI long double __str_to_float_c_locale<long double>(const char*, char**);
+inline _LIBCPP_HIDE_FROM_ABI long double __str_to_float_c_locale<long double>(const char* __nptr, char** __endptr) {
+ return __strtold_c_locale(__nptr, __endptr);
+}
#endif
//
diff --git a/libcxx/src/support/win32/locale_win32.cpp b/libcxx/src/support/win32/locale_win32.cpp
index 7c66c22aeb1b80..3ab2107afa0e0a 100644
--- a/libcxx/src/support/win32/locale_win32.cpp
+++ b/libcxx/src/support/win32/locale_win32.cpp
@@ -298,10 +298,10 @@ const char* __get_locale_encoding(__locale_t loc) {
//
// Strtonum functions
//
-// Fallback, as long double has no _strtold_l on MinGW.
+// _strtold_l is unavailable on MinGW; provide a plain exported helper instead
+// so that no abi_tag is inherited by the exported symbol.
#if !defined(_LIBCPP_MSVCRT)
-template <>
-long double __str_to_float_c_locale<long double>(const char* nptr, char** endptr) {
+long double __strtold_c_locale(const char* nptr, char** endptr) {
__locale_guard __current(__get_c_locale());
return std::strtold(nptr, endptr);
}
More information about the libcxx-commits
mailing list