libstdc++: Fix ranges::stable_sort handling of null buffer [PR123180]

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.

Reviewed-by: Patrick Palka <ppalka@redhat.com>
This commit is contained in:
Jonathan Wakely
2025-12-18 10:38:31 +00:00
committed by Jonathan Wakely
parent 1ed9526113
commit 630c1bfbb5
2 changed files with 68 additions and 2 deletions

View File

@@ -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(),

View File

@@ -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();
}