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 f8bcee31964bb..3bc639d0479f9 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 #include +#include -#include "test_macros.h" +#include "increasing_allocator.h" #include "min_allocator.h" +#include "test_macros.h" -TEST_CONSTEXPR_CXX20 bool tests() -{ - { - std::vector 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 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> 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 -struct increasing_allocator { - using value_type = T; - std::size_t min_elements = 1000; - increasing_allocator() = default; - - template - constexpr increasing_allocator(const increasing_allocator& other) noexcept : min_elements(other.min_elements) {} - - constexpr std::allocation_result allocate_at_least(std::size_t n) { - if (n < min_elements) - n = min_elements; - min_elements += 1000; - return std::allocator{}.allocate_at_least(n); + { + std::vector> 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 allocate_at_least(n).ptr; } - constexpr void deallocate(T* p, std::size_t n) noexcept { std::allocator{}.deallocate(p, n); } -}; +#endif -template -bool operator==(increasing_allocator, increasing_allocator) { return true; } +#if TEST_STD_VER >= 23 // https://github.com/llvm/llvm-project/issues/95161 constexpr bool test_increasing_allocator() { std::vector> 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 e39afb2d48f0a..48eb6ed85d47c 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 #include -#include "test_macros.h" -#include "test_allocator.h" -#include "min_allocator.h" +#include + #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 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 > 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 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 > 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 > 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 > 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> 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> 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 -struct increasing_allocator { - using value_type = T; - std::size_t min_elements = 1000; - increasing_allocator() = default; - - template - constexpr increasing_allocator(const increasing_allocator& other) noexcept : min_elements(other.min_elements) {} - - constexpr std::allocation_result allocate_at_least(std::size_t n) { - if (n < min_elements) - n = min_elements; - min_elements += 1000; - return std::allocator{}.allocate_at_least(n); + { + std::vector> 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> 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 allocate_at_least(n).ptr; } - constexpr void deallocate(T* p, std::size_t n) noexcept { std::allocator{}.deallocate(p, n); } -}; +#endif -template -bool operator==(increasing_allocator, increasing_allocator) { return true; } +#if TEST_STD_VER >= 23 // https://github.com/llvm/llvm-project/issues/95161 constexpr bool test_increasing_allocator() { std::vector> 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 6f5e43d1341f5..2d901e7afe2b6 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 #include +#include -#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 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 -struct increasing_allocator { - using value_type = T; - increasing_allocator() = default; - template - increasing_allocator(const increasing_allocator&) noexcept {} - std::allocation_result 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(::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(p)); } -}; - -template -bool operator==(increasing_allocator, increasing_allocator) { - return true; -} - // https://github.com/llvm/llvm-project/issues/95161 void test_increasing_allocator() { std::basic_string, increasing_allocator> s{ diff --git a/libcxx/test/support/increasing_allocator.h b/libcxx/test/support/increasing_allocator.h new file mode 100644 index 0000000000000..30bd6f40c8dad --- /dev/null +++ b/libcxx/test/support/increasing_allocator.h @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// 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 TEST_SUPPORT_INCREASING_ALLOCATOR_H +#define TEST_SUPPORT_INCREASING_ALLOCATOR_H + +#include +#include + +#include "test_macros.h" + +// 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, and std::basic_string, ensuring that shrink_to_fit does not increase the capacity of +// the allocated memory. + +template +struct increasing_allocator { + using value_type = T; + std::size_t min_elements = 1000; + increasing_allocator() = default; + + template + TEST_CONSTEXPR_CXX20 increasing_allocator(const increasing_allocator& other) TEST_NOEXCEPT + : min_elements(other.min_elements) {} + +#if TEST_STD_VER >= 23 + TEST_CONSTEXPR_CXX23 std::allocation_result allocate_at_least(std::size_t n) { + if (n < min_elements) + n = min_elements; + min_elements += 1000; + return std::allocator{}.allocate_at_least(n); + } +#endif // TEST_STD_VER >= 23 + + TEST_CONSTEXPR_CXX20 T* allocate(std::size_t n) { return std::allocator().allocate(n); } + + TEST_CONSTEXPR_CXX20 void deallocate(T* p, std::size_t n) TEST_NOEXCEPT { std::allocator().deallocate(p, n); } +}; + +template +TEST_CONSTEXPR_CXX20 bool operator==(increasing_allocator, increasing_allocator) TEST_NOEXCEPT { + return true; +} + +#endif // TEST_SUPPORT_INCREASING_ALLOCATOR_H