[libcxx-commits] [libcxx] [libc++] Add a thread-safe version of std::lgamma in the dylib (PR #153631)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Tue Feb 3 09:52:09 PST 2026


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

>From bec5ff793f4ec2eaafc119204450123de294fdb1 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 14 Aug 2025 13:34:33 -0400
Subject: [PATCH 1/7] [libc++] Avoid redeclaring lgamma_r

This causes issues when building with modules, and redeclaring functions
provided by another library (here the C library) is bad hygiene. Instead,
use <math.h> to access the declaration provided by the system.

As a drive-by, this also starts using ::lgamma_r instead of ::lgamma when
building on top of LLVM-libc. We didn't do that previously due to a
declration conflict, but using the _r version when we can should only
make things thread safe.
---
 libcxx/include/__configuration/availability.h | 13 +++++++
 libcxx/include/__math/gamma.h                 | 25 ++++++++++++++
 .../include/__random/binomial_distribution.h  | 34 +++----------------
 libcxx/src/CMakeLists.txt                     |  1 +
 libcxx/src/math.cpp                           | 26 ++++++++++++++
 5 files changed, 70 insertions(+), 29 deletions(-)
 create mode 100644 libcxx/src/math.cpp

diff --git a/libcxx/include/__configuration/availability.h b/libcxx/include/__configuration/availability.h
index 5433df872fa39..c1032b3ac26a2 100644
--- a/libcxx/include/__configuration/availability.h
+++ b/libcxx/include/__configuration/availability.h
@@ -84,6 +84,9 @@
 // in all versions of the library are available.
 #if !_LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS
 
+#  define _LIBCPP_INTRODUCED_IN_LLVM_22 1
+#  define _LIBCPP_INTRODUCED_IN_LLVM_22_ATTRIBUTE /* nothing */
+
 #  define _LIBCPP_INTRODUCED_IN_LLVM_21 1
 #  define _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE /* nothing */
 
@@ -112,6 +115,11 @@
 
 // clang-format off
 
+// LLVM 22
+// TODO: Fill this in
+#  define _LIBCPP_INTRODUCED_IN_LLVM_22 0
+#  define _LIBCPP_INTRODUCED_IN_LLVM_22_ATTRIBUTE __attribute__((unavailable))
+
 // LLVM 21
 // TODO: Fill this in
 #  define _LIBCPP_INTRODUCED_IN_LLVM_21 0
@@ -317,6 +325,11 @@
 #define _LIBCPP_AVAILABILITY_HAS_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE _LIBCPP_INTRODUCED_IN_LLVM_21
 // No attribute, since we've had bad_function_call::what() in the headers before
 
+// This controls whether we provide an implementation of a thread safe variant of the `std::lgamma`
+// function in the dylib.
+#define _LIBCPP_AVAILABILITY_HAS_THREAD_SAFE_LGAMMA _LIBCPP_INTRODUCED_IN_LLVM_22
+// No attribute, since we call ::lgamma_r instead
+
 // Define availability attributes that depend on both
 // _LIBCPP_HAS_EXCEPTIONS and _LIBCPP_HAS_RTTI.
 #if !_LIBCPP_HAS_EXCEPTIONS || !_LIBCPP_HAS_RTTI
diff --git a/libcxx/include/__math/gamma.h b/libcxx/include/__math/gamma.h
index 693e111a84e99..66fce3b5646de 100644
--- a/libcxx/include/__math/gamma.h
+++ b/libcxx/include/__math/gamma.h
@@ -55,6 +55,31 @@ inline _LIBCPP_HIDE_FROM_ABI double tgamma(_A1 __x) _NOEXCEPT {
   return __builtin_tgamma((double)__x);
 }
 
+// __lgamma_r
+
+struct __lgamma_result {
+  double __result;
+  int __sign;
+};
+
+#if _LIBCPP_AVAILABILITY_HAS_THREAD_SAFE_LGAMMA
+_LIBCPP_EXPORTED_FROM_ABI __lgamma_result __lgamma_thread_safe_impl(double) _NOEXCEPT;
+
+inline _LIBCPP_HIDE_FROM_ABI __lgamma_result __lgamma_thread_safe(double __d) _NOEXCEPT {
+  return __math::__lgamma_thread_safe_impl(__d);
+}
+#else
+// When deploying to older targets, call `lgamma_r` directly but avoid declaring the actual
+// function since different platforms declare the function slightly differently.
+double __lgamma_r_shim(double, int*) _NOEXCEPT __asm__("lgamma_r");
+
+inline _LIBCPP_HIDE_FROM_ABI __lgamma_result __lgamma_thread_safe(double __d) _NOEXCEPT {
+  int __sign;
+  double __res = __math::__lgamma_r_shim(__d, &__sign);
+  return __lgamma_result{__res, __sign};
+}
+#endif
+
 } // namespace __math
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__random/binomial_distribution.h b/libcxx/include/__random/binomial_distribution.h
index bada8cfdd74a3..2b74c592306b9 100644
--- a/libcxx/include/__random/binomial_distribution.h
+++ b/libcxx/include/__random/binomial_distribution.h
@@ -10,6 +10,7 @@
 #define _LIBCPP___RANDOM_BINOMIAL_DISTRIBUTION_H
 
 #include <__config>
+#include <__math/gamma.h>
 #include <__random/is_valid.h>
 #include <__random/uniform_real_distribution.h>
 #include <cmath>
@@ -97,39 +98,14 @@ class binomial_distribution {
   }
 };
 
-// Some libc declares the math functions to be `noexcept`.
-#if defined(_LIBCPP_GLIBC_PREREQ)
-#  if _LIBCPP_GLIBC_PREREQ(2, 8)
-#    define _LIBCPP_LGAMMA_R_NOEXCEPT _NOEXCEPT
-#  else
-#    define _LIBCPP_LGAMMA_R_NOEXCEPT
-#  endif
-#elif defined(__LLVM_LIBC__)
-#  define _LIBCPP_LGAMMA_R_NOEXCEPT _NOEXCEPT
-#else
-#  define _LIBCPP_LGAMMA_R_NOEXCEPT
-#endif
-
-#if !defined(_LIBCPP_MSVCRT_LIKE)
-extern "C" double lgamma_r(double, int*) _LIBCPP_LGAMMA_R_NOEXCEPT;
-#endif
-
-inline _LIBCPP_HIDE_FROM_ABI double __libcpp_lgamma(double __d) {
-#if defined(_LIBCPP_MSVCRT_LIKE)
-  return lgamma(__d);
-#else
-  int __sign;
-  return lgamma_r(__d, &__sign);
-#endif
-}
-
 template <class _IntType>
 binomial_distribution<_IntType>::param_type::param_type(result_type __t, double __p) : __t_(__t), __p_(__p) {
   if (0 < __p_ && __p_ < 1) {
     __r0_ = static_cast<result_type>((__t_ + 1) * __p_);
-    __pr_ = std::exp(
-        std::__libcpp_lgamma(__t_ + 1.) - std::__libcpp_lgamma(__r0_ + 1.) - std::__libcpp_lgamma(__t_ - __r0_ + 1.) +
-        __r0_ * std::log(__p_) + (__t_ - __r0_) * std::log(1 - __p_));
+    __pr_ =
+        std::exp(__math::__lgamma_thread_safe(__t_ + 1.).__result - __math::__lgamma_thread_safe(__r0_ + 1.).__result -
+                 __math::__lgamma_thread_safe(__t_ - __r0_ + 1.).__result + __r0_ * std::log(__p_) +
+                 (__t_ - __r0_) * std::log(1 - __p_));
     __odds_ratio_ = __p_ / (1 - __p_);
   }
 }
diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt
index f59fe0e08fccb..16e9a2e163dad 100644
--- a/libcxx/src/CMakeLists.txt
+++ b/libcxx/src/CMakeLists.txt
@@ -30,6 +30,7 @@ set(LIBCXX_SOURCES
   include/ryu/ryu.h
   include/to_chars_floating_point.h
   include/from_chars_floating_point.h
+  math.cpp
   memory.cpp
   memory_resource.cpp
   new_handler.cpp
diff --git a/libcxx/src/math.cpp b/libcxx/src/math.cpp
new file mode 100644
index 0000000000000..2b33f919a4d70
--- /dev/null
+++ b/libcxx/src/math.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifdef __APPLE__
+#  define _REENTRANT
+#endif
+
+#include <cmath>
+#include <math.h> // for lgamma_r
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+namespace __math {
+
+_LIBCPP_EXPORTED_FROM_ABI __lgamma_result __lgamma_thread_safe_impl(double __d) noexcept {
+  int __sign;
+  double __result = ::lgamma_r(__d, &__sign);
+  return __lgamma_result{__result, __sign};
+}
+
+} // namespace __math
+_LIBCPP_END_NAMESPACE_STD

>From f580f124da9220fa1071c892bb2aa1639fdf80db Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 16 Sep 2025 16:00:22 -0400
Subject: [PATCH 2/7] Handle ABIlist

---
 libcxx/lib/abi/CHANGELOG.TXT                           | 10 ++++++++++
 ...darwin.libcxxabi.v1.stable.exceptions.nonew.abilist |  1 +
 ...roid21.libcxxabi.v1.stable.exceptions.nonew.abilist |  1 +
 ...bm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist |  1 +
 ...bm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist |  1 +
 ...darwin.libcxxabi.v1.stable.exceptions.nonew.abilist |  1 +
 ...roid21.libcxxabi.v1.stable.exceptions.nonew.abilist |  1 +
 ...reebsd.libcxxabi.v1.stable.exceptions.nonew.abilist |  1 +
 ...ux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist |  1 +
 ...-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist |  1 +
 10 files changed, 19 insertions(+)

diff --git a/libcxx/lib/abi/CHANGELOG.TXT b/libcxx/lib/abi/CHANGELOG.TXT
index 968dc7a22a8c7..f6064bf052687 100644
--- a/libcxx/lib/abi/CHANGELOG.TXT
+++ b/libcxx/lib/abi/CHANGELOG.TXT
@@ -16,6 +16,16 @@ New entries should be added directly below the "Version" header.
 Version 22.0
 ------------
 
+* [libc++] Add a thread-safe version of std::lgamma in the dylib
+
+  This patch adds a new function __lgamma_thread_safe in the dylib to avoid having to redeclare
+  ::lgamma_r within libc++'s own headers. This merely introduces a new symbol so it's not an ABI
+  break.
+
+  All platforms
+  -------------
+  Symbol added: _ZNSt3__16__math25__lgamma_thread_safe_implEd
+
 * [libc++] Remove __time_get_storage::{__analyze,init} from the ABI
 
   These functions have never been used outside the dylib, so there is no point in exporting them.
diff --git a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
index 3a1d8950c2db0..f5da8dabefe48 100644
--- a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1692,6 +1692,7 @@
 {'is_defined': True, 'name': '__ZNSt3__15wcoutE', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__16__itoa8__u64toaEyPc', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
index 313de84df20e8..92dedea3e6a1b 100644
--- a/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1329,6 +1329,7 @@
 {'is_defined': True, 'name': '_ZNSt6__ndk16__clocEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk16__itoa8__u32toaEjPc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk16__itoa8__u64toaEyPc', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt6__ndk16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
index 99cde72885cf2..f1244d12570c1 100644
--- a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -677,6 +677,7 @@
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEyPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12steady_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock11from_time_tEi', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
index 577d6cf759a77..af16461b1cd78 100644
--- a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -677,6 +677,7 @@
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12steady_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock11from_time_tEl', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
index 5173a1a76b81a..5361d12bbd0c8 100644
--- a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1691,6 +1691,7 @@
 {'is_defined': True, 'name': '__ZNSt3__15wcoutE', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__16__itoa8__u64toaEyPc', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
index 1be7d8a2ac20b..e8a420e4e9122 100644
--- a/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1329,6 +1329,7 @@
 {'is_defined': True, 'name': '_ZNSt6__ndk16__clocEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk16__itoa8__u32toaEjPc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk16__itoa8__u64toaEmPc', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt6__ndk16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
index 40ae625d3bd69..bd2208f403d5b 100644
--- a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1342,6 +1342,7 @@
 {'is_defined': True, 'name': '_ZNSt3__15wcoutE', 'size': 384, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
index 90166073b135f..bd2303afa3222 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1341,6 +1341,7 @@
 {'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
index 5855c17cf11ed..eb7566ffe951c 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
@@ -1312,6 +1312,7 @@
 {'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}

>From 58a05fdd246d4781208647f7d2dd35f5beed41ba Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 17 Sep 2025 13:54:07 -0400
Subject: [PATCH 3/7] Link against -lm

---
 libcxx/CMakeLists.txt        | 4 ++++
 libcxx/cmake/config-ix.cmake | 6 ++++++
 2 files changed, 10 insertions(+)

diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt
index 1423b6713fd35..b959f2f244be9 100644
--- a/libcxx/CMakeLists.txt
+++ b/libcxx/CMakeLists.txt
@@ -681,6 +681,10 @@ function(cxx_link_system_libraries target)
     target_link_libraries(${target} PRIVATE atomic)
   endif()
 
+  if (LIBCXX_HAS_MATH_LIB)
+    target_link_libraries(${target} PRIVATE m)
+  endif()
+
   if (MINGW)
     target_link_libraries(${target} PRIVATE "${MINGW_LIBRARIES}")
   endif()
diff --git a/libcxx/cmake/config-ix.cmake b/libcxx/cmake/config-ix.cmake
index 270d80575adcf..80eeda05b302a 100644
--- a/libcxx/cmake/config-ix.cmake
+++ b/libcxx/cmake/config-ix.cmake
@@ -110,24 +110,30 @@ if(WIN32 AND NOT MINGW)
   set(LIBCXX_HAS_PTHREAD_LIB NO)
   set(LIBCXX_HAS_RT_LIB NO)
   set(LIBCXX_HAS_ATOMIC_LIB NO)
+  set(LIBCXX_HAS_MATH_LIB NO)
 elseif(APPLE)
   set(LIBCXX_HAS_PTHREAD_LIB NO)
   set(LIBCXX_HAS_RT_LIB NO)
   set(LIBCXX_HAS_ATOMIC_LIB NO)
+  set(LIBCXX_HAS_MATH_LIB NO)
 elseif(FUCHSIA)
   set(LIBCXX_HAS_PTHREAD_LIB NO)
   set(LIBCXX_HAS_RT_LIB NO)
   check_library_exists(atomic __atomic_fetch_add_8 "" LIBCXX_HAS_ATOMIC_LIB)
+  set(LIBCXX_HAS_MATH_LIB NO)
 elseif(ANDROID)
   set(LIBCXX_HAS_PTHREAD_LIB NO)
   set(LIBCXX_HAS_RT_LIB NO)
   set(LIBCXX_HAS_ATOMIC_LIB NO)
+  set(LIBCXX_HAS_MATH_LIB NO)
 elseif(PICOLIBC)
   set(LIBCXX_HAS_PTHREAD_LIB NO)
   set(LIBCXX_HAS_RT_LIB NO)
   set(LIBCXX_HAS_ATOMIC_LIB NO)
+  set(LIBCXX_HAS_MATH_LIB NO)
 else()
   check_library_exists(pthread pthread_create "" LIBCXX_HAS_PTHREAD_LIB)
   check_library_exists(rt clock_gettime "" LIBCXX_HAS_RT_LIB)
   check_library_exists(atomic __atomic_fetch_add_8 "" LIBCXX_HAS_ATOMIC_LIB)
+  check_library_exists(m lgamma_r "" LIBCXX_HAS_MATH_LIB)
 endif()

>From fac6c316ae853c96215893ce59becb8ade2f1523 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Mon, 17 Nov 2025 16:59:39 -0500
Subject: [PATCH 4/7] Workaround broken flag detection on GCC

---
 libcxx/cmake/config-ix.cmake | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/libcxx/cmake/config-ix.cmake b/libcxx/cmake/config-ix.cmake
index 80eeda05b302a..91f9737d5710b 100644
--- a/libcxx/cmake/config-ix.cmake
+++ b/libcxx/cmake/config-ix.cmake
@@ -135,5 +135,7 @@ else()
   check_library_exists(pthread pthread_create "" LIBCXX_HAS_PTHREAD_LIB)
   check_library_exists(rt clock_gettime "" LIBCXX_HAS_RT_LIB)
   check_library_exists(atomic __atomic_fetch_add_8 "" LIBCXX_HAS_ATOMIC_LIB)
-  check_library_exists(m lgamma_r "" LIBCXX_HAS_MATH_LIB)
+  if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+    set(LIBCXX_HAS_MATH_LIB ON)
+  endif()
 endif()

>From 5f5e5434b39e79a90394065392e33b8ca01c8ebf Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Mon, 17 Nov 2025 17:03:58 -0500
Subject: [PATCH 5/7] Remove EXPORTED_FROM_ABI

---
 libcxx/src/math.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/src/math.cpp b/libcxx/src/math.cpp
index 2b33f919a4d70..d8cbab2bcbecd 100644
--- a/libcxx/src/math.cpp
+++ b/libcxx/src/math.cpp
@@ -16,7 +16,7 @@
 _LIBCPP_BEGIN_NAMESPACE_STD
 namespace __math {
 
-_LIBCPP_EXPORTED_FROM_ABI __lgamma_result __lgamma_thread_safe_impl(double __d) noexcept {
+__lgamma_result __lgamma_thread_safe_impl(double __d) noexcept {
   int __sign;
   double __result = ::lgamma_r(__d, &__sign);
   return __lgamma_result{__result, __sign};

>From 72280379f482bd23d588850f81b443b07cbc79bc Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Mon, 17 Nov 2025 17:08:56 -0500
Subject: [PATCH 6/7] Move out of __math namespace

---
 libcxx/include/__math/gamma.h                             | 8 ++++----
 libcxx/include/__random/binomial_distribution.h           | 7 +++----
 libcxx/lib/abi/CHANGELOG.TXT                              | 2 +-
 ...le-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist | 2 +-
 ...c-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist | 2 +-
 ...4-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist | 2 +-
 ...le-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist | 2 +-
 ...n-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist | 2 +-
 ...linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist | 2 +-
 ...nux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist | 2 +-
 libcxx/src/math.cpp                                       | 2 --
 11 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/libcxx/include/__math/gamma.h b/libcxx/include/__math/gamma.h
index 66fce3b5646de..4d3c4d5d54c19 100644
--- a/libcxx/include/__math/gamma.h
+++ b/libcxx/include/__math/gamma.h
@@ -55,6 +55,8 @@ inline _LIBCPP_HIDE_FROM_ABI double tgamma(_A1 __x) _NOEXCEPT {
   return __builtin_tgamma((double)__x);
 }
 
+} // namespace __math
+
 // __lgamma_r
 
 struct __lgamma_result {
@@ -66,7 +68,7 @@ struct __lgamma_result {
 _LIBCPP_EXPORTED_FROM_ABI __lgamma_result __lgamma_thread_safe_impl(double) _NOEXCEPT;
 
 inline _LIBCPP_HIDE_FROM_ABI __lgamma_result __lgamma_thread_safe(double __d) _NOEXCEPT {
-  return __math::__lgamma_thread_safe_impl(__d);
+  return std::__lgamma_thread_safe_impl(__d);
 }
 #else
 // When deploying to older targets, call `lgamma_r` directly but avoid declaring the actual
@@ -75,13 +77,11 @@ double __lgamma_r_shim(double, int*) _NOEXCEPT __asm__("lgamma_r");
 
 inline _LIBCPP_HIDE_FROM_ABI __lgamma_result __lgamma_thread_safe(double __d) _NOEXCEPT {
   int __sign;
-  double __res = __math::__lgamma_r_shim(__d, &__sign);
+  double __res = std::__lgamma_r_shim(__d, &__sign);
   return __lgamma_result{__res, __sign};
 }
 #endif
 
-} // namespace __math
-
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP___MATH_GAMMA_H
diff --git a/libcxx/include/__random/binomial_distribution.h b/libcxx/include/__random/binomial_distribution.h
index 2b74c592306b9..f0d76be89bf5e 100644
--- a/libcxx/include/__random/binomial_distribution.h
+++ b/libcxx/include/__random/binomial_distribution.h
@@ -102,10 +102,9 @@ template <class _IntType>
 binomial_distribution<_IntType>::param_type::param_type(result_type __t, double __p) : __t_(__t), __p_(__p) {
   if (0 < __p_ && __p_ < 1) {
     __r0_ = static_cast<result_type>((__t_ + 1) * __p_);
-    __pr_ =
-        std::exp(__math::__lgamma_thread_safe(__t_ + 1.).__result - __math::__lgamma_thread_safe(__r0_ + 1.).__result -
-                 __math::__lgamma_thread_safe(__t_ - __r0_ + 1.).__result + __r0_ * std::log(__p_) +
-                 (__t_ - __r0_) * std::log(1 - __p_));
+    __pr_ = std::exp(std::__lgamma_thread_safe(__t_ + 1.).__result - std::__lgamma_thread_safe(__r0_ + 1.).__result -
+                     std::__lgamma_thread_safe(__t_ - __r0_ + 1.).__result + __r0_ * std::log(__p_) +
+                     (__t_ - __r0_) * std::log(1 - __p_));
     __odds_ratio_ = __p_ / (1 - __p_);
   }
 }
diff --git a/libcxx/lib/abi/CHANGELOG.TXT b/libcxx/lib/abi/CHANGELOG.TXT
index f6064bf052687..8910838d225ce 100644
--- a/libcxx/lib/abi/CHANGELOG.TXT
+++ b/libcxx/lib/abi/CHANGELOG.TXT
@@ -24,7 +24,7 @@ Version 22.0
 
   All platforms
   -------------
-  Symbol added: _ZNSt3__16__math25__lgamma_thread_safe_implEd
+  Symbol added: _ZNSt3__125__lgamma_thread_safe_implEd
 
 * [libc++] Remove __time_get_storage::{__analyze,init} from the ABI
 
diff --git a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
index f5da8dabefe48..7659c3c60d927 100644
--- a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1692,7 +1692,7 @@
 {'is_defined': True, 'name': '__ZNSt3__15wcoutE', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__16__itoa8__u64toaEyPc', 'type': 'FUNC'}
-{'is_defined': True, 'name': '__ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__125__lgamma_thread_safe_implEd', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
index f1244d12570c1..7132aab13318a 100644
--- a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -677,7 +677,7 @@
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEyPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
-{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__125__lgamma_thread_safe_implEd', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12steady_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock11from_time_tEi', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
index af16461b1cd78..c357d04e33fc5 100644
--- a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -677,7 +677,7 @@
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
-{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__125__lgamma_thread_safe_implEd', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12steady_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock11from_time_tEl', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
index 5361d12bbd0c8..8936296d7da81 100644
--- a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1691,7 +1691,7 @@
 {'is_defined': True, 'name': '__ZNSt3__15wcoutE', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__16__itoa8__u64toaEyPc', 'type': 'FUNC'}
-{'is_defined': True, 'name': '__ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__125__lgamma_thread_safe_implEd', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
index bd2208f403d5b..3b99f20c111de 100644
--- a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1342,7 +1342,7 @@
 {'is_defined': True, 'name': '_ZNSt3__15wcoutE', 'size': 384, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__125__lgamma_thread_safe_implEd', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
index bd2303afa3222..cd538a2e5b0b9 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1341,7 +1341,7 @@
 {'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__125__lgamma_thread_safe_implEd', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
index eb7566ffe951c..3d8ea59c28bd5 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
@@ -1312,7 +1312,7 @@
 {'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__125__lgamma_thread_safe_implEd', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}
diff --git a/libcxx/src/math.cpp b/libcxx/src/math.cpp
index d8cbab2bcbecd..84c323e1a0b49 100644
--- a/libcxx/src/math.cpp
+++ b/libcxx/src/math.cpp
@@ -14,7 +14,6 @@
 #include <math.h> // for lgamma_r
 
 _LIBCPP_BEGIN_NAMESPACE_STD
-namespace __math {
 
 __lgamma_result __lgamma_thread_safe_impl(double __d) noexcept {
   int __sign;
@@ -22,5 +21,4 @@ __lgamma_result __lgamma_thread_safe_impl(double __d) noexcept {
   return __lgamma_result{__result, __sign};
 }
 
-} // namespace __math
 _LIBCPP_END_NAMESPACE_STD

>From b0cd4891a37a0bfca47dd3a77c87d444d3a2eb20 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 3 Feb 2026 12:51:51 -0500
Subject: [PATCH 7/7] Update for LLVM 23

---
 libcxx/include/__configuration/availability.h     | 10 +++++++++-
 libcxx/lib/abi/CHANGELOG.TXT                      |  8 ++++++--
 libcxx/utils/libcxx/test/features/availability.py |  9 ++++++++-
 3 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/libcxx/include/__configuration/availability.h b/libcxx/include/__configuration/availability.h
index 79c33e6c96e45..1a79181739d41 100644
--- a/libcxx/include/__configuration/availability.h
+++ b/libcxx/include/__configuration/availability.h
@@ -39,6 +39,9 @@
 // in all versions of the library are available.
 #if !_LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS
 
+#  define _LIBCPP_INTRODUCED_IN_LLVM_23 1
+#  define _LIBCPP_INTRODUCED_IN_LLVM_23_ATTRIBUTE /* nothing */
+
 #  define _LIBCPP_INTRODUCED_IN_LLVM_22 1
 #  define _LIBCPP_INTRODUCED_IN_LLVM_22_ATTRIBUTE /* nothing */
 
@@ -70,6 +73,11 @@
 
 // clang-format off
 
+// LLVM 23
+// TODO: Fill this in
+#  define _LIBCPP_INTRODUCED_IN_LLVM_23 0
+#  define _LIBCPP_INTRODUCED_IN_LLVM_23_ATTRIBUTE __attribute__((unavailable))
+
 // LLVM 22
 // TODO: Fill this in
 #  define _LIBCPP_INTRODUCED_IN_LLVM_22 0
@@ -297,7 +305,7 @@
 
 // This controls whether we provide an implementation of a thread safe variant of the `std::lgamma`
 // function in the dylib.
-#define _LIBCPP_AVAILABILITY_HAS_THREAD_SAFE_LGAMMA _LIBCPP_INTRODUCED_IN_LLVM_22
+#define _LIBCPP_AVAILABILITY_HAS_THREAD_SAFE_LGAMMA _LIBCPP_INTRODUCED_IN_LLVM_23
 // No attribute, since we call ::lgamma_r instead
 
 // Only define a bunch of symbols in the dylib if we need to be compatible with LLVM 7 headers or older
diff --git a/libcxx/lib/abi/CHANGELOG.TXT b/libcxx/lib/abi/CHANGELOG.TXT
index 87a00d4c717de..62f0e5ed92408 100644
--- a/libcxx/lib/abi/CHANGELOG.TXT
+++ b/libcxx/lib/abi/CHANGELOG.TXT
@@ -13,7 +13,7 @@ To generate a summary, re-generate the new ABI list using the
 New entries should be added directly below the "Version" header.
 
 ------------
-Version 22.0
+Version 23.0
 ------------
 
 * [libc++] Add a thread-safe version of std::lgamma in the dylib
@@ -26,9 +26,13 @@ Version 22.0
   -------------
   Symbol added: _ZNSt3__125__lgamma_thread_safe_implEd
 
+------------
+Version 22.0
+------------
+
 * [libc++] Allows any types of size 4 and 8 to use native platform ulock_wait
 
-  This patch added symbols for platform wait functions with the size of the type 
+  This patch added symbols for platform wait functions with the size of the type
 
   All platforms
   -------------
diff --git a/libcxx/utils/libcxx/test/features/availability.py b/libcxx/utils/libcxx/test/features/availability.py
index 39c6cf45a1708..e9c08b23ef50b 100644
--- a/libcxx/utils/libcxx/test/features/availability.py
+++ b/libcxx/utils/libcxx/test/features/availability.py
@@ -12,6 +12,13 @@
 # Helpers to define correspondances between LLVM versions and vendor system versions.
 # Those are used for backdeployment features below, do not use directly in tests.
 features = [
+    Feature(
+        name="_target-has-llvm-23",
+        when=lambda cfg: BooleanExpression.evaluate(
+            "TBD",
+            cfg.available_features,
+        ),
+    ),
     Feature(
         name="_target-has-llvm-22",
         when=lambda cfg: BooleanExpression.evaluate(
@@ -128,7 +135,7 @@
 # a libc++ flavor that enables availability markup. Similarly, a test could fail when
 # run against the system library of an older version of FreeBSD, even though FreeBSD
 # doesn't provide availability markup at the time of writing this.
-for version in ("12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22"):
+for version in ("12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23"):
     features.append(
         Feature(
             name="using-built-library-before-llvm-{}".format(version),



More information about the libcxx-commits mailing list