Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 allocate_at_least(n).ptr; }
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;
Expand All @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 allocate_at_least(n).ptr; }
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;
Expand All @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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 allocate_at_least(n).ptr; }
void deallocate(T* p, std::size_t) noexcept { ::operator delete(static_cast<void*>(p)); }
};

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{
Expand Down
52 changes: 52 additions & 0 deletions libcxx/test/support/increasing_allocator.h
Original file line number Diff line number Diff line change
@@ -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 <cstddef>
#include <memory>

#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<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;
std::size_t min_elements = 1000;
increasing_allocator() = default;

template <typename U>
TEST_CONSTEXPR_CXX20 increasing_allocator(const increasing_allocator<U>& other) TEST_NOEXCEPT
: min_elements(other.min_elements) {}

#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);
}
#endif // TEST_STD_VER >= 23

TEST_CONSTEXPR_CXX20 T* allocate(std::size_t n) { return std::allocator<T>().allocate(n); }

TEST_CONSTEXPR_CXX20 void deallocate(T* p, std::size_t n) TEST_NOEXCEPT { std::allocator<T>().deallocate(p, n); }
};

template <typename T, typename U>
TEST_CONSTEXPR_CXX20 bool operator==(increasing_allocator<T>, increasing_allocator<U>) TEST_NOEXCEPT {
return true;
}

#endif // TEST_SUPPORT_INCREASING_ALLOCATOR_H
Loading