The logic of the null pointer check got reversed when converting the
std::stable_sort code for ranges::stable_sort.

libstdc++-v3/ChangeLog:

        PR libstdc++/123180
        * include/bits/ranges_algo.h (__stable_sort_fn::operator()): Fix
        sense of null check. Replace typedef with alias-declaration.
        * testsuite/25_algorithms/stable_sort/123180.cc: New test.
---

Tested x86_64-linux.

 libstdc++-v3/include/bits/ranges_algo.h       |  4 +-
 .../25_algorithms/stable_sort/123180.cc       | 66 +++++++++++++++++++
 2 files changed, 68 insertions(+), 2 deletions(-)
 create mode 100644 libstdc++-v3/testsuite/25_algorithms/stable_sort/123180.cc

diff --git a/libstdc++-v3/include/bits/ranges_algo.h 
b/libstdc++-v3/include/bits/ranges_algo.h
index 5c9fe627aee0..92e298633cf4 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -2709,7 +2709,7 @@ namespace ranges
            }
 # endif
 
-           typedef _Temporary_buffer<_Iter, iter_value_t<_Iter>> _TmpBuf;
+           using _TmpBuf = _Temporary_buffer<_Iter, iter_value_t<_Iter>>;
            // __stable_sort_adaptive sorts the range in two halves,
            // so the buffer only needs to fit half the range at once.
            _TmpBuf __buf(__first, ptrdiff_t((__last - __first + 1) / 2));
@@ -2718,7 +2718,7 @@ namespace ranges
              __detail::__stable_sort_adaptive(__first,
                                               __first + 
_DistanceType(__buf.size()),
                                               __last, __buf.begin(), 
__comp_proj);
-           else if (__buf.begin()) [[unlikely]]
+           else if (__buf.begin() == nullptr) [[unlikely]]
              __detail::__inplace_stable_sort(__first, __last, __comp_proj);
            else
              __detail::__stable_sort_adaptive_resize(__first, __last, 
__buf.begin(),
diff --git a/libstdc++-v3/testsuite/25_algorithms/stable_sort/123180.cc 
b/libstdc++-v3/testsuite/25_algorithms/stable_sort/123180.cc
new file mode 100644
index 000000000000..7c56f37142e0
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/stable_sort/123180.cc
@@ -0,0 +1,66 @@
+// { dg-do run }
+
+#include <algorithm>
+#include <new>
+#include <cstdlib>
+#include <cstdio>
+
+#if __cplusplus < 201103L
+# define NOEXCEPT throw()
+# define nullptr 0
+# define THROW_BAD_ALLOC throw(std::bad_alloc)
+#else
+# define NOEXCEPT noexcept
+# define THROW_BAD_ALLOC noexcept(false)
+#endif
+
+std::size_t limit = -1u;
+
+void* operator new(std::size_t n, const std::nothrow_t&) NOEXCEPT
+{
+  if (n > limit)
+    return NULL;
+  return std::malloc(n);
+}
+
+void* operator new(std::size_t n) THROW_BAD_ALLOC
+{
+  return std::malloc(n);
+}
+
+void operator delete(void* p) NOEXCEPT { std::free(p); }
+#ifdef __cpp_sized_deallocation
+void operator delete(void* p, std::size_t) NOEXCEPT { std::free(p); }
+#endif
+
+void
+test_stl_algo()
+{
+  int a[] = { 4, 6, 2, 1, 7, 9, 2, 2, 2, 8 };
+  limit = -1u;
+  std::stable_sort(a, a+10); // gets as much memory as it needs
+  limit = 2 * sizeof(int);
+  std::stable_sort(a, a+10); // only gets memory for two ints
+  limit = 0;
+  std::stable_sort(a, a+10); // gets no memory
+}
+
+void
+test_ranges_algo()
+{
+#if __cplusplus >= 202002L
+  int a[] = { 4, 6, 2, 1, 7, 9, 2, 2, 2, 8 };
+  limit = -1u;
+  std::ranges::stable_sort(a); // gets as much memory as it needs
+  limit = 2 * sizeof(int);
+  std::ranges::stable_sort(a); // only gets memory for two ints
+  limit = 0;
+  std::ranges::stable_sort(a); // gets no memory
+#endif
+}
+
+int main()
+{
+  test_stl_algo();
+  test_ranges_algo();
+}
-- 
2.52.0

Reply via email to