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