[libcxx-commits] [libcxx] [libc++][test] Fix increasing_allocator to meet `Cpp17Allocator` requirements (PR #115671)

Peng Liu via libcxx-commits libcxx-commits at lists.llvm.org
Sun Nov 10 14:25:14 PST 2024


https://github.com/winner245 created https://github.com/llvm/llvm-project/pull/115671

The `increasing_allocator<T>` class, originally introduced to test `shrink_to_fit` for `vector` and `string` (#95161), does not satisfy `Cpp17Allocator` requirements because its `allocate(n)` member function may allocate more memory than requested. However, the standard ([[allocator.requirements]/36](https://eel.is/c++draft/allocator.requirements#general-36)) mandates that `a.allocate(n)` must allocate memory for an array of exactly `n` objects of type `T`. 

> a.allocate(n)
[35](https://eel.is/c++draft/allocator.requirements#general-35) Result: XX​::​pointer
[36](https://eel.is/c++draft/allocator.requirements#general-36) Effects: Memory is allocated for an array of n T and such an object is created but array elements are not constructed[.](https://eel.is/c++draft/allocator.requirements#general-36.sentence-1)
[Example [1](https://eel.is/c++draft/allocator.requirements#general-example-1): When reusing storage denoted by some pointer value p, launder(reinterpret_cast<T*>(new (p) byte[n * sizeof(T)])) can be used to implicitly create a suitable array object and obtain a pointer to it[.](https://eel.is/c++draft/allocator.requirements#general-36.sentence-2) — end example]

This PR addresses the issue by modifying `increasing_allocator<T>::allocate(n)` such that it strictly allocates for exatcly `n` objects. Note that this change does not affect the existing tests for `shrink_to_fit`, as those tests only utilize the `allocate_at_least` member function, which is already standard conforming.

>From 4044fbee867f739ad28f705bbcae01259e704381 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Sun, 10 Nov 2024 17:13:54 -0500
Subject: [PATCH] Fix increasing_allocator to conform to standard

---
 .../containers/sequences/vector.bool/shrink_to_fit.pass.cpp   | 2 +-
 .../sequences/vector/vector.capacity/shrink_to_fit.pass.cpp   | 2 +-
 .../basic.string/string.capacity/shrink_to_fit.pass.cpp       | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp
index f8bcee31964bbb..136b151efa29ef 100644
--- a/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp
@@ -55,7 +55,7 @@ struct increasing_allocator {
     min_elements += 1000;
     return std::allocator<T>{}.allocate_at_least(n);
   }
-  constexpr T* allocate(std::size_t n) { return allocate_at_least(n).ptr; }
+  constexpr T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }
   constexpr void deallocate(T* p, std::size_t n) noexcept { std::allocator<T>{}.deallocate(p, n); }
 };
 
diff --git a/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp
index e39afb2d48f0a0..97d67dac2baa8c 100644
--- a/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp
@@ -87,7 +87,7 @@ struct increasing_allocator {
     min_elements += 1000;
     return std::allocator<T>{}.allocate_at_least(n);
   }
-  constexpr T* allocate(std::size_t n) { return allocate_at_least(n).ptr; }
+  constexpr T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }
   constexpr void deallocate(T* p, std::size_t n) noexcept { std::allocator<T>{}.deallocate(p, n); }
 };
 
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
index 6f5e43d1341f53..68360329308bab 100644
--- a/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
@@ -79,8 +79,8 @@ struct increasing_allocator {
     min_bytes += 1000;
     return {static_cast<T*>(::operator new(allocation_amount)), allocation_amount / sizeof(T)};
   }
-  T* allocate(std::size_t n) { return allocate_at_least(n).ptr; }
-  void deallocate(T* p, std::size_t) noexcept { ::operator delete(static_cast<void*>(p)); }
+  T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }
+  void deallocate(T* p, std::size_t) noexcept { std::allocator<T>{}.deallocate(p, n); }
 };
 
 template <typename T, typename U>



More information about the libcxx-commits mailing list