[libcxx-commits] [libcxx] [libc++][test] Refactor increasing_allocator (PR #115671)
Peng Liu via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Dec 3 04:06:06 PST 2024
https://github.com/winner245 updated https://github.com/llvm/llvm-project/pull/115671
>From 84b13025db74b212d0cd87ab6d24c43999d47752 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 1/3] 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..9f0b5ff7abdfe7 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 n) noexcept { std::allocator<T>{}.deallocate(p, n); }
};
template <typename T, typename U>
>From 79b8761deb1a8b2211489775ff699c1d7c4ac8e7 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Wed, 13 Nov 2024 11:15:10 -0500
Subject: [PATCH 2/3] Factor out increasing_allocator
---
.../vector.bool/shrink_to_fit.pass.cpp | 73 +++-------
.../vector.capacity/shrink_to_fit.pass.cpp | 137 ++++++++----------
.../string.capacity/shrink_to_fit.pass.cpp | 31 +---
libcxx/test/support/increasing_allocator.h | 43 ++++++
4 files changed, 128 insertions(+), 156 deletions(-)
create mode 100644 libcxx/test/support/increasing_allocator.h
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 136b151efa29ef..3bc639d0479f96 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
@@ -11,59 +11,35 @@
// void shrink_to_fit();
-#include <vector>
#include <cassert>
+#include <vector>
-#include "test_macros.h"
+#include "increasing_allocator.h"
#include "min_allocator.h"
+#include "test_macros.h"
-TEST_CONSTEXPR_CXX20 bool tests()
-{
- {
- std::vector<bool> v(100);
- v.push_back(1);
- v.shrink_to_fit();
- assert(v.capacity() >= 101);
- assert(v.size() >= 101);
- }
+TEST_CONSTEXPR_CXX20 bool tests() {
+ {
+ std::vector<bool> v(100);
+ v.push_back(1);
+ v.shrink_to_fit();
+ assert(v.capacity() >= 101);
+ assert(v.size() >= 101);
+ }
#if TEST_STD_VER >= 11
- {
- std::vector<bool, min_allocator<bool>> v(100);
- v.push_back(1);
- v.shrink_to_fit();
- assert(v.capacity() >= 101);
- assert(v.size() >= 101);
- }
-#endif
-
- return true;
-}
-
-#if TEST_STD_VER >= 23
-template <typename T>
-struct increasing_allocator {
- using value_type = T;
- std::size_t min_elements = 1000;
- increasing_allocator() = default;
-
- template <typename U>
- constexpr increasing_allocator(const increasing_allocator<U>& other) noexcept : min_elements(other.min_elements) {}
-
- constexpr std::allocation_result<T*> allocate_at_least(std::size_t n) {
- if (n < min_elements)
- n = min_elements;
- min_elements += 1000;
- return std::allocator<T>{}.allocate_at_least(n);
+ {
+ std::vector<bool, min_allocator<bool>> v(100);
+ v.push_back(1);
+ v.shrink_to_fit();
+ assert(v.capacity() >= 101);
+ assert(v.size() >= 101);
}
- 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); }
-};
+#endif
-template <typename T, typename U>
-bool operator==(increasing_allocator<T>, increasing_allocator<U>) {
return true;
}
+#if TEST_STD_VER >= 23
// https://github.com/llvm/llvm-project/issues/95161
constexpr bool test_increasing_allocator() {
std::vector<bool, increasing_allocator<bool>> v;
@@ -77,16 +53,15 @@ constexpr bool test_increasing_allocator() {
}
#endif // TEST_STD_VER >= 23
-int main(int, char**)
-{
+int main(int, char**) {
tests();
#if TEST_STD_VER > 17
- static_assert(tests());
+ static_assert(tests());
#endif
#if TEST_STD_VER >= 23
- test_increasing_allocator();
- static_assert(test_increasing_allocator());
+ test_increasing_allocator();
+ static_assert(test_increasing_allocator());
#endif // TEST_STD_VER >= 23
- return 0;
+ return 0;
}
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 97d67dac2baa8c..48eb6ed85d47c6 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
@@ -10,92 +10,70 @@
// void shrink_to_fit();
-#include <vector>
#include <cassert>
-#include "test_macros.h"
-#include "test_allocator.h"
-#include "min_allocator.h"
+#include <vector>
+
#include "asan_testing.h"
+#include "increasing_allocator.h"
+#include "min_allocator.h"
+#include "test_allocator.h"
+#include "test_macros.h"
TEST_CONSTEXPR_CXX20 bool tests() {
- {
- std::vector<int> v(100);
- v.push_back(1);
- assert(is_contiguous_container_asan_correct(v));
- v.shrink_to_fit();
- assert(v.capacity() == 101);
- assert(v.size() == 101);
- assert(is_contiguous_container_asan_correct(v));
- }
- {
- std::vector<int, limited_allocator<int, 401> > v(100);
- v.push_back(1);
- assert(is_contiguous_container_asan_correct(v));
- v.shrink_to_fit();
- assert(v.capacity() == 101);
- assert(v.size() == 101);
- assert(is_contiguous_container_asan_correct(v));
- }
+ {
+ std::vector<int> v(100);
+ v.push_back(1);
+ assert(is_contiguous_container_asan_correct(v));
+ v.shrink_to_fit();
+ assert(v.capacity() == 101);
+ assert(v.size() == 101);
+ assert(is_contiguous_container_asan_correct(v));
+ }
+ {
+ std::vector<int, limited_allocator<int, 401> > v(100);
+ v.push_back(1);
+ assert(is_contiguous_container_asan_correct(v));
+ v.shrink_to_fit();
+ assert(v.capacity() == 101);
+ assert(v.size() == 101);
+ assert(is_contiguous_container_asan_correct(v));
+ }
#ifndef TEST_HAS_NO_EXCEPTIONS
- if (!TEST_IS_CONSTANT_EVALUATED) {
- std::vector<int, limited_allocator<int, 400> > v(100);
- v.push_back(1);
- assert(is_contiguous_container_asan_correct(v));
- v.shrink_to_fit();
- LIBCPP_ASSERT(v.capacity() == 200); // assumes libc++'s 2x growth factor
- assert(v.size() == 101);
- assert(is_contiguous_container_asan_correct(v));
- }
+ if (!TEST_IS_CONSTANT_EVALUATED) {
+ std::vector<int, limited_allocator<int, 400> > v(100);
+ v.push_back(1);
+ assert(is_contiguous_container_asan_correct(v));
+ v.shrink_to_fit();
+ LIBCPP_ASSERT(v.capacity() == 200); // assumes libc++'s 2x growth factor
+ assert(v.size() == 101);
+ assert(is_contiguous_container_asan_correct(v));
+ }
#endif
#if TEST_STD_VER >= 11
- {
- std::vector<int, min_allocator<int>> v(100);
- v.push_back(1);
- assert(is_contiguous_container_asan_correct(v));
- v.shrink_to_fit();
- assert(v.capacity() == 101);
- assert(v.size() == 101);
- assert(is_contiguous_container_asan_correct(v));
- }
- {
- std::vector<int, safe_allocator<int>> v(100);
- v.push_back(1);
- assert(is_contiguous_container_asan_correct(v));
- v.shrink_to_fit();
- assert(v.capacity() == 101);
- assert(v.size() == 101);
- assert(is_contiguous_container_asan_correct(v));
- }
-#endif
-
- return true;
-}
-
-#if TEST_STD_VER >= 23
-template <typename T>
-struct increasing_allocator {
- using value_type = T;
- std::size_t min_elements = 1000;
- increasing_allocator() = default;
-
- template <typename U>
- constexpr increasing_allocator(const increasing_allocator<U>& other) noexcept : min_elements(other.min_elements) {}
-
- constexpr std::allocation_result<T*> allocate_at_least(std::size_t n) {
- if (n < min_elements)
- n = min_elements;
- min_elements += 1000;
- return std::allocator<T>{}.allocate_at_least(n);
+ {
+ std::vector<int, min_allocator<int>> v(100);
+ v.push_back(1);
+ assert(is_contiguous_container_asan_correct(v));
+ v.shrink_to_fit();
+ assert(v.capacity() == 101);
+ assert(v.size() == 101);
+ assert(is_contiguous_container_asan_correct(v));
+ }
+ {
+ std::vector<int, safe_allocator<int>> v(100);
+ v.push_back(1);
+ assert(is_contiguous_container_asan_correct(v));
+ v.shrink_to_fit();
+ assert(v.capacity() == 101);
+ assert(v.size() == 101);
+ assert(is_contiguous_container_asan_correct(v));
}
- 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); }
-};
+#endif
-template <typename T, typename U>
-bool operator==(increasing_allocator<T>, increasing_allocator<U>) {
return true;
}
+#if TEST_STD_VER >= 23
// https://github.com/llvm/llvm-project/issues/95161
constexpr bool test_increasing_allocator() {
std::vector<int, increasing_allocator<int>> v;
@@ -111,16 +89,15 @@ constexpr bool test_increasing_allocator() {
}
#endif // TEST_STD_VER >= 23
-int main(int, char**)
-{
+int main(int, char**) {
tests();
#if TEST_STD_VER > 17
- static_assert(tests());
+ static_assert(tests());
#endif
#if TEST_STD_VER >= 23
- test_increasing_allocator();
- static_assert(test_increasing_allocator());
+ test_increasing_allocator();
+ static_assert(test_increasing_allocator());
#endif
- return 0;
+ return 0;
}
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 9f0b5ff7abdfe7..2d901e7afe2b67 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
@@ -10,12 +10,13 @@
// void shrink_to_fit(); // constexpr since C++20
-#include <string>
#include <cassert>
+#include <string>
-#include "test_macros.h"
-#include "min_allocator.h"
#include "asan_testing.h"
+#include "increasing_allocator.h"
+#include "min_allocator.h"
+#include "test_macros.h"
template <class S>
TEST_CONSTEXPR_CXX20 void test(S s) {
@@ -64,30 +65,6 @@ TEST_CONSTEXPR_CXX20 bool test() {
}
#if TEST_STD_VER >= 23
-std::size_t min_bytes = 1000;
-
-template <typename T>
-struct increasing_allocator {
- using value_type = T;
- increasing_allocator() = default;
- template <typename U>
- increasing_allocator(const increasing_allocator<U>&) noexcept {}
- std::allocation_result<T*> allocate_at_least(std::size_t n) {
- std::size_t allocation_amount = n * sizeof(T);
- if (allocation_amount < min_bytes)
- allocation_amount = min_bytes;
- min_bytes += 1000;
- return {static_cast<T*>(::operator new(allocation_amount)), allocation_amount / sizeof(T)};
- }
- T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }
- void deallocate(T* p, std::size_t n) noexcept { std::allocator<T>{}.deallocate(p, n); }
-};
-
-template <typename T, typename U>
-bool operator==(increasing_allocator<T>, increasing_allocator<U>) {
- return true;
-}
-
// https://github.com/llvm/llvm-project/issues/95161
void test_increasing_allocator() {
std::basic_string<char, std::char_traits<char>, increasing_allocator<char>> s{
diff --git a/libcxx/test/support/increasing_allocator.h b/libcxx/test/support/increasing_allocator.h
new file mode 100644
index 00000000000000..4fef6d35849909
--- /dev/null
+++ b/libcxx/test/support/increasing_allocator.h
@@ -0,0 +1,43 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef INCREASING_ALLOCATOR_H
+#define INCREASING_ALLOCATOR_H
+
+#include <cstddef>
+#include <memory>
+
+#include "test_macros.h"
+
+#if TEST_STD_VER >= 23
+template <typename T>
+struct increasing_allocator {
+ using value_type = T;
+ std::size_t min_elements = 1000;
+ increasing_allocator() = default;
+
+ template <typename U>
+ constexpr increasing_allocator(const increasing_allocator<U>& other) noexcept : min_elements(other.min_elements) {}
+
+ constexpr std::allocation_result<T*> allocate_at_least(std::size_t n) {
+ if (n < min_elements)
+ n = min_elements;
+ min_elements += 1000;
+ return std::allocator<T>{}.allocate_at_least(n);
+ }
+ 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); }
+};
+
+template <typename T, typename U>
+bool operator==(increasing_allocator<T>, increasing_allocator<U>) {
+ return true;
+}
+#endif // TEST_STD_VER >= 23
+
+#endif // INCREASING_ALLOCATOR_H
\ No newline at end of file
>From bdd094f020e7e2d88bb449de00d9d7614cf7c9be Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Fri, 29 Nov 2024 08:55:36 -0500
Subject: [PATCH 3/3] Add comment for increasing_allocator
---
libcxx/test/support/increasing_allocator.h | 38 ++++++++++++++++------
1 file changed, 28 insertions(+), 10 deletions(-)
diff --git a/libcxx/test/support/increasing_allocator.h b/libcxx/test/support/increasing_allocator.h
index 4fef6d35849909..2536e50db61782 100644
--- a/libcxx/test/support/increasing_allocator.h
+++ b/libcxx/test/support/increasing_allocator.h
@@ -6,15 +6,20 @@
//
//===----------------------------------------------------------------------===//
-#ifndef INCREASING_ALLOCATOR_H
-#define INCREASING_ALLOCATOR_H
+#ifndef TEST_SUPPORT_INCREASING_ALLOCATOR_H
+#define TEST_SUPPORT_INCREASING_ALLOCATOR_H
#include <cstddef>
#include <memory>
#include "test_macros.h"
-#if TEST_STD_VER >= 23
+// The increasing_allocator is a custom allocator that enforces an increasing minimum allocation size,
+// ensuring that it allocates an increasing amount of memory, possibly exceeding the requested amount.
+// This unique behavior is particularly useful for testing the shrink_to_fit functionality in std::vector,
+// vector<bool>, and std::basic_string, ensuring that shrink_to_fit does not increase the capacity of
+// the allocated memory.
+
template <typename T>
struct increasing_allocator {
using value_type = T;
@@ -22,22 +27,35 @@ struct increasing_allocator {
increasing_allocator() = default;
template <typename U>
- constexpr increasing_allocator(const increasing_allocator<U>& other) noexcept : min_elements(other.min_elements) {}
+ TEST_CONSTEXPR_CXX20 increasing_allocator(const increasing_allocator<U>& other) TEST_NOEXCEPT
+ : min_elements(other.min_elements) {}
- constexpr std::allocation_result<T*> allocate_at_least(std::size_t n) {
+#if TEST_STD_VER >= 23
+ TEST_CONSTEXPR_CXX23 std::allocation_result<T*> allocate_at_least(std::size_t n) {
if (n < min_elements)
n = min_elements;
min_elements += 1000;
return std::allocator<T>{}.allocate_at_least(n);
}
- 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); }
+#endif // TEST_STD_VER >= 23
+
+ TEST_CONSTEXPR_CXX20 T* allocate(std::size_t n) {
+#if TEST_STD_VER >= 23
+ return allocate_at_least(n).ptr;
+#else
+ if (n < min_elements)
+ n = min_elements;
+ min_elements += 1000;
+ return std::allocator<T>().allocate(n);
+#endif
+ }
+
+ TEST_CONSTEXPR_CXX20 void deallocate(T* p, std::size_t n) TEST_NOEXCEPT { std::allocator<T>().deallocate(p, n); }
};
template <typename T, typename U>
-bool operator==(increasing_allocator<T>, increasing_allocator<U>) {
+TEST_CONSTEXPR_CXX20 bool operator==(increasing_allocator<T>, increasing_allocator<U>) TEST_NOEXCEPT {
return true;
}
-#endif // TEST_STD_VER >= 23
-#endif // INCREASING_ALLOCATOR_H
\ No newline at end of file
+#endif // TEST_SUPPORT_INCREASING_ALLOCATOR_H
More information about the libcxx-commits
mailing list