---
libstdc++-v3/include/bits/new_allocator.h | 30 ++++++---
.../20_util/allocator/allocate_at_least2.cc | 66 +++++++++++++++++++
.../vector/modifiers/insert_vs_emplace.cc | 48 +++++++++-----
3 files changed, 116 insertions(+), 28 deletions(-)
create mode 100644 libstdc++-v3/testsuite/20_util/allocator/
allocate_at_least2.cc
diff --git a/libstdc++-v3/include/bits/new_allocator.h b/libstdc++-
v3/include/bits/new_allocator.h
index 4524355a4a0..e7666b5831c 100644
--- a/libstdc++-v3/include/bits/new_allocator.h
+++ b/libstdc++-v3/include/bits/new_allocator.h
@@ -177,6 +177,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
[[nodiscard]] constexpr std::allocation_result<_Tp*, size_t>
allocate_at_least(size_t __n)
{
+#if __cpp_aligned_new
if ! consteval
{
if constexpr (requires { sizeof(_Tp); })
@@ -184,19 +185,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if constexpr ( sizeof(_Tp) <
__STDCPP_DEFAULT_NEW_ALIGNMENT__)
{
_S_check_allocation_limit(__n);
- const size_t __need = __n * sizeof(_Tp);
+ size_t __bytes = __n * sizeof(_Tp);
const size_t __mask =
__STDCPP_DEFAULT_NEW_ALIGNMENT__ - 1;
- size_t __ask = (__need + __mask) & ~__mask;
- // Avoid rounding up to and asking for 2^63 bytes
(PR108377):
- __ask -= __ask >> (__SIZE_WIDTH__ - 1);
- auto* __p =
static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__ask));
- using _U8 = const unsigned char;
- static_assert(sizeof(_Tp) <= ~_U8());
- // Use 8-bit division for minimal latency:
- _U8 __spare = __ask - __need, __size = sizeof(_Tp);
- return { __p , __n + __spare / __size };
+ size_t __max = (__bytes + __mask) & ~__mask;
+ // Avoid seeming to ask for 2^63 bytes (PR108377):
+ __max -= __max >> (__SIZE_WIDTH__ - 1);
+ auto __spare = static_cast<unsigned>(__max - __bytes);
+ if constexpr (sizeof(_Tp) < (__mask + 1) / 2)
+ {
+ auto __bonus = __spare / sizeof(_Tp);
+ __n += __bonus;
+ __bytes += __bonus * sizeof(_Tp);
+ }
+ else if (sizeof(_Tp) <= __spare)
+ {
+ __n += 1;
+ __bytes += sizeof(_Tp);
+ }
+ void* __p = _GLIBCXX_OPERATOR_NEW(__bytes);
+ return { static_cast<_Tp*>(__p), __n };
}
}
+#endif
return { allocate(__n), __n };
}
#endif
diff --git a/libstdc++-v3/testsuite/20_util/allocator/
allocate_at_least2.cc b/libstdc++-v3/testsuite/20_util/allocator/
allocate_at_least2.cc
new file mode 100644
index 00000000000..4f8645ed50d
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/allocator/allocate_at_least2.cc
@@ -0,0 +1,66 @@
+// { dg-do run { target c++23 } }
+
+#include <memory>
+#include <stdlib.h>
+#include <testsuite_hooks.h>
+
+std::size_t gn = 0;
+void* operator new(std::size_t n)
+{
+ gn = n;
+ return ::malloc(n);
+}
+
+// Failing to define ops delete, too, would generate warnings.
+
+void operator delete(void* p) noexcept
+{ ::free(p); }
+
+#if __cpp_sized_deallocation
+void operator delete(void* p, std::size_t) noexcept
+{ ::free(p); }
+#endif
+
+template <unsigned size, unsigned n>
+void test_nm()
+{
+ struct A { char a[size]; };
+ std::allocator<A> alloc;
+ using alloc_traits = std::allocator_traits<std::allocator<A>>;
+ auto [p, m] = alloc_traits::allocate_at_least(alloc, n);
+
+#if __cpp_aligned_new
+ unsigned mod = __STDCPP_DEFAULT_NEW_ALIGNMENT__;
+ unsigned max = ((n * size) + mod - 1) & ~(mod - 1);
+ unsigned count = max / sizeof(A);
+#else
+ unsigned count = n;
+#endif
+ VERIFY(m == count);
+ VERIFY(gn == count * sizeof(A));
+ VERIFY(p != nullptr); // named it, use it.
+}
+
+void test()
+{ // m gn
+ test_nm<1,3>(); // 16 16
+ test_nm<2,3>(); // 8 16
+ test_nm<3,3>(); // 5 15
+ test_nm<4,3>(); // 4 16
+ test_nm<5,3>(); // 3 15
+ test_nm<6,3>(); // 5 30
+ test_nm<7,3>(); // 4 28
+ test_nm<8,3>(); // 4 32
+ test_nm<9,3>(); // 3 27
+ test_nm<10,3>(); // 3 30
+ test_nm<11,3>(); // 4 44
+ test_nm<12,3>(); // 4 48
+ test_nm<13,3>(); // 3 39
+ test_nm<14,3>(); // 3 42
+ test_nm<15,3>(); // 3 45
+}
+
+int main()
+{
+ test();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/
insert_vs_emplace.cc b/libstdc++-v3/testsuite/23_containers/vector/
modifiers/insert_vs_emplace.cc
index 187e433d9d3..d226490d6f3 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/
insert_vs_emplace.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/
insert_vs_emplace.cc
@@ -223,11 +223,12 @@ test03()
void
test04()
{
- const X::special expected{ 0, 3, 1, 0, 3, 0 };
+ const X::special expected{ 0, 4, 1, 0, 4, 0 };
X::special ins, emp;
{
std::vector<X> v;
- v.reserve(3);
+ v.reserve(4);
+ v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
@@ -241,7 +242,8 @@ test04()
}
{
std::vector<X> v;
- v.reserve(3);
+ v.reserve(4);
+ v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
@@ -261,11 +263,12 @@ test04()
void
test05()
{
- const X::special expected{ 0, 3, 0, 0, 4, 0 };
+ const X::special expected{ 0, 4, 0, 0, 5, 0 };
X::special ins, emp;
{
std::vector<X> v;
- v.reserve(3);
+ v.reserve(4);
+ v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
@@ -279,7 +282,8 @@ test05()
}
{
std::vector<X> v;
- v.reserve(3);
+ v.reserve(4);
+ v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
@@ -299,11 +303,12 @@ test05()
void
test06()
{
- const X::special expected{ 1, 4, 0, 0, 4, 0 };
+ const X::special expected{ 1, 5, 0, 0, 5, 0 };
X::special ins, emp;
{
std::vector<X> v;
- v.reserve(3);
+ v.reserve(4);
+ v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
@@ -316,7 +321,8 @@ test06()
}
{
std::vector<X> v;
- v.reserve(3);
+ v.reserve(4);
+ v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
@@ -447,11 +453,12 @@ test09()
void
test10()
{
- const X::special expected{ 0, 3, 1, 0, 3, 0 };
+ const X::special expected{ 0, 4, 1, 0, 4, 0 };
X::special ins, emp;
{
std::vector<X> v;
- v.reserve(3);
+ v.reserve(4);
+ v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
@@ -465,7 +472,8 @@ test10()
}
{
std::vector<X> v;
- v.reserve(3);
+ v.reserve(4);
+ v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
@@ -485,11 +493,12 @@ test10()
void
test11()
{
- const X::special expected{ 0, 3, 0, 0, 4, 0 };
+ const X::special expected{ 0, 4, 0, 0, 5, 0 };
X::special ins, emp;
{
std::vector<X> v;
- v.reserve(3);
+ v.reserve(4);
+ v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
@@ -503,7 +512,8 @@ test11()
}
{
std::vector<X> v;
- v.reserve(3);
+ v.reserve(4);
+ v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
@@ -523,11 +533,12 @@ test11()
void
test12()
{
- const X::special expected{ 1, 4, 0, 0, 4, 0 };
+ const X::special expected{ 1, 5, 0, 0, 5, 0 };
X::special ins, emp;
{
std::vector<X> v;
- v.reserve(3);
+ v.reserve(4);
+ v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
@@ -540,7 +551,8 @@ test12()
}
{
std::vector<X> v;
- v.reserve(3);
+ v.reserve(4);
+ v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
v.push_back(X(0,0));
--
2.54.0