[libcxx-commits] [libcxx] [libc++][C++26] P2562R1: `constexpr` Stable Sorting (PR #110320)

via libcxx-commits libcxx-commits at lists.llvm.org
Sun Nov 17 05:48:01 PST 2024


https://github.com/PaulXiCao updated https://github.com/llvm/llvm-project/pull/110320

>From 2366f3cd4a0c4f20a925008bd27e020ebaa2b160 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Fri, 27 Sep 2024 21:36:37 +0200
Subject: [PATCH 01/24] constexpr stable_sort

---
 libcxx/include/__algorithm/sort.h        |  2 +-
 libcxx/include/__algorithm/stable_sort.h | 48 +++++++++++++-----------
 libcxx/include/__memory/destruct_n.h     | 20 +++++-----
 3 files changed, 37 insertions(+), 33 deletions(-)

diff --git a/libcxx/include/__algorithm/sort.h b/libcxx/include/__algorithm/sort.h
index ed828b6d723147b..0e4d68ca56560a3 100644
--- a/libcxx/include/__algorithm/sort.h
+++ b/libcxx/include/__algorithm/sort.h
@@ -240,7 +240,7 @@ __selection_sort(_BidirectionalIterator __first, _BidirectionalIterator __last,
 // Sort the iterator range [__first, __last) using the comparator __comp using
 // the insertion sort algorithm.
 template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
-_LIBCPP_HIDE_FROM_ABI void
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
 __insertion_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) {
   using _Ops = _IterOps<_AlgPolicy>;
 
diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index 43f591ac02b01df..6e9fb3a7eca1787 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -69,7 +69,7 @@ _LIBCPP_HIDE_FROM_ABI void __insertion_sort_move(
 }
 
 template <class _AlgPolicy, class _Compare, class _InputIterator1, class _InputIterator2>
-_LIBCPP_HIDE_FROM_ABI void __merge_move_construct(
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __merge_move_construct(
     _InputIterator1 __first1,
     _InputIterator1 __last1,
     _InputIterator2 __first2,
@@ -107,7 +107,7 @@ _LIBCPP_HIDE_FROM_ABI void __merge_move_construct(
 }
 
 template <class _AlgPolicy, class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator>
-_LIBCPP_HIDE_FROM_ABI void __merge_move_assign(
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __merge_move_assign(
     _InputIterator1 __first1,
     _InputIterator1 __last1,
     _InputIterator2 __first2,
@@ -135,19 +135,21 @@ _LIBCPP_HIDE_FROM_ABI void __merge_move_assign(
 }
 
 template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
-void __stable_sort(_RandomAccessIterator __first,
-                   _RandomAccessIterator __last,
-                   _Compare __comp,
-                   typename iterator_traits<_RandomAccessIterator>::difference_type __len,
-                   typename iterator_traits<_RandomAccessIterator>::value_type* __buff,
-                   ptrdiff_t __buff_size);
+_LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort(
+    _RandomAccessIterator __first,
+    _RandomAccessIterator __last,
+    _Compare __comp,
+    typename iterator_traits<_RandomAccessIterator>::difference_type __len,
+    typename iterator_traits<_RandomAccessIterator>::value_type* __buff,
+    ptrdiff_t __buff_size);
 
 template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
-void __stable_sort_move(_RandomAccessIterator __first1,
-                        _RandomAccessIterator __last1,
-                        _Compare __comp,
-                        typename iterator_traits<_RandomAccessIterator>::difference_type __len,
-                        typename iterator_traits<_RandomAccessIterator>::value_type* __first2) {
+_LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort_move(
+    _RandomAccessIterator __first1,
+    _RandomAccessIterator __last1,
+    _Compare __comp,
+    typename iterator_traits<_RandomAccessIterator>::difference_type __len,
+    typename iterator_traits<_RandomAccessIterator>::value_type* __first2) {
   using _Ops = _IterOps<_AlgPolicy>;
 
   typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
@@ -191,12 +193,13 @@ struct __stable_sort_switch {
 };
 
 template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
-void __stable_sort(_RandomAccessIterator __first,
-                   _RandomAccessIterator __last,
-                   _Compare __comp,
-                   typename iterator_traits<_RandomAccessIterator>::difference_type __len,
-                   typename iterator_traits<_RandomAccessIterator>::value_type* __buff,
-                   ptrdiff_t __buff_size) {
+_LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort(
+    _RandomAccessIterator __first,
+    _RandomAccessIterator __last,
+    _Compare __comp,
+    typename iterator_traits<_RandomAccessIterator>::difference_type __len,
+    typename iterator_traits<_RandomAccessIterator>::value_type* __buff,
+    ptrdiff_t __buff_size) {
   typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
   typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
   switch (__len) {
@@ -236,7 +239,7 @@ void __stable_sort(_RandomAccessIterator __first,
 }
 
 template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
-inline _LIBCPP_HIDE_FROM_ABI void
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
 __stable_sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) {
   using value_type      = typename iterator_traits<_RandomAccessIterator>::value_type;
   using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
@@ -255,13 +258,14 @@ __stable_sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last,
 }
 
 template <class _RandomAccessIterator, class _Compare>
-inline _LIBCPP_HIDE_FROM_ABI void
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
 stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
   std::__stable_sort_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp);
 }
 
 template <class _RandomAccessIterator>
-inline _LIBCPP_HIDE_FROM_ABI void stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) {
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
+stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) {
   std::stable_sort(__first, __last, __less<>());
 }
 
diff --git a/libcxx/include/__memory/destruct_n.h b/libcxx/include/__memory/destruct_n.h
index 66adefb0f51fc7a..db227a4ea1dc779 100644
--- a/libcxx/include/__memory/destruct_n.h
+++ b/libcxx/include/__memory/destruct_n.h
@@ -25,35 +25,35 @@ struct __destruct_n {
   size_t __size_;
 
   template <class _Tp>
-  _LIBCPP_HIDE_FROM_ABI void __process(_Tp* __p, false_type) _NOEXCEPT {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __process(_Tp* __p, false_type) _NOEXCEPT {
     for (size_t __i = 0; __i < __size_; ++__i, ++__p)
       __p->~_Tp();
   }
 
   template <class _Tp>
-  _LIBCPP_HIDE_FROM_ABI void __process(_Tp*, true_type) _NOEXCEPT {}
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __process(_Tp*, true_type) _NOEXCEPT {}
 
-  _LIBCPP_HIDE_FROM_ABI void __incr(false_type) _NOEXCEPT { ++__size_; }
-  _LIBCPP_HIDE_FROM_ABI void __incr(true_type) _NOEXCEPT {}
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __incr(false_type) _NOEXCEPT { ++__size_; }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __incr(true_type) _NOEXCEPT {}
 
-  _LIBCPP_HIDE_FROM_ABI void __set(size_t __s, false_type) _NOEXCEPT { __size_ = __s; }
-  _LIBCPP_HIDE_FROM_ABI void __set(size_t, true_type) _NOEXCEPT {}
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __set(size_t __s, false_type) _NOEXCEPT { __size_ = __s; }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __set(size_t, true_type) _NOEXCEPT {}
 
 public:
-  _LIBCPP_HIDE_FROM_ABI explicit __destruct_n(size_t __s) _NOEXCEPT : __size_(__s) {}
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __destruct_n(size_t __s) _NOEXCEPT : __size_(__s) {}
 
   template <class _Tp>
-  _LIBCPP_HIDE_FROM_ABI void __incr() _NOEXCEPT {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __incr() _NOEXCEPT {
     __incr(integral_constant<bool, is_trivially_destructible<_Tp>::value>());
   }
 
   template <class _Tp>
-  _LIBCPP_HIDE_FROM_ABI void __set(size_t __s, _Tp*) _NOEXCEPT {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __set(size_t __s, _Tp*) _NOEXCEPT {
     __set(__s, integral_constant<bool, is_trivially_destructible<_Tp>::value>());
   }
 
   template <class _Tp>
-  _LIBCPP_HIDE_FROM_ABI void operator()(_Tp* __p) _NOEXCEPT {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void operator()(_Tp* __p) _NOEXCEPT {
     __process(__p, integral_constant<bool, is_trivially_destructible<_Tp>::value>());
   }
 };

>From 0ea964a2ef72971bac7dd9d657291249492fef93 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Fri, 27 Sep 2024 21:36:54 +0200
Subject: [PATCH 02/24] tests

---
 .../alg.sort/stable.sort/stable_sort.pass.cpp | 233 ++++++++++++------
 1 file changed, 163 insertions(+), 70 deletions(-)

diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
index 4301d22027de85e..92803c89dbcb7c2 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
@@ -14,7 +14,9 @@
 //   void
 //   stable_sort(Iter first, Iter last);
 
+#include <__config>
 #include <algorithm>
+#include <array>
 #include <cassert>
 #include <iterator>
 #include <random>
@@ -23,8 +25,6 @@
 #include "count_new.h"
 #include "test_macros.h"
 
-std::mt19937 randomness;
-
 template <class RI>
 void
 test_sort_helper(RI f, RI l)
@@ -80,66 +80,149 @@ test_sort_()
     }
 }
 
-void
-test_larger_sorts(int N, int M)
-{
-    assert(N != 0);
-    assert(M != 0);
-    // create array length N filled with M different numbers
-    int* array = new int[N];
-    int x = 0;
-    for (int i = 0; i < N; ++i)
-    {
-        array[i] = x;
-        if (++x == M)
-            x = 0;
+template <int N, int M>
+_LIBCPP_CONSTEXPR_SINCE_CXX26 std::array<int, N> init_saw_tooth_pattern() {
+  std::array<int, N> array;
+  for (int i = 0, x = 0; i < N; ++i) {
+    array[i] = x;
+    if (++x == M)
+      x = 0;
+  }
+  return array;
+}
+
+template <int N, int M>
+_LIBCPP_CONSTEXPR_SINCE_CXX26 std::array<int, N> sort_saw_tooth_pattern() {
+  std::array<int, N> array = init_saw_tooth_pattern<N, M>();
+  std::stable_sort(array.begin(), array.end());
+  return array;
+}
+
+template <int N, int M>
+_LIBCPP_CONSTEXPR_SINCE_CXX26 std::array<int, N> sort_already_sorted() {
+  std::array<int, N> array = sort_saw_tooth_pattern<N, M>();
+  std::stable_sort(array.begin(), array.end());
+  return array;
+}
+
+template <int N, int M>
+std::array<int, N> sort_reversely_sorted() {
+  std::array<int, N> array = sort_saw_tooth_pattern<N, M>();
+  std::reverse(array.begin(), array.end());
+  std::stable_sort(array.begin(), array.end());
+  return array;
+}
+
+template <int N, int M>
+_LIBCPP_CONSTEXPR_SINCE_CXX26 std::array<int, N> sort_swapped_sorted_ranges() {
+  std::array<int, N> array = sort_saw_tooth_pattern<N, M>();
+  std::swap_ranges(array.begin(), array.begin() + N / 2, array.begin() + N / 2);
+  std::stable_sort(array.begin(), array.end());
+  return array;
+}
+
+template <int N, int M>
+std::array<int, N> sort_reversely_swapped_sorted_ranges() {
+  std::array<int, N> array = sort_saw_tooth_pattern<N, M>();
+  std::reverse(array.begin(), array.end());
+  std::swap_ranges(array.begin(), array.begin() + N / 2, array.begin() + N / 2);
+  std::stable_sort(array.begin(), array.end());
+  return array;
+}
+
+#if _LIBCPP_STD_VER >= 26
+#  define COMPILE_OR_RUNTIME_ASSERT(func)                                                                              \
+    if consteval {                                                                                                     \
+      static_assert(func);                                                                                             \
+    } else {                                                                                                           \
+      assert(func);                                                                                                    \
     }
-    // test saw tooth pattern
-    std::stable_sort(array, array+N);
-    assert(std::is_sorted(array, array+N));
-    // test random pattern
-    std::shuffle(array, array+N, randomness);
-    std::stable_sort(array, array+N);
-    assert(std::is_sorted(array, array+N));
-    // test sorted pattern
-    std::stable_sort(array, array+N);
-    assert(std::is_sorted(array, array+N));
-    // test reverse sorted pattern
-    std::reverse(array, array+N);
-    std::stable_sort(array, array+N);
-    assert(std::is_sorted(array, array+N));
-    // test swap ranges 2 pattern
-    std::swap_ranges(array, array+N/2, array+N/2);
-    std::stable_sort(array, array+N);
-    assert(std::is_sorted(array, array+N));
-    // test reverse swap ranges 2 pattern
-    std::reverse(array, array+N);
-    std::swap_ranges(array, array+N/2, array+N/2);
-    std::stable_sort(array, array+N);
-    assert(std::is_sorted(array, array+N));
-    delete [] array;
+#else
+#  define COMPILE_OR_RUNTIME_ASSERT(func) assert(func);
+#endif
+
+template <int N, int M>
+_LIBCPP_CONSTEXPR_SINCE_CXX26 void test_larger_sorts() {
+  static_assert(N > 0, "");
+  static_assert(M > 0, "");
+
+  { // test saw tooth pattern
+    _LIBCPP_CONSTEXPR_SINCE_CXX26 std::array<int, N> array = sort_saw_tooth_pattern<N, M>();
+    COMPILE_OR_RUNTIME_ASSERT(std::is_sorted(array.begin(), array.end()))
+  }
+
+#if _LIBCPP_STD_VER >= 26
+  if !consteval
+#endif
+  { // test random pattern
+    // random-number generators not constexpr-friendly
+    static std::mt19937 randomness;
+    std::array<int, N> array = init_saw_tooth_pattern<N, M>();
+    std::shuffle(array.begin(), array.end(), randomness);
+    std::stable_sort(array.begin(), array.end());
+    assert(std::is_sorted(array.begin(), array.end()));
+  }
+
+  { // test sorted pattern
+    _LIBCPP_CONSTEXPR_SINCE_CXX26 std::array<int, N> array = sort_already_sorted<N, M>();
+    COMPILE_OR_RUNTIME_ASSERT(std::is_sorted(array.begin(), array.end()))
+  }
+
+#if _LIBCPP_STD_VER >= 26
+  if !consteval
+#endif
+  { // test reverse sorted pattern
+    // consteval error: "constexpr evaluation hit maximum step limit"
+    std::array<int, N> array = sort_reversely_sorted<N, M>();
+    assert(std::is_sorted(array.begin(), array.end()));
+  }
+
+  { // test swap ranges 2 pattern
+    _LIBCPP_CONSTEXPR_SINCE_CXX26 std::array<int, N> array = sort_swapped_sorted_ranges<N, M>();
+    COMPILE_OR_RUNTIME_ASSERT(std::is_sorted(array.begin(), array.end()))
+  }
+
+#if _LIBCPP_STD_VER >= 26
+  if !consteval
+#endif
+  { // test reverse swap ranges 2 pattern
+    // consteval error: "constexpr evaluation hit maximum step limit"
+    std::array<int, N> array = sort_reversely_swapped_sorted_ranges<N, M>();
+    assert(std::is_sorted(array.begin(), array.end()));
+  }
 }
 
-void
-test_larger_sorts(int N)
-{
-    test_larger_sorts(N, 1);
-    test_larger_sorts(N, 2);
-    test_larger_sorts(N, 3);
-    test_larger_sorts(N, N/2-1);
-    test_larger_sorts(N, N/2);
-    test_larger_sorts(N, N/2+1);
-    test_larger_sorts(N, N-2);
-    test_larger_sorts(N, N-1);
-    test_larger_sorts(N, N);
+template <int N>
+_LIBCPP_CONSTEXPR_SINCE_CXX26 void test_larger_sorts() {
+  test_larger_sorts<N, 1>();
+  test_larger_sorts<N, 2>();
+  test_larger_sorts<N, 3>();
+  test_larger_sorts<N, N / 2 - 1>();
+  test_larger_sorts<N, N / 2>();
+  test_larger_sorts<N, N / 2 + 1>();
+  test_larger_sorts<N, N - 2>();
+  test_larger_sorts<N, N - 1>();
+  test_larger_sorts<N, N>();
 }
 
-int main(int, char**)
-{
-    // test null range
+#if _LIBCPP_STD_VER >= 26
+#  define COMPILE_AND_RUNTIME_CALL(func)                                                                               \
+    func;                                                                                                              \
+    static_assert((func, true));
+#else
+#  define COMPILE_AND_RUNTIME_CALL(func) func;
+#endif
+
+int main(int, char**) {
+  { // test null range
     int d = 0;
     std::stable_sort(&d, &d);
-    // exhaustively test all possibilities up to length 8
+#if _LIBCPP_STD_VER >= 26
+    static_assert((std::stable_sort(&d, &d), true));
+#endif
+  }
+
+  { // exhaustively test all possibilities up to length 8
     test_sort_<1>();
     test_sort_<2>();
     test_sort_<3>();
@@ -148,22 +231,32 @@ int main(int, char**)
     test_sort_<6>();
     test_sort_<7>();
     test_sort_<8>();
+  }
 
-    test_larger_sorts(256);
-    test_larger_sorts(257);
-    test_larger_sorts(499);
-    test_larger_sorts(500);
-    test_larger_sorts(997);
-    test_larger_sorts(1000);
-    test_larger_sorts(1009);
-
-#if !defined(TEST_HAS_NO_EXCEPTIONS)
-    { // check that the algorithm works without memory
-        std::vector<int> vec(150, 3);
-        getGlobalMemCounter()->throw_after = 0;
-        std::stable_sort(vec.begin(), vec.end());
-    }
-#endif // !defined(TEST_HAS_NO_EXCEPTIONS)
+  { // larger sorts
+    // run- and conditionally compile-time tests
+    test_larger_sorts<256>();
+    test_larger_sorts<257>();
+#if _LIBCPP_STD_VER >= 26
+    static_assert((test_larger_sorts<256>(), true));
+    static_assert((test_larger_sorts<257>(), true));
+#endif
+
+    // only runtime tests bc. error: "constexpr evaluation hit maximum step limit"
+    test_larger_sorts<499>();
+    test_larger_sorts<500>();
+    test_larger_sorts<997>();
+    test_larger_sorts<1000>();
+    test_larger_sorts<1009>();
+  }
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  { // check that the algorithm works without memory
+    std::vector<int> vec(150, 3);
+    getGlobalMemCounter()->throw_after = 0;
+    std::stable_sort(vec.begin(), vec.end());
+  }
+#endif
 
   return 0;
 }

>From 2a4251654665527353e32ee39981131147d6b28e Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Fri, 27 Sep 2024 21:48:37 +0200
Subject: [PATCH 03/24] update algorithm synopsis

---
 libcxx/include/algorithm | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm
index 14355d63f2901ca..a093c6ad21b70a8 100644
--- a/libcxx/include/algorithm
+++ b/libcxx/include/algorithm
@@ -1530,11 +1530,11 @@ template <class RandomAccessIterator, class Compare>
     sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp);
 
 template <class RandomAccessIterator>
-    void
+    constexpr void               // constexpr in C++26
     stable_sort(RandomAccessIterator first, RandomAccessIterator last);
 
 template <class RandomAccessIterator, class Compare>
-    void
+    constexpr void               // constexpr in C++26
     stable_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp);
 
 template <class RandomAccessIterator>

>From 7cf77e73c43675b39e403dd74bfbfb6c6020bfc4 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Fri, 27 Sep 2024 21:50:51 +0200
Subject: [PATCH 04/24] update docs

---
 libcxx/docs/Status/Cxx2cPapers.csv | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index 6659d815612d05e..c64b32ee00ab56d 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -2,7 +2,7 @@
 "`P2497R0 <https://wg21.link/P2497R0>`__","Testing for success or failure of ``<charconv>`` functions","2023-06 (Varna)","|Complete|","18",""
 "`P2592R3 <https://wg21.link/P2592R3>`__","Hashing support for ``std::chrono`` value classes","2023-06 (Varna)","","",""
 "`P2587R3 <https://wg21.link/P2587R3>`__","``to_string`` or not ``to_string``","2023-06 (Varna)","","",""
-"`P2562R1 <https://wg21.link/P2562R1>`__","``constexpr`` Stable Sorting","2023-06 (Varna)","","",""
+"`P2562R1 <https://wg21.link/P2562R1>`__","``constexpr`` Stable Sorting","2023-06 (Varna)","|Complete|","20.0",""
 "`P2545R4 <https://wg21.link/P2545R4>`__","Read-Copy Update (RCU)","2023-06 (Varna)","","",""
 "`P2530R3 <https://wg21.link/P2530R3>`__","Hazard Pointers for C++26","2023-06 (Varna)","","",""
 "`P2538R1 <https://wg21.link/P2538R1>`__","ADL-proof ``std::projected``","2023-06 (Varna)","|Complete|","18",""

>From 05a13a74d94ae4a0cd64ce73efc6fb1f1d9c9ac8 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Wed, 2 Oct 2024 22:39:53 +0200
Subject: [PATCH 05/24] paper status: partial

---
 libcxx/docs/Status/Cxx2cPapers.csv | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index c64b32ee00ab56d..0827aeb96a2c24b 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -2,7 +2,7 @@
 "`P2497R0 <https://wg21.link/P2497R0>`__","Testing for success or failure of ``<charconv>`` functions","2023-06 (Varna)","|Complete|","18",""
 "`P2592R3 <https://wg21.link/P2592R3>`__","Hashing support for ``std::chrono`` value classes","2023-06 (Varna)","","",""
 "`P2587R3 <https://wg21.link/P2587R3>`__","``to_string`` or not ``to_string``","2023-06 (Varna)","","",""
-"`P2562R1 <https://wg21.link/P2562R1>`__","``constexpr`` Stable Sorting","2023-06 (Varna)","|Complete|","20.0",""
+"`P2562R1 <https://wg21.link/P2562R1>`__","``constexpr`` Stable Sorting","2023-06 (Varna)","|Partial|","20.0",""
 "`P2545R4 <https://wg21.link/P2545R4>`__","Read-Copy Update (RCU)","2023-06 (Varna)","","",""
 "`P2530R3 <https://wg21.link/P2530R3>`__","Hazard Pointers for C++26","2023-06 (Varna)","","",""
 "`P2538R1 <https://wg21.link/P2538R1>`__","ADL-proof ``std::projected``","2023-06 (Varna)","|Complete|","18",""

>From e5b51d9cf58ff6fed8c573c25a2839f4436be536 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Fri, 4 Oct 2024 19:13:04 +0200
Subject: [PATCH 06/24] remove include of internal header

---
 .../alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp        | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
index 92803c89dbcb7c2..14560a98fff727a 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
@@ -14,7 +14,6 @@
 //   void
 //   stable_sort(Iter first, Iter last);
 
-#include <__config>
 #include <algorithm>
 #include <array>
 #include <cassert>

>From 2ae4f9fd3528c151e74b5aff259c0199a5554367 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Fri, 4 Oct 2024 19:15:42 +0200
Subject: [PATCH 07/24] replace _LIBCPP_CONSTEXPR_SINCE_CXX26 by
 TEST_CONSTEXPR_CXX26

---
 .../alg.sort/stable.sort/stable_sort.pass.cpp  | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
index 14560a98fff727a..89cf06bad3046ab 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
@@ -80,7 +80,7 @@ test_sort_()
 }
 
 template <int N, int M>
-_LIBCPP_CONSTEXPR_SINCE_CXX26 std::array<int, N> init_saw_tooth_pattern() {
+TEST_CONSTEXPR_CXX26 std::array<int, N> init_saw_tooth_pattern() {
   std::array<int, N> array;
   for (int i = 0, x = 0; i < N; ++i) {
     array[i] = x;
@@ -91,14 +91,14 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 std::array<int, N> init_saw_tooth_pattern() {
 }
 
 template <int N, int M>
-_LIBCPP_CONSTEXPR_SINCE_CXX26 std::array<int, N> sort_saw_tooth_pattern() {
+TEST_CONSTEXPR_CXX26 std::array<int, N> sort_saw_tooth_pattern() {
   std::array<int, N> array = init_saw_tooth_pattern<N, M>();
   std::stable_sort(array.begin(), array.end());
   return array;
 }
 
 template <int N, int M>
-_LIBCPP_CONSTEXPR_SINCE_CXX26 std::array<int, N> sort_already_sorted() {
+TEST_CONSTEXPR_CXX26 std::array<int, N> sort_already_sorted() {
   std::array<int, N> array = sort_saw_tooth_pattern<N, M>();
   std::stable_sort(array.begin(), array.end());
   return array;
@@ -113,7 +113,7 @@ std::array<int, N> sort_reversely_sorted() {
 }
 
 template <int N, int M>
-_LIBCPP_CONSTEXPR_SINCE_CXX26 std::array<int, N> sort_swapped_sorted_ranges() {
+TEST_CONSTEXPR_CXX26 std::array<int, N> sort_swapped_sorted_ranges() {
   std::array<int, N> array = sort_saw_tooth_pattern<N, M>();
   std::swap_ranges(array.begin(), array.begin() + N / 2, array.begin() + N / 2);
   std::stable_sort(array.begin(), array.end());
@@ -141,12 +141,12 @@ std::array<int, N> sort_reversely_swapped_sorted_ranges() {
 #endif
 
 template <int N, int M>
-_LIBCPP_CONSTEXPR_SINCE_CXX26 void test_larger_sorts() {
+TEST_CONSTEXPR_CXX26 void test_larger_sorts() {
   static_assert(N > 0, "");
   static_assert(M > 0, "");
 
   { // test saw tooth pattern
-    _LIBCPP_CONSTEXPR_SINCE_CXX26 std::array<int, N> array = sort_saw_tooth_pattern<N, M>();
+    TEST_CONSTEXPR_CXX26 std::array<int, N> array = sort_saw_tooth_pattern<N, M>();
     COMPILE_OR_RUNTIME_ASSERT(std::is_sorted(array.begin(), array.end()))
   }
 
@@ -163,7 +163,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 void test_larger_sorts() {
   }
 
   { // test sorted pattern
-    _LIBCPP_CONSTEXPR_SINCE_CXX26 std::array<int, N> array = sort_already_sorted<N, M>();
+    TEST_CONSTEXPR_CXX26 std::array<int, N> array = sort_already_sorted<N, M>();
     COMPILE_OR_RUNTIME_ASSERT(std::is_sorted(array.begin(), array.end()))
   }
 
@@ -177,7 +177,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 void test_larger_sorts() {
   }
 
   { // test swap ranges 2 pattern
-    _LIBCPP_CONSTEXPR_SINCE_CXX26 std::array<int, N> array = sort_swapped_sorted_ranges<N, M>();
+    TEST_CONSTEXPR_CXX26 std::array<int, N> array = sort_swapped_sorted_ranges<N, M>();
     COMPILE_OR_RUNTIME_ASSERT(std::is_sorted(array.begin(), array.end()))
   }
 
@@ -192,7 +192,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 void test_larger_sorts() {
 }
 
 template <int N>
-_LIBCPP_CONSTEXPR_SINCE_CXX26 void test_larger_sorts() {
+TEST_CONSTEXPR_CXX26 void test_larger_sorts() {
   test_larger_sorts<N, 1>();
   test_larger_sorts<N, 2>();
   test_larger_sorts<N, 3>();

>From bf479373697179f48a80ac1c37fbc646c3748700 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Fri, 4 Oct 2024 19:14:05 +0200
Subject: [PATCH 08/24] documentation: use proper function declaration

---
 .../alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
index 89cf06bad3046ab..cb32174a2ca0c50 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
@@ -8,11 +8,9 @@
 
 // <algorithm>
 
-// template<RandomAccessIterator Iter>
-//   requires ShuffleIterator<Iter>
-//         && LessThanComparable<Iter::value_type>
-//   void
-//   stable_sort(Iter first, Iter last);
+// template <class RandomAccessIterator>
+//     constexpr void               // constexpr in C++26
+//     stable_sort(RandomAccessIterator first, RandomAccessIterator last);
 
 #include <algorithm>
 #include <array>

>From 5081abde98ea020984c90491f000f42b03d1e3ba Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sat, 5 Oct 2024 22:13:23 +0200
Subject: [PATCH 09/24] workaround for gcc bug with placement new

---
 libcxx/include/__algorithm/stable_sort.h | 38 ++++++++++++++++--------
 1 file changed, 25 insertions(+), 13 deletions(-)

diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index 6e9fb3a7eca1787..6ed8ccc06079015 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -35,6 +35,18 @@ _LIBCPP_PUSH_MACROS
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 <= 140100)
+#  define __STABLE_SORT_NEW(__placement_args, __type, __new_initializer)                                               \
+    do {                                                                                                               \
+      [__placement_args] { ::new (__placement_args) __type(__new_initializer); }();                                    \
+    } while (0)
+#else
+#  define __STABLE_SORT_NEW(__placement_args, __type, __new_initializer)                                               \
+    do {                                                                                                               \
+      ::new (__placement_args) __type(__new_initializer);                                                              \
+    } while (0)
+#endif
+
 template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
 _LIBCPP_HIDE_FROM_ABI void __insertion_sort_move(
     _BidirectionalIterator __first1,
@@ -48,19 +60,19 @@ _LIBCPP_HIDE_FROM_ABI void __insertion_sort_move(
     __destruct_n __d(0);
     unique_ptr<value_type, __destruct_n&> __h(__first2, __d);
     value_type* __last2 = __first2;
-    ::new ((void*)__last2) value_type(_Ops::__iter_move(__first1));
+    __STABLE_SORT_NEW((void*)__last2, value_type, _Ops::__iter_move(__first1));
     __d.template __incr<value_type>();
     for (++__last2; ++__first1 != __last1; ++__last2) {
       value_type* __j2 = __last2;
       value_type* __i2 = __j2;
       if (__comp(*__first1, *--__i2)) {
-        ::new ((void*)__j2) value_type(std::move(*__i2));
+        __STABLE_SORT_NEW((void*)__j2, value_type, std::move(*__i2));
         __d.template __incr<value_type>();
         for (--__j2; __i2 != __first2 && __comp(*__first1, *--__i2); --__j2)
           *__j2 = std::move(*__i2);
         *__j2 = _Ops::__iter_move(__first1);
       } else {
-        ::new ((void*)__j2) value_type(_Ops::__iter_move(__first1));
+        __STABLE_SORT_NEW((void*)__j2, value_type, _Ops::__iter_move(__first1));
         __d.template __incr<value_type>();
       }
     }
@@ -84,22 +96,22 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __merge_move_construct(
   for (; true; ++__result) {
     if (__first1 == __last1) {
       for (; __first2 != __last2; ++__first2, (void)++__result, __d.template __incr<value_type>())
-        ::new ((void*)__result) value_type(_Ops::__iter_move(__first2));
+        __STABLE_SORT_NEW((void*)__result, value_type, _Ops::__iter_move(__first2));
       __h.release();
       return;
     }
     if (__first2 == __last2) {
       for (; __first1 != __last1; ++__first1, (void)++__result, __d.template __incr<value_type>())
-        ::new ((void*)__result) value_type(_Ops::__iter_move(__first1));
+        __STABLE_SORT_NEW((void*)__result, value_type, _Ops::__iter_move(__first1));
       __h.release();
       return;
     }
     if (__comp(*__first2, *__first1)) {
-      ::new ((void*)__result) value_type(_Ops::__iter_move(__first2));
+      __STABLE_SORT_NEW((void*)__result, value_type, _Ops::__iter_move(__first2));
       __d.template __incr<value_type>();
       ++__first2;
     } else {
-      ::new ((void*)__result) value_type(_Ops::__iter_move(__first1));
+      __STABLE_SORT_NEW((void*)__result, value_type, _Ops::__iter_move(__first1));
       __d.template __incr<value_type>();
       ++__first1;
     }
@@ -157,21 +169,21 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort_move(
   case 0:
     return;
   case 1:
-    ::new ((void*)__first2) value_type(_Ops::__iter_move(__first1));
+    __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move(__first1));
     return;
   case 2:
     __destruct_n __d(0);
     unique_ptr<value_type, __destruct_n&> __h2(__first2, __d);
     if (__comp(*--__last1, *__first1)) {
-      ::new ((void*)__first2) value_type(_Ops::__iter_move(__last1));
+      __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move(__last1));
       __d.template __incr<value_type>();
       ++__first2;
-      ::new ((void*)__first2) value_type(_Ops::__iter_move(__first1));
+      __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move(__first1));
     } else {
-      ::new ((void*)__first2) value_type(_Ops::__iter_move(__first1));
+      __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move(__first1));
       __d.template __incr<value_type>();
       ++__first2;
-      ::new ((void*)__first2) value_type(_Ops::__iter_move(__last1));
+      __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move(__last1));
     }
     __h2.release();
     return;
@@ -269,8 +281,8 @@ stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) {
   std::stable_sort(__first, __last, __less<>());
 }
 
+#undef __STABLE_SORT_NEW
 _LIBCPP_END_NAMESPACE_STD
-
 _LIBCPP_POP_MACROS
 
 #endif // _LIBCPP___ALGORITHM_STABLE_SORT_H

>From 9b139d384bfc478b16c201c311d80792bb1ecf78 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sun, 6 Oct 2024 15:00:48 +0200
Subject: [PATCH 10/24] workaround for gcc bug with placement new: fix lambda
 capturing

---
 libcxx/include/__algorithm/stable_sort.h | 40 ++++++++++++++----------
 1 file changed, 24 insertions(+), 16 deletions(-)

diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index 6ed8ccc06079015..dc418fd19ad6b1f 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -35,15 +35,22 @@ _LIBCPP_PUSH_MACROS
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+#define __STABLE_SORT_NEW_IMPL(__placement_arg, __type, __new_initializer_func, __new_initializer_arg)                 \
+  do {                                                                                                                 \
+    ::new (__placement_arg) __type(__new_initializer_func(__new_initializer_arg));                                     \
+  } while (0)
+
 #if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 <= 140100)
-#  define __STABLE_SORT_NEW(__placement_args, __type, __new_initializer)                                               \
+#  define __STABLE_SORT_NEW(__placement_arg, __type, __new_initializer_func, __new_initializer_arg)                    \
     do {                                                                                                               \
-      [__placement_args] { ::new (__placement_args) __type(__new_initializer); }();                                    \
+      [__placement_arg, &__new_initializer_arg] {                                                                       \
+        __STABLE_SORT_NEW_IMPL(__placement_arg, __type, __new_initializer_func, __new_initializer_arg);                \
+      }();                                                                                                             \
     } while (0)
 #else
-#  define __STABLE_SORT_NEW(__placement_args, __type, __new_initializer)                                               \
+#  define __STABLE_SORT_NEW(__placement_arg, __type, __new_initializer_func, __new_initializer_arg)                                                \
     do {                                                                                                               \
-      ::new (__placement_args) __type(__new_initializer);                                                              \
+      __STABLE_SORT_NEW_IMPL(__placement_arg, __type, __new_initializer_func, __new_initializer_arg);                  \
     } while (0)
 #endif
 
@@ -60,19 +67,19 @@ _LIBCPP_HIDE_FROM_ABI void __insertion_sort_move(
     __destruct_n __d(0);
     unique_ptr<value_type, __destruct_n&> __h(__first2, __d);
     value_type* __last2 = __first2;
-    __STABLE_SORT_NEW((void*)__last2, value_type, _Ops::__iter_move(__first1));
+    __STABLE_SORT_NEW((void*)__last2, value_type, _Ops::__iter_move, __first1);
     __d.template __incr<value_type>();
     for (++__last2; ++__first1 != __last1; ++__last2) {
       value_type* __j2 = __last2;
       value_type* __i2 = __j2;
       if (__comp(*__first1, *--__i2)) {
-        __STABLE_SORT_NEW((void*)__j2, value_type, std::move(*__i2));
+        __STABLE_SORT_NEW((void*)__j2, value_type, std::move, *__i2);
         __d.template __incr<value_type>();
         for (--__j2; __i2 != __first2 && __comp(*__first1, *--__i2); --__j2)
           *__j2 = std::move(*__i2);
         *__j2 = _Ops::__iter_move(__first1);
       } else {
-        __STABLE_SORT_NEW((void*)__j2, value_type, _Ops::__iter_move(__first1));
+        __STABLE_SORT_NEW((void*)__j2, value_type, _Ops::__iter_move, __first1);
         __d.template __incr<value_type>();
       }
     }
@@ -96,22 +103,22 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __merge_move_construct(
   for (; true; ++__result) {
     if (__first1 == __last1) {
       for (; __first2 != __last2; ++__first2, (void)++__result, __d.template __incr<value_type>())
-        __STABLE_SORT_NEW((void*)__result, value_type, _Ops::__iter_move(__first2));
+        __STABLE_SORT_NEW((void*)__result, value_type, _Ops::__iter_move, __first2);
       __h.release();
       return;
     }
     if (__first2 == __last2) {
       for (; __first1 != __last1; ++__first1, (void)++__result, __d.template __incr<value_type>())
-        __STABLE_SORT_NEW((void*)__result, value_type, _Ops::__iter_move(__first1));
+        __STABLE_SORT_NEW((void*)__result, value_type, _Ops::__iter_move, __first1);
       __h.release();
       return;
     }
     if (__comp(*__first2, *__first1)) {
-      __STABLE_SORT_NEW((void*)__result, value_type, _Ops::__iter_move(__first2));
+      __STABLE_SORT_NEW((void*)__result, value_type, _Ops::__iter_move, __first2);
       __d.template __incr<value_type>();
       ++__first2;
     } else {
-      __STABLE_SORT_NEW((void*)__result, value_type, _Ops::__iter_move(__first1));
+      __STABLE_SORT_NEW((void*)__result, value_type, _Ops::__iter_move, __first1);
       __d.template __incr<value_type>();
       ++__first1;
     }
@@ -169,21 +176,21 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort_move(
   case 0:
     return;
   case 1:
-    __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move(__first1));
+    __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move, __first1);
     return;
   case 2:
     __destruct_n __d(0);
     unique_ptr<value_type, __destruct_n&> __h2(__first2, __d);
     if (__comp(*--__last1, *__first1)) {
-      __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move(__last1));
+      __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move, __last1);
       __d.template __incr<value_type>();
       ++__first2;
-      __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move(__first1));
+      __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move, __first1);
     } else {
-      __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move(__first1));
+      __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move, __first1);
       __d.template __incr<value_type>();
       ++__first2;
-      __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move(__last1));
+      __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move, __last1);
     }
     __h2.release();
     return;
@@ -282,6 +289,7 @@ stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) {
 }
 
 #undef __STABLE_SORT_NEW
+#undef __STABLE_SORT_NEW_IMPL
 _LIBCPP_END_NAMESPACE_STD
 _LIBCPP_POP_MACROS
 

>From 7dbd0043c33ec316ce1b12aaef33e6c96790809c Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sun, 6 Oct 2024 21:16:33 +0200
Subject: [PATCH 11/24] workaround for gcc bug with placement new: v3

---
 libcxx/include/__algorithm/stable_sort.h | 33 ++++++++++++------------
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index dc418fd19ad6b1f..e0ff647e08ef09b 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -35,20 +35,21 @@ _LIBCPP_PUSH_MACROS
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+// Workaround for "constexpr placement new" bug in gcc (fixed in 14.2).
+// See https://github.com/llvm/llvm-project/pull/110320#discussion_r1788557715.
 #define __STABLE_SORT_NEW_IMPL(__placement_arg, __type, __new_initializer_func, __new_initializer_arg)                 \
   do {                                                                                                                 \
-    ::new (__placement_arg) __type(__new_initializer_func(__new_initializer_arg));                                     \
+    ::new ((void*)__placement_arg) __type(__new_initializer_func(__new_initializer_arg));                              \
   } while (0)
-
 #if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 <= 140100)
 #  define __STABLE_SORT_NEW(__placement_arg, __type, __new_initializer_func, __new_initializer_arg)                    \
     do {                                                                                                               \
-      [__placement_arg, &__new_initializer_arg] {                                                                       \
+      [__placement_arg, &__new_initializer_arg] {                                                                      \
         __STABLE_SORT_NEW_IMPL(__placement_arg, __type, __new_initializer_func, __new_initializer_arg);                \
       }();                                                                                                             \
     } while (0)
 #else
-#  define __STABLE_SORT_NEW(__placement_arg, __type, __new_initializer_func, __new_initializer_arg)                                                \
+#  define __STABLE_SORT_NEW(__placement_arg, __type, __new_initializer_func, __new_initializer_arg)                    \
     do {                                                                                                               \
       __STABLE_SORT_NEW_IMPL(__placement_arg, __type, __new_initializer_func, __new_initializer_arg);                  \
     } while (0)
@@ -67,19 +68,19 @@ _LIBCPP_HIDE_FROM_ABI void __insertion_sort_move(
     __destruct_n __d(0);
     unique_ptr<value_type, __destruct_n&> __h(__first2, __d);
     value_type* __last2 = __first2;
-    __STABLE_SORT_NEW((void*)__last2, value_type, _Ops::__iter_move, __first1);
+    __STABLE_SORT_NEW(__last2, value_type, _Ops::__iter_move, __first1);
     __d.template __incr<value_type>();
     for (++__last2; ++__first1 != __last1; ++__last2) {
       value_type* __j2 = __last2;
       value_type* __i2 = __j2;
       if (__comp(*__first1, *--__i2)) {
-        __STABLE_SORT_NEW((void*)__j2, value_type, std::move, *__i2);
+        __STABLE_SORT_NEW(__j2, value_type, std::move, *__i2);
         __d.template __incr<value_type>();
         for (--__j2; __i2 != __first2 && __comp(*__first1, *--__i2); --__j2)
           *__j2 = std::move(*__i2);
         *__j2 = _Ops::__iter_move(__first1);
       } else {
-        __STABLE_SORT_NEW((void*)__j2, value_type, _Ops::__iter_move, __first1);
+        __STABLE_SORT_NEW(__j2, value_type, _Ops::__iter_move, __first1);
         __d.template __incr<value_type>();
       }
     }
@@ -103,22 +104,22 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __merge_move_construct(
   for (; true; ++__result) {
     if (__first1 == __last1) {
       for (; __first2 != __last2; ++__first2, (void)++__result, __d.template __incr<value_type>())
-        __STABLE_SORT_NEW((void*)__result, value_type, _Ops::__iter_move, __first2);
+        __STABLE_SORT_NEW(__result, value_type, _Ops::__iter_move, __first2);
       __h.release();
       return;
     }
     if (__first2 == __last2) {
       for (; __first1 != __last1; ++__first1, (void)++__result, __d.template __incr<value_type>())
-        __STABLE_SORT_NEW((void*)__result, value_type, _Ops::__iter_move, __first1);
+        __STABLE_SORT_NEW(__result, value_type, _Ops::__iter_move, __first1);
       __h.release();
       return;
     }
     if (__comp(*__first2, *__first1)) {
-      __STABLE_SORT_NEW((void*)__result, value_type, _Ops::__iter_move, __first2);
+      __STABLE_SORT_NEW(__result, value_type, _Ops::__iter_move, __first2);
       __d.template __incr<value_type>();
       ++__first2;
     } else {
-      __STABLE_SORT_NEW((void*)__result, value_type, _Ops::__iter_move, __first1);
+      __STABLE_SORT_NEW(__result, value_type, _Ops::__iter_move, __first1);
       __d.template __incr<value_type>();
       ++__first1;
     }
@@ -176,21 +177,21 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort_move(
   case 0:
     return;
   case 1:
-    __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move, __first1);
+    __STABLE_SORT_NEW(__first2, value_type, _Ops::__iter_move, __first1);
     return;
   case 2:
     __destruct_n __d(0);
     unique_ptr<value_type, __destruct_n&> __h2(__first2, __d);
     if (__comp(*--__last1, *__first1)) {
-      __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move, __last1);
+      __STABLE_SORT_NEW(__first2, value_type, _Ops::__iter_move, __last1);
       __d.template __incr<value_type>();
       ++__first2;
-      __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move, __first1);
+      __STABLE_SORT_NEW(__first2, value_type, _Ops::__iter_move, __first1);
     } else {
-      __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move, __first1);
+      __STABLE_SORT_NEW(__first2, value_type, _Ops::__iter_move, __first1);
       __d.template __incr<value_type>();
       ++__first2;
-      __STABLE_SORT_NEW((void*)__first2, value_type, _Ops::__iter_move, __last1);
+      __STABLE_SORT_NEW(__first2, value_type, _Ops::__iter_move, __last1);
     }
     __h2.release();
     return;

>From 363eb7c451b95271873b454f04aa3d3dadad9979 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sun, 6 Oct 2024 21:26:55 +0200
Subject: [PATCH 12/24] workaround for gcc bug with placement new: v4

---
 libcxx/include/__algorithm/stable_sort.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index e0ff647e08ef09b..c56a1701d4c2577 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -74,7 +74,10 @@ _LIBCPP_HIDE_FROM_ABI void __insertion_sort_move(
       value_type* __j2 = __last2;
       value_type* __i2 = __j2;
       if (__comp(*__first1, *--__i2)) {
-        __STABLE_SORT_NEW(__j2, value_type, std::move, *__i2);
+        {
+          value_type& __tmp = *__i2;
+          __STABLE_SORT_NEW(__j2, value_type, std::move, __tmp);
+        }
         __d.template __incr<value_type>();
         for (--__j2; __i2 != __first2 && __comp(*__first1, *--__i2); --__j2)
           *__j2 = std::move(*__i2);

>From 11310980343b68471d279929bc59451e120d58a4 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Fri, 11 Oct 2024 21:53:13 +0200
Subject: [PATCH 13/24] workaround for gcc bug with placement new: v5 (test)

---
 libcxx/include/__algorithm/stable_sort.h | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index c56a1701d4c2577..d1f457ec47c672b 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -122,7 +122,12 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __merge_move_construct(
       __d.template __incr<value_type>();
       ++__first2;
     } else {
-      __STABLE_SORT_NEW(__result, value_type, _Ops::__iter_move, __first1);
+// __STABLE_SORT_NEW(__result, value_type, _Ops::__iter_move, __first1);
+#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 <= 140100)
+      [__result, &__first1] { ::new (__result) value_type(_Ops::__iter_move(__first1)); }();
+#else
+      ::new (__result) value_type(_Ops::__iter_move(__first1));
+#endif
       __d.template __incr<value_type>();
       ++__first1;
     }

>From 2aada1a62b38db06ed72f4e5d8ee5aee433bbf6e Mon Sep 17 00:00:00 2001
From: PaulXiCao <paul.luckner at rwth-aachen.de>
Date: Sat, 12 Oct 2024 09:14:30 +0000
Subject: [PATCH 14/24] workaround for gcc bug with placement new: v6

Co-authored-by: A. Jiang <de34 at live.cn>
---
 libcxx/include/__algorithm/stable_sort.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index d1f457ec47c672b..3c84c5b1dd7dc72 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -124,9 +124,9 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __merge_move_construct(
     } else {
 // __STABLE_SORT_NEW(__result, value_type, _Ops::__iter_move, __first1);
 #if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 <= 140100)
-      [__result, &__first1] { ::new (__result) value_type(_Ops::__iter_move(__first1)); }();
+      [__result, &__first1] { ::new ((void*)__result) value_type(_Ops::__iter_move(__first1)); }();
 #else
-      ::new (__result) value_type(_Ops::__iter_move(__first1));
+      ::new ((void*)__result) value_type(_Ops::__iter_move(__first1));
 #endif
       __d.template __incr<value_type>();
       ++__first1;

>From 8f16d4ff6fac76f2b437c4cf2dea417c27a96724 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sun, 13 Oct 2024 18:57:43 +0200
Subject: [PATCH 15/24] workaround for gcc bug with placement new: v7

---
 libcxx/include/__algorithm/stable_sort.h | 50 ++++++++----------------
 1 file changed, 17 insertions(+), 33 deletions(-)

diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index 3c84c5b1dd7dc72..640babe4c4466bb 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -37,22 +37,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 // Workaround for "constexpr placement new" bug in gcc (fixed in 14.2).
 // See https://github.com/llvm/llvm-project/pull/110320#discussion_r1788557715.
-#define __STABLE_SORT_NEW_IMPL(__placement_arg, __type, __new_initializer_func, __new_initializer_arg)                 \
-  do {                                                                                                                 \
-    ::new ((void*)__placement_arg) __type(__new_initializer_func(__new_initializer_arg));                              \
-  } while (0)
 #if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 <= 140100)
-#  define __STABLE_SORT_NEW(__placement_arg, __type, __new_initializer_func, __new_initializer_arg)                    \
-    do {                                                                                                               \
-      [__placement_arg, &__new_initializer_arg] {                                                                      \
-        __STABLE_SORT_NEW_IMPL(__placement_arg, __type, __new_initializer_func, __new_initializer_arg);                \
-      }();                                                                                                             \
-    } while (0)
+#  define _LIBCPP_MOVING_PLACEMENT_NEW(__ptr, __type, __move_func, __iter)                                             \
+    [__ptr, &__iter] { ::new ((void*)__ptr) __type(__move_func(__iter)); }()
 #else
-#  define __STABLE_SORT_NEW(__placement_arg, __type, __new_initializer_func, __new_initializer_arg)                    \
-    do {                                                                                                               \
-      __STABLE_SORT_NEW_IMPL(__placement_arg, __type, __new_initializer_func, __new_initializer_arg);                  \
-    } while (0)
+#  define _LIBCPP_MOVING_PLACEMENT_NEW(__ptr, __type, __move_func, __iter)                                             \
+    ::new ((void*)__ptr) __type(__move_func(__iter))
 #endif
 
 template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
@@ -68,7 +58,7 @@ _LIBCPP_HIDE_FROM_ABI void __insertion_sort_move(
     __destruct_n __d(0);
     unique_ptr<value_type, __destruct_n&> __h(__first2, __d);
     value_type* __last2 = __first2;
-    __STABLE_SORT_NEW(__last2, value_type, _Ops::__iter_move, __first1);
+    _LIBCPP_MOVING_PLACEMENT_NEW(__last2, value_type, _Ops::__iter_move, __first1);
     __d.template __incr<value_type>();
     for (++__last2; ++__first1 != __last1; ++__last2) {
       value_type* __j2 = __last2;
@@ -76,14 +66,14 @@ _LIBCPP_HIDE_FROM_ABI void __insertion_sort_move(
       if (__comp(*__first1, *--__i2)) {
         {
           value_type& __tmp = *__i2;
-          __STABLE_SORT_NEW(__j2, value_type, std::move, __tmp);
+          _LIBCPP_MOVING_PLACEMENT_NEW(__j2, value_type, std::move, __tmp);
         }
         __d.template __incr<value_type>();
         for (--__j2; __i2 != __first2 && __comp(*__first1, *--__i2); --__j2)
           *__j2 = std::move(*__i2);
         *__j2 = _Ops::__iter_move(__first1);
       } else {
-        __STABLE_SORT_NEW(__j2, value_type, _Ops::__iter_move, __first1);
+        _LIBCPP_MOVING_PLACEMENT_NEW(__j2, value_type, _Ops::__iter_move, __first1);
         __d.template __incr<value_type>();
       }
     }
@@ -107,27 +97,22 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __merge_move_construct(
   for (; true; ++__result) {
     if (__first1 == __last1) {
       for (; __first2 != __last2; ++__first2, (void)++__result, __d.template __incr<value_type>())
-        __STABLE_SORT_NEW(__result, value_type, _Ops::__iter_move, __first2);
+        _LIBCPP_MOVING_PLACEMENT_NEW(__result, value_type, _Ops::__iter_move, __first2);
       __h.release();
       return;
     }
     if (__first2 == __last2) {
       for (; __first1 != __last1; ++__first1, (void)++__result, __d.template __incr<value_type>())
-        __STABLE_SORT_NEW(__result, value_type, _Ops::__iter_move, __first1);
+        _LIBCPP_MOVING_PLACEMENT_NEW(__result, value_type, _Ops::__iter_move, __first1);
       __h.release();
       return;
     }
     if (__comp(*__first2, *__first1)) {
-      __STABLE_SORT_NEW(__result, value_type, _Ops::__iter_move, __first2);
+      _LIBCPP_MOVING_PLACEMENT_NEW(__result, value_type, _Ops::__iter_move, __first2);
       __d.template __incr<value_type>();
       ++__first2;
     } else {
-// __STABLE_SORT_NEW(__result, value_type, _Ops::__iter_move, __first1);
-#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 <= 140100)
-      [__result, &__first1] { ::new ((void*)__result) value_type(_Ops::__iter_move(__first1)); }();
-#else
-      ::new ((void*)__result) value_type(_Ops::__iter_move(__first1));
-#endif
+      _LIBCPP_MOVING_PLACEMENT_NEW(__result, value_type, _Ops::__iter_move, __first1);
       __d.template __incr<value_type>();
       ++__first1;
     }
@@ -185,21 +170,21 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort_move(
   case 0:
     return;
   case 1:
-    __STABLE_SORT_NEW(__first2, value_type, _Ops::__iter_move, __first1);
+    _LIBCPP_MOVING_PLACEMENT_NEW(__first2, value_type, _Ops::__iter_move, __first1);
     return;
   case 2:
     __destruct_n __d(0);
     unique_ptr<value_type, __destruct_n&> __h2(__first2, __d);
     if (__comp(*--__last1, *__first1)) {
-      __STABLE_SORT_NEW(__first2, value_type, _Ops::__iter_move, __last1);
+      _LIBCPP_MOVING_PLACEMENT_NEW(__first2, value_type, _Ops::__iter_move, __last1);
       __d.template __incr<value_type>();
       ++__first2;
-      __STABLE_SORT_NEW(__first2, value_type, _Ops::__iter_move, __first1);
+      _LIBCPP_MOVING_PLACEMENT_NEW(__first2, value_type, _Ops::__iter_move, __first1);
     } else {
-      __STABLE_SORT_NEW(__first2, value_type, _Ops::__iter_move, __first1);
+      _LIBCPP_MOVING_PLACEMENT_NEW(__first2, value_type, _Ops::__iter_move, __first1);
       __d.template __incr<value_type>();
       ++__first2;
-      __STABLE_SORT_NEW(__first2, value_type, _Ops::__iter_move, __last1);
+      _LIBCPP_MOVING_PLACEMENT_NEW(__first2, value_type, _Ops::__iter_move, __last1);
     }
     __h2.release();
     return;
@@ -297,8 +282,7 @@ stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) {
   std::stable_sort(__first, __last, __less<>());
 }
 
-#undef __STABLE_SORT_NEW
-#undef __STABLE_SORT_NEW_IMPL
+#undef _LIBCPP_MOVING_PLACEMENT_NEW
 _LIBCPP_END_NAMESPACE_STD
 _LIBCPP_POP_MACROS
 

>From 2f90ac3f35926ce21902e7e445ef13e1e22e0539 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sun, 13 Oct 2024 19:00:27 +0200
Subject: [PATCH 16/24] test: use TEST_STD_VER

---
 .../alg.sort/stable.sort/stable_sort.pass.cpp      | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
index cb32174a2ca0c50..720b93e5d1779c9 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
@@ -127,7 +127,7 @@ std::array<int, N> sort_reversely_swapped_sorted_ranges() {
   return array;
 }
 
-#if _LIBCPP_STD_VER >= 26
+#if TEST_STD_VER >= 26
 #  define COMPILE_OR_RUNTIME_ASSERT(func)                                                                              \
     if consteval {                                                                                                     \
       static_assert(func);                                                                                             \
@@ -148,7 +148,7 @@ TEST_CONSTEXPR_CXX26 void test_larger_sorts() {
     COMPILE_OR_RUNTIME_ASSERT(std::is_sorted(array.begin(), array.end()))
   }
 
-#if _LIBCPP_STD_VER >= 26
+#if TEST_STD_VER >= 26
   if !consteval
 #endif
   { // test random pattern
@@ -165,7 +165,7 @@ TEST_CONSTEXPR_CXX26 void test_larger_sorts() {
     COMPILE_OR_RUNTIME_ASSERT(std::is_sorted(array.begin(), array.end()))
   }
 
-#if _LIBCPP_STD_VER >= 26
+#if TEST_STD_VER >= 26
   if !consteval
 #endif
   { // test reverse sorted pattern
@@ -179,7 +179,7 @@ TEST_CONSTEXPR_CXX26 void test_larger_sorts() {
     COMPILE_OR_RUNTIME_ASSERT(std::is_sorted(array.begin(), array.end()))
   }
 
-#if _LIBCPP_STD_VER >= 26
+#if TEST_STD_VER >= 26
   if !consteval
 #endif
   { // test reverse swap ranges 2 pattern
@@ -202,7 +202,7 @@ TEST_CONSTEXPR_CXX26 void test_larger_sorts() {
   test_larger_sorts<N, N>();
 }
 
-#if _LIBCPP_STD_VER >= 26
+#if TEST_STD_VER >= 26
 #  define COMPILE_AND_RUNTIME_CALL(func)                                                                               \
     func;                                                                                                              \
     static_assert((func, true));
@@ -214,7 +214,7 @@ int main(int, char**) {
   { // test null range
     int d = 0;
     std::stable_sort(&d, &d);
-#if _LIBCPP_STD_VER >= 26
+#if TEST_STD_VER >= 26
     static_assert((std::stable_sort(&d, &d), true));
 #endif
   }
@@ -234,7 +234,7 @@ int main(int, char**) {
     // run- and conditionally compile-time tests
     test_larger_sorts<256>();
     test_larger_sorts<257>();
-#if _LIBCPP_STD_VER >= 26
+#if TEST_STD_VER >= 26
     static_assert((test_larger_sorts<256>(), true));
     static_assert((test_larger_sorts<257>(), true));
 #endif

>From c91a11af11795131d2e560f04579aa269243c2dc Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Fri, 18 Oct 2024 21:19:47 +0200
Subject: [PATCH 17/24] increase constexpr-steps as unstable abi tests cause
 more evaluation steps

---
 .../alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
index 720b93e5d1779c9..bcd5155138a169d 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
@@ -12,6 +12,8 @@
 //     constexpr void               // constexpr in C++26
 //     stable_sort(RandomAccessIterator first, RandomAccessIterator last);
 
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2000000
+
 #include <algorithm>
 #include <array>
 #include <cassert>
@@ -234,14 +236,16 @@ int main(int, char**) {
     // run- and conditionally compile-time tests
     test_larger_sorts<256>();
     test_larger_sorts<257>();
+    test_larger_sorts<499>();
+    test_larger_sorts<500>();
 #if TEST_STD_VER >= 26
     static_assert((test_larger_sorts<256>(), true));
     static_assert((test_larger_sorts<257>(), true));
+    static_assert((test_larger_sorts<499>(), true));
+    static_assert((test_larger_sorts<500>(), true));
 #endif
 
     // only runtime tests bc. error: "constexpr evaluation hit maximum step limit"
-    test_larger_sorts<499>();
-    test_larger_sorts<500>();
     test_larger_sorts<997>();
     test_larger_sorts<1000>();
     test_larger_sorts<1009>();

>From 47afcf17b679b0d8507fd02e92b928e82ebdd0cb Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Fri, 18 Oct 2024 22:06:51 +0200
Subject: [PATCH 18/24] simplify testing (possible b.c. increase of
 constexpr-steps)

---
 .../alg.sort/stable.sort/stable_sort.pass.cpp | 53 +++++--------------
 1 file changed, 12 insertions(+), 41 deletions(-)

diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
index bcd5155138a169d..8302c59ef0ef546 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
@@ -12,7 +12,7 @@
 //     constexpr void               // constexpr in C++26
 //     stable_sort(RandomAccessIterator first, RandomAccessIterator last);
 
-// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2000000
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=20000000
 
 #include <algorithm>
 #include <array>
@@ -105,7 +105,7 @@ TEST_CONSTEXPR_CXX26 std::array<int, N> sort_already_sorted() {
 }
 
 template <int N, int M>
-std::array<int, N> sort_reversely_sorted() {
+TEST_CONSTEXPR_CXX26 std::array<int, N> sort_reversely_sorted() {
   std::array<int, N> array = sort_saw_tooth_pattern<N, M>();
   std::reverse(array.begin(), array.end());
   std::stable_sort(array.begin(), array.end());
@@ -121,7 +121,7 @@ TEST_CONSTEXPR_CXX26 std::array<int, N> sort_swapped_sorted_ranges() {
 }
 
 template <int N, int M>
-std::array<int, N> sort_reversely_swapped_sorted_ranges() {
+TEST_CONSTEXPR_CXX26 std::array<int, N> sort_reversely_swapped_sorted_ranges() {
   std::array<int, N> array = sort_saw_tooth_pattern<N, M>();
   std::reverse(array.begin(), array.end());
   std::swap_ranges(array.begin(), array.begin() + N / 2, array.begin() + N / 2);
@@ -129,25 +129,14 @@ std::array<int, N> sort_reversely_swapped_sorted_ranges() {
   return array;
 }
 
-#if TEST_STD_VER >= 26
-#  define COMPILE_OR_RUNTIME_ASSERT(func)                                                                              \
-    if consteval {                                                                                                     \
-      static_assert(func);                                                                                             \
-    } else {                                                                                                           \
-      assert(func);                                                                                                    \
-    }
-#else
-#  define COMPILE_OR_RUNTIME_ASSERT(func) assert(func);
-#endif
-
 template <int N, int M>
 TEST_CONSTEXPR_CXX26 void test_larger_sorts() {
   static_assert(N > 0, "");
   static_assert(M > 0, "");
 
   { // test saw tooth pattern
-    TEST_CONSTEXPR_CXX26 std::array<int, N> array = sort_saw_tooth_pattern<N, M>();
-    COMPILE_OR_RUNTIME_ASSERT(std::is_sorted(array.begin(), array.end()))
+    std::array<int, N> array = sort_saw_tooth_pattern<N, M>();
+    assert(std::is_sorted(array.begin(), array.end()));
   }
 
 #if TEST_STD_VER >= 26
@@ -163,29 +152,21 @@ TEST_CONSTEXPR_CXX26 void test_larger_sorts() {
   }
 
   { // test sorted pattern
-    TEST_CONSTEXPR_CXX26 std::array<int, N> array = sort_already_sorted<N, M>();
-    COMPILE_OR_RUNTIME_ASSERT(std::is_sorted(array.begin(), array.end()))
+    std::array<int, N> array = sort_already_sorted<N, M>();
+    assert(std::is_sorted(array.begin(), array.end()));
   }
 
-#if TEST_STD_VER >= 26
-  if !consteval
-#endif
   { // test reverse sorted pattern
-    // consteval error: "constexpr evaluation hit maximum step limit"
     std::array<int, N> array = sort_reversely_sorted<N, M>();
     assert(std::is_sorted(array.begin(), array.end()));
   }
 
   { // test swap ranges 2 pattern
-    TEST_CONSTEXPR_CXX26 std::array<int, N> array = sort_swapped_sorted_ranges<N, M>();
-    COMPILE_OR_RUNTIME_ASSERT(std::is_sorted(array.begin(), array.end()))
+    std::array<int, N> array = sort_swapped_sorted_ranges<N, M>();
+    assert(std::is_sorted(array.begin(), array.end()));
   }
 
-#if TEST_STD_VER >= 26
-  if !consteval
-#endif
   { // test reverse swap ranges 2 pattern
-    // consteval error: "constexpr evaluation hit maximum step limit"
     std::array<int, N> array = sort_reversely_swapped_sorted_ranges<N, M>();
     assert(std::is_sorted(array.begin(), array.end()));
   }
@@ -204,14 +185,6 @@ TEST_CONSTEXPR_CXX26 void test_larger_sorts() {
   test_larger_sorts<N, N>();
 }
 
-#if TEST_STD_VER >= 26
-#  define COMPILE_AND_RUNTIME_CALL(func)                                                                               \
-    func;                                                                                                              \
-    static_assert((func, true));
-#else
-#  define COMPILE_AND_RUNTIME_CALL(func) func;
-#endif
-
 int main(int, char**) {
   { // test null range
     int d = 0;
@@ -233,19 +206,17 @@ int main(int, char**) {
   }
 
   { // larger sorts
-    // run- and conditionally compile-time tests
+    // run- and compile-time tests
     test_larger_sorts<256>();
     test_larger_sorts<257>();
-    test_larger_sorts<499>();
-    test_larger_sorts<500>();
 #if TEST_STD_VER >= 26
     static_assert((test_larger_sorts<256>(), true));
     static_assert((test_larger_sorts<257>(), true));
-    static_assert((test_larger_sorts<499>(), true));
-    static_assert((test_larger_sorts<500>(), true));
 #endif
 
     // only runtime tests bc. error: "constexpr evaluation hit maximum step limit"
+    test_larger_sorts<499>();
+    test_larger_sorts<500>();
     test_larger_sorts<997>();
     test_larger_sorts<1000>();
     test_larger_sorts<1009>();

>From 61cc660f5a0f48de10cf3f767d3b8a99775bfec6 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sat, 9 Nov 2024 12:56:13 +0100
Subject: [PATCH 19/24] refactor tests: do not extract tests into separate
 functions

---
 .../alg.sort/stable.sort/stable_sort.pass.cpp | 163 +++++++-----------
 1 file changed, 60 insertions(+), 103 deletions(-)

diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
index 8302c59ef0ef546..e924d3562c92465 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
@@ -80,96 +80,48 @@ test_sort_()
 }
 
 template <int N, int M>
-TEST_CONSTEXPR_CXX26 std::array<int, N> init_saw_tooth_pattern() {
-  std::array<int, N> array;
-  for (int i = 0, x = 0; i < N; ++i) {
+TEST_CONSTEXPR_CXX26 void test_larger_sorts() {
+  static_assert(N != 0);
+  static_assert(M != 0);
+
+  // create array length N filled with M different numbers
+  std::array<int, N> array_;
+  int* const array = array_.data();
+  int x            = 0;
+  for (int i = 0; i < N; ++i) {
     array[i] = x;
     if (++x == M)
       x = 0;
   }
-  return array;
-}
-
-template <int N, int M>
-TEST_CONSTEXPR_CXX26 std::array<int, N> sort_saw_tooth_pattern() {
-  std::array<int, N> array = init_saw_tooth_pattern<N, M>();
-  std::stable_sort(array.begin(), array.end());
-  return array;
-}
-
-template <int N, int M>
-TEST_CONSTEXPR_CXX26 std::array<int, N> sort_already_sorted() {
-  std::array<int, N> array = sort_saw_tooth_pattern<N, M>();
-  std::stable_sort(array.begin(), array.end());
-  return array;
-}
-
-template <int N, int M>
-TEST_CONSTEXPR_CXX26 std::array<int, N> sort_reversely_sorted() {
-  std::array<int, N> array = sort_saw_tooth_pattern<N, M>();
-  std::reverse(array.begin(), array.end());
-  std::stable_sort(array.begin(), array.end());
-  return array;
-}
-
-template <int N, int M>
-TEST_CONSTEXPR_CXX26 std::array<int, N> sort_swapped_sorted_ranges() {
-  std::array<int, N> array = sort_saw_tooth_pattern<N, M>();
-  std::swap_ranges(array.begin(), array.begin() + N / 2, array.begin() + N / 2);
-  std::stable_sort(array.begin(), array.end());
-  return array;
-}
-
-template <int N, int M>
-TEST_CONSTEXPR_CXX26 std::array<int, N> sort_reversely_swapped_sorted_ranges() {
-  std::array<int, N> array = sort_saw_tooth_pattern<N, M>();
-  std::reverse(array.begin(), array.end());
-  std::swap_ranges(array.begin(), array.begin() + N / 2, array.begin() + N / 2);
-  std::stable_sort(array.begin(), array.end());
-  return array;
-}
-
-template <int N, int M>
-TEST_CONSTEXPR_CXX26 void test_larger_sorts() {
-  static_assert(N > 0, "");
-  static_assert(M > 0, "");
-
-  { // test saw tooth pattern
-    std::array<int, N> array = sort_saw_tooth_pattern<N, M>();
-    assert(std::is_sorted(array.begin(), array.end()));
-  }
-
+  // test saw tooth pattern
+  std::stable_sort(array, array + N);
+  assert(std::is_sorted(array, array + N));
+  // test random pattern
 #if TEST_STD_VER >= 26
-  if !consteval
+  if !consteval // random-number generators not constexpr-friendly
 #endif
-  { // test random pattern
-    // random-number generators not constexpr-friendly
+  {
     static std::mt19937 randomness;
-    std::array<int, N> array = init_saw_tooth_pattern<N, M>();
-    std::shuffle(array.begin(), array.end(), randomness);
-    std::stable_sort(array.begin(), array.end());
-    assert(std::is_sorted(array.begin(), array.end()));
-  }
-
-  { // test sorted pattern
-    std::array<int, N> array = sort_already_sorted<N, M>();
-    assert(std::is_sorted(array.begin(), array.end()));
-  }
-
-  { // test reverse sorted pattern
-    std::array<int, N> array = sort_reversely_sorted<N, M>();
-    assert(std::is_sorted(array.begin(), array.end()));
-  }
-
-  { // test swap ranges 2 pattern
-    std::array<int, N> array = sort_swapped_sorted_ranges<N, M>();
-    assert(std::is_sorted(array.begin(), array.end()));
-  }
-
-  { // test reverse swap ranges 2 pattern
-    std::array<int, N> array = sort_reversely_swapped_sorted_ranges<N, M>();
-    assert(std::is_sorted(array.begin(), array.end()));
+    std::shuffle(array, array + N, randomness);
+    std::stable_sort(array, array + N);
+    assert(std::is_sorted(array, array + N));
   }
+  // test sorted pattern
+  std::stable_sort(array, array + N);
+  assert(std::is_sorted(array, array + N));
+  // test reverse sorted pattern
+  std::reverse(array, array + N);
+  std::stable_sort(array, array + N);
+  assert(std::is_sorted(array, array + N));
+  // test swap ranges 2 pattern
+  std::swap_ranges(array, array + N / 2, array + N / 2);
+  std::stable_sort(array, array + N);
+  assert(std::is_sorted(array, array + N));
+  // test reverse swap ranges 2 pattern
+  std::reverse(array, array + N);
+  std::swap_ranges(array, array + N / 2, array + N / 2);
+  std::stable_sort(array, array + N);
+  assert(std::is_sorted(array, array + N));
 }
 
 template <int N>
@@ -185,16 +137,16 @@ TEST_CONSTEXPR_CXX26 void test_larger_sorts() {
   test_larger_sorts<N, N>();
 }
 
-int main(int, char**) {
-  { // test null range
-    int d = 0;
-    std::stable_sort(&d, &d);
+TEST_CONSTEXPR_CXX26 void test() {
+  // test null range
+  int d = 0;
+  std::stable_sort(&d, &d);
+
+  // exhaustively test all possibilities up to length 8
 #if TEST_STD_VER >= 26
-    static_assert((std::stable_sort(&d, &d), true));
+  if !consteval
 #endif
-  }
-
-  { // exhaustively test all possibilities up to length 8
+  {
     test_sort_<1>();
     test_sort_<2>();
     test_sort_<3>();
@@ -205,30 +157,35 @@ int main(int, char**) {
     test_sort_<8>();
   }
 
-  { // larger sorts
-    // run- and compile-time tests
-    test_larger_sorts<256>();
-    test_larger_sorts<257>();
+  test_larger_sorts<256>();
+  test_larger_sorts<257>();
+  test_larger_sorts<499>();
+  test_larger_sorts<500>();
+  test_larger_sorts<997>();
 #if TEST_STD_VER >= 26
-    static_assert((test_larger_sorts<256>(), true));
-    static_assert((test_larger_sorts<257>(), true));
+  if !consteval // only runtime tests bc. error: "constexpr evaluation hit maximum step limit"
 #endif
-
-    // only runtime tests bc. error: "constexpr evaluation hit maximum step limit"
-    test_larger_sorts<499>();
-    test_larger_sorts<500>();
-    test_larger_sorts<997>();
+  {
     test_larger_sorts<1000>();
     test_larger_sorts<1009>();
   }
 
-#ifndef TEST_HAS_NO_EXCEPTIONS
+#if !defined(TEST_HAS_NO_EXCEPTIONS)
+#  if TEST_STD_VER >= 26
+  if !consteval
+#  endif
   { // check that the algorithm works without memory
     std::vector<int> vec(150, 3);
     getGlobalMemCounter()->throw_after = 0;
     std::stable_sort(vec.begin(), vec.end());
   }
-#endif
+#endif // !defined(TEST_HAS_NO_EXCEPTIONS)
+}
 
+int main(int, char**) {
+  test();
+#if TEST_STD_VER >= 26
+  static_assert((test(), true));
+#endif
   return 0;
 }

>From 648f1260d14b8a31a1e335db6f1e22330b6f0ccd Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sat, 9 Nov 2024 13:04:48 +0100
Subject: [PATCH 20/24] tests: match previous formatting

---
 .../alg.sort/stable.sort/stable_sort.pass.cpp | 185 +++++++++---------
 1 file changed, 96 insertions(+), 89 deletions(-)

diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
index e924d3562c92465..bcc4505b4c0f3c9 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
@@ -80,112 +80,119 @@ test_sort_()
 }
 
 template <int N, int M>
-TEST_CONSTEXPR_CXX26 void test_larger_sorts() {
-  static_assert(N != 0);
-  static_assert(M != 0);
-
-  // create array length N filled with M different numbers
-  std::array<int, N> array_;
-  int* const array = array_.data();
-  int x            = 0;
-  for (int i = 0; i < N; ++i) {
-    array[i] = x;
-    if (++x == M)
-      x = 0;
-  }
-  // test saw tooth pattern
-  std::stable_sort(array, array + N);
-  assert(std::is_sorted(array, array + N));
-  // test random pattern
+TEST_CONSTEXPR_CXX26
+void
+test_larger_sorts()
+{
+    static_assert(N != 0);
+    static_assert(M != 0);
+    // create array length N filled with M different numbers
+    std::array<int, N> array_;
+    int* array = array_.data();
+    int x = 0;
+    for (int i = 0; i < N; ++i)
+    {
+        array[i] = x;
+        if (++x == M)
+            x = 0;
+    }
+    // test saw tooth pattern
+    std::stable_sort(array, array+N);
+    assert(std::is_sorted(array, array+N));
+    // test random pattern
 #if TEST_STD_VER >= 26
-  if !consteval // random-number generators not constexpr-friendly
+    if !consteval // random-number generators not constexpr-friendly
 #endif
-  {
-    static std::mt19937 randomness;
-    std::shuffle(array, array + N, randomness);
-    std::stable_sort(array, array + N);
-    assert(std::is_sorted(array, array + N));
-  }
-  // test sorted pattern
-  std::stable_sort(array, array + N);
-  assert(std::is_sorted(array, array + N));
-  // test reverse sorted pattern
-  std::reverse(array, array + N);
-  std::stable_sort(array, array + N);
-  assert(std::is_sorted(array, array + N));
-  // test swap ranges 2 pattern
-  std::swap_ranges(array, array + N / 2, array + N / 2);
-  std::stable_sort(array, array + N);
-  assert(std::is_sorted(array, array + N));
-  // test reverse swap ranges 2 pattern
-  std::reverse(array, array + N);
-  std::swap_ranges(array, array + N / 2, array + N / 2);
-  std::stable_sort(array, array + N);
-  assert(std::is_sorted(array, array + N));
+    {
+        static std::mt19937 randomness;
+        std::shuffle(array, array+N, randomness);
+        std::stable_sort(array, array+N);
+        assert(std::is_sorted(array, array+N));
+    }
+    // test sorted pattern
+    std::stable_sort(array, array+N);
+    assert(std::is_sorted(array, array+N));
+    // test reverse sorted pattern
+    std::reverse(array, array+N);
+    std::stable_sort(array, array+N);
+    assert(std::is_sorted(array, array+N));
+    // test swap ranges 2 pattern
+    std::swap_ranges(array, array+N/2, array+N/2);
+    std::stable_sort(array, array+N);
+    assert(std::is_sorted(array, array+N));
+    // test reverse swap ranges 2 pattern
+    std::reverse(array, array+N);
+    std::swap_ranges(array, array+N/2, array+N/2);
+    std::stable_sort(array, array+N);
+    assert(std::is_sorted(array, array+N));
 }
 
 template <int N>
-TEST_CONSTEXPR_CXX26 void test_larger_sorts() {
-  test_larger_sorts<N, 1>();
-  test_larger_sorts<N, 2>();
-  test_larger_sorts<N, 3>();
-  test_larger_sorts<N, N / 2 - 1>();
-  test_larger_sorts<N, N / 2>();
-  test_larger_sorts<N, N / 2 + 1>();
-  test_larger_sorts<N, N - 2>();
-  test_larger_sorts<N, N - 1>();
-  test_larger_sorts<N, N>();
+TEST_CONSTEXPR_CXX26
+void
+test_larger_sorts()
+{
+    test_larger_sorts<N, 1>();
+    test_larger_sorts<N, 2>();
+    test_larger_sorts<N, 3>();
+    test_larger_sorts<N, N/2-1>();
+    test_larger_sorts<N, N/2>();
+    test_larger_sorts<N, N/2+1>();
+    test_larger_sorts<N, N-2>();
+    test_larger_sorts<N, N-1>();
+    test_larger_sorts<N, N>();
 }
 
-TEST_CONSTEXPR_CXX26 void test() {
-  // test null range
-  int d = 0;
-  std::stable_sort(&d, &d);
-
-  // exhaustively test all possibilities up to length 8
+TEST_CONSTEXPR_CXX26 void test()
+{
+    // test null range
+    int d = 0;
+    std::stable_sort(&d, &d);
+  
+    // exhaustively test all possibilities up to length 8
 #if TEST_STD_VER >= 26
-  if !consteval
+    if !consteval
 #endif
-  {
-    test_sort_<1>();
-    test_sort_<2>();
-    test_sort_<3>();
-    test_sort_<4>();
-    test_sort_<5>();
-    test_sort_<6>();
-    test_sort_<7>();
-    test_sort_<8>();
-  }
-
-  test_larger_sorts<256>();
-  test_larger_sorts<257>();
-  test_larger_sorts<499>();
-  test_larger_sorts<500>();
-  test_larger_sorts<997>();
+    {
+        test_sort_<1>();
+        test_sort_<2>();
+        test_sort_<3>();
+        test_sort_<4>();
+        test_sort_<5>();
+        test_sort_<6>();
+        test_sort_<7>();
+        test_sort_<8>();
+    }
+  
+    test_larger_sorts<256>();
+    test_larger_sorts<257>();
+    test_larger_sorts<499>();
+    test_larger_sorts<500>();
+    test_larger_sorts<997>();
 #if TEST_STD_VER >= 26
-  if !consteval // only runtime tests bc. error: "constexpr evaluation hit maximum step limit"
+    if !consteval // only runtime tests bc. error: "constexpr evaluation hit maximum step limit"
 #endif
-  {
-    test_larger_sorts<1000>();
-    test_larger_sorts<1009>();
-  }
+    {
+        test_larger_sorts<1000>();
+        test_larger_sorts<1009>();
+    }
 
 #if !defined(TEST_HAS_NO_EXCEPTIONS)
-#  if TEST_STD_VER >= 26
-  if !consteval
-#  endif
-  { // check that the algorithm works without memory
-    std::vector<int> vec(150, 3);
-    getGlobalMemCounter()->throw_after = 0;
-    std::stable_sort(vec.begin(), vec.end());
-  }
+#if TEST_STD_VER >= 26
+    if !consteval
+#endif
+    { // check that the algorithm works without memory
+        std::vector<int> vec(150, 3);
+        getGlobalMemCounter()->throw_after = 0;
+        std::stable_sort(vec.begin(), vec.end());
+    }
 #endif // !defined(TEST_HAS_NO_EXCEPTIONS)
 }
 
 int main(int, char**) {
-  test();
+    test();
 #if TEST_STD_VER >= 26
-  static_assert((test(), true));
+    static_assert((test(), true));
 #endif
-  return 0;
+    return 0;
 }

>From d24a71411937fa43d9428d5b32138e54fd2ae213 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sat, 9 Nov 2024 13:21:56 +0100
Subject: [PATCH 21/24] disable large test at compiletime

---
 .../alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
index bcc4505b4c0f3c9..eb484bc9440f24d 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
@@ -168,11 +168,11 @@ TEST_CONSTEXPR_CXX26 void test()
     test_larger_sorts<257>();
     test_larger_sorts<499>();
     test_larger_sorts<500>();
-    test_larger_sorts<997>();
 #if TEST_STD_VER >= 26
     if !consteval // only runtime tests bc. error: "constexpr evaluation hit maximum step limit"
 #endif
     {
+        test_larger_sorts<997>();
         test_larger_sorts<1000>();
         test_larger_sorts<1009>();
     }

>From 61a5556fde397deec7e5ba250b85a0bd4624fcfc Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sat, 9 Nov 2024 13:22:35 +0100
Subject: [PATCH 22/24] use construct_at for placement new gcc workaround

---
 libcxx/include/__algorithm/stable_sort.h | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index 640babe4c4466bb..7048ae2caf08b60 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -18,6 +18,7 @@
 #include <__cstddef/ptrdiff_t.h>
 #include <__debug_utils/strict_weak_ordering_check.h>
 #include <__iterator/iterator_traits.h>
+#include <__memory/construct_at.h>
 #include <__memory/destruct_n.h>
 #include <__memory/unique_ptr.h>
 #include <__memory/unique_temporary_buffer.h>
@@ -37,9 +38,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 // Workaround for "constexpr placement new" bug in gcc (fixed in 14.2).
 // See https://github.com/llvm/llvm-project/pull/110320#discussion_r1788557715.
-#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 <= 140100)
-#  define _LIBCPP_MOVING_PLACEMENT_NEW(__ptr, __type, __move_func, __iter)                                             \
-    [__ptr, &__iter] { ::new ((void*)__ptr) __type(__move_func(__iter)); }()
+#if (_LIBCPP_STD_VER >= 20) ||                                                                                         \
+    (!defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 <= 140100))
+#  define _LIBCPP_MOVING_PLACEMENT_NEW(__ptr, __type, __move_func, __iter) std::construct_at(__ptr, __move_func(__iter))
 #else
 #  define _LIBCPP_MOVING_PLACEMENT_NEW(__ptr, __type, __move_func, __iter)                                             \
     ::new ((void*)__ptr) __type(__move_func(__iter))

>From 58ab844ee49afa95b04a02ac0ed54ca07b7092b8 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sat, 9 Nov 2024 17:20:53 +0100
Subject: [PATCH 23/24] tests: fix static asserts

---
 .../alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp     | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
index eb484bc9440f24d..8548f1b01d77ac2 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
@@ -84,8 +84,8 @@ TEST_CONSTEXPR_CXX26
 void
 test_larger_sorts()
 {
-    static_assert(N != 0);
-    static_assert(M != 0);
+    static_assert(N != 0, "");
+    static_assert(M != 0, "");
     // create array length N filled with M different numbers
     std::array<int, N> array_;
     int* array = array_.data();

>From e9ec61509d23c1b44b0f12d66472dcb6209b4235 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sun, 10 Nov 2024 16:49:56 +0100
Subject: [PATCH 24/24] test: gcc hits constexpr operation limit

---
 .../alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp     | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
index 8548f1b01d77ac2..ea5f787390a8d8c 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
@@ -166,12 +166,12 @@ TEST_CONSTEXPR_CXX26 void test()
   
     test_larger_sorts<256>();
     test_larger_sorts<257>();
-    test_larger_sorts<499>();
-    test_larger_sorts<500>();
 #if TEST_STD_VER >= 26
     if !consteval // only runtime tests bc. error: "constexpr evaluation hit maximum step limit"
 #endif
     {
+        test_larger_sorts<499>();
+        test_larger_sorts<500>();
         test_larger_sorts<997>();
         test_larger_sorts<1000>();
         test_larger_sorts<1009>();



More information about the libcxx-commits mailing list