https://gcc.gnu.org/g:89552346e3cef8ef32e2ebe643bb96d085447e68

commit r16-5642-g89552346e3cef8ef32e2ebe643bb96d085447e68
Author: Jonathan Wakely <[email protected]>
Date:   Wed Nov 26 14:44:03 2025 +0000

    libstdc++: Fix std::counting_semaphore<> default max value
    
    My recent (uncommitted) changes to support a 64-bit __platform_wait_t
    for FreeBSD and Darwin revealed a problem in std::counting_semaphore.
    When the default template argument is used and __platform_wait_t is a
    64-bit type, the numeric_limits<__platform_wait_t>::max() value doesn't
    fit in ptrdiff_t and so we get ptrdiff_t(-1), which fails a
    static_assert in the class body.
    
    The solution is to cap the value to PTRDIFF_MAX instead of allowing it
    to go negative.
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/semaphore_base.h (__platform_semaphore::_S_max):
            Limit to PTRDIFF_MAX to avoid negative values.
            * testsuite/30_threads/semaphore/least_max_value.cc: New test.
    
    Reviewed-by: Tomasz KamiƄski <[email protected]>

Diff:
---
 libstdc++-v3/include/bits/semaphore_base.h                 | 14 ++++++++++++--
 .../testsuite/30_threads/semaphore/least_max_value.cc      |  9 +++++++++
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/include/bits/semaphore_base.h 
b/libstdc++-v3/include/bits/semaphore_base.h
index 82871ce3518b..cb815d340aca 100644
--- a/libstdc++-v3/include/bits/semaphore_base.h
+++ b/libstdc++-v3/include/bits/semaphore_base.h
@@ -173,8 +173,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   {
     using __count_type = __detail::__platform_wait_t;
 
-    static constexpr ptrdiff_t _S_max
-      = _Binary ? 1 : __gnu_cxx::__int_traits<__count_type>::__max;
+    static consteval ptrdiff_t
+    _S_calc_max()
+    {
+      if (_Binary)
+       return 1;
+      else if ((ptrdiff_t)__gnu_cxx::__int_traits<__count_type>::__max < 0)
+       return __gnu_cxx::__int_traits<ptrdiff_t>::__max;
+      else
+       return __gnu_cxx::__int_traits<__count_type>::__max;
+    }
+
+    static constexpr ptrdiff_t _S_max = _S_calc_max();
 
     constexpr explicit
     __platform_semaphore_impl(__count_type __count) noexcept
diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/least_max_value.cc 
b/libstdc++-v3/testsuite/30_threads/semaphore/least_max_value.cc
new file mode 100644
index 000000000000..67fa1258b7f0
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/semaphore/least_max_value.cc
@@ -0,0 +1,9 @@
+// { dg-do compile { target c++20 } }
+// { dg-require-effective-target gthreads { target { ! *-*-linux* } } }
+// { dg-require-effective-target hosted }
+
+#include <semaphore>
+
+std::counting_semaphore<> sem(0);
+std::counting_semaphore<> sem2(2);
+std::counting_semaphore sem3(3);

Reply via email to