Thanks to visit codestin.com
Credit goes to github.com

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
58 changes: 35 additions & 23 deletions stl/inc/xmemory
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,15 @@ template <class _Ty>
struct _Is_default_allocator<allocator<_Ty>, void_t<typename allocator<_Ty>::_From_primary>>
: is_same<typename allocator<_Ty>::_From_primary, allocator<_Ty>>::type {};

#if _HAS_CXX23
template <class _Alloc, class _SizeTy, class = void>
inline constexpr bool _Has_member_allocate_at_least = false;

template <class _Alloc, class _SizeTy>
inline constexpr bool _Has_member_allocate_at_least<_Alloc, _SizeTy,
void_t<decltype(_STD declval<_Alloc&>().allocate_at_least(_STD declval<const _SizeTy&>()))>> = true;
#endif // _HAS_CXX23

template <class _Void, class... _Types>
struct _Has_no_allocator_construct : true_type {};

Expand Down Expand Up @@ -511,6 +520,14 @@ template <class _Alloc>
struct _Has_select_on_container_copy_construction<_Alloc,
void_t<decltype(_STD declval<const _Alloc&>().select_on_container_copy_construction())>> : true_type {};

#if _HAS_CXX23
_EXPORT_STD template <class _Ptr, class _SizeTy = size_t>
struct allocation_result {
_Ptr ptr;
_SizeTy count;
};
#endif // _HAS_CXX23

_EXPORT_STD template <class _Alloc>
struct allocator_traits;

Expand Down Expand Up @@ -553,6 +570,17 @@ struct _Normal_allocator_traits { // defines traits for allocators
}
}

#if _HAS_CXX23
_NODISCARD_RAW_PTR_ALLOC static constexpr allocation_result<pointer, size_type> allocate_at_least(
_Alloc& _Al, _CRT_GUARDOVERFLOW const size_type _Count) {
if constexpr (_Has_member_allocate_at_least<_Alloc, size_type>) {
return _Al.allocate_at_least(_Count);
} else {
return {_Al.allocate(_Count), _Count};
}
}
#endif // _HAS_CXX23

static _CONSTEXPR20 void deallocate(_Alloc& _Al, pointer _Ptr, size_type _Count) {
_Al.deallocate(_Ptr, _Count);
}
Expand Down Expand Up @@ -653,6 +681,13 @@ struct _Default_allocator_traits { // traits for std::allocator
}
}

#if _HAS_CXX23
_NODISCARD_RAW_PTR_ALLOC static constexpr allocation_result<pointer, size_type> allocate_at_least(
_Alloc& _Al, _CRT_GUARDOVERFLOW const size_type _Count) {
return {_Al.allocate(_Count), _Count};
}
#endif // _HAS_CXX23

static _CONSTEXPR20 void deallocate(_Alloc& _Al, const pointer _Ptr, const size_type _Count) {
// no overflow check on the following multiply; we assume _Allocate did that check
#if _HAS_CXX20 // TRANSITION, GH-1532
Expand Down Expand Up @@ -747,29 +782,6 @@ struct _Simple_types { // wraps types from allocators with simple addressing for
using const_pointer = const value_type*;
};

#if _HAS_CXX23
_EXPORT_STD template <class _Ptr>
struct allocation_result {
_Ptr ptr;
size_t count;
};

#ifdef __cpp_lib_concepts
template <class _Alloc>
concept _Has_member_allocate_at_least = requires(_Alloc _Al, size_t _Count) { _Al.allocate_at_least(_Count); };

_EXPORT_STD template <class _Alloc>
_NODISCARD constexpr allocation_result<typename allocator_traits<_Alloc>::pointer> allocate_at_least(
_Alloc& _Al, const size_t _Count) {
if constexpr (_Has_member_allocate_at_least<_Alloc>) {
return _Al.allocate_at_least(_Count);
} else {
return {_Al.allocate(_Count), _Count};
}
}
#endif // __cpp_lib_concepts
#endif // _HAS_CXX23

// The number of user bytes a single byte of ASAN shadow memory can track.
_INLINE_VAR constexpr size_t _Asan_granularity = 8;
_INLINE_VAR constexpr size_t _Asan_granularity_mask = _Asan_granularity - 1;
Expand Down
1 change: 1 addition & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@
// P2499R0 string_view Range Constructor Should Be explicit
// P2505R5 Monadic Functions For expected
// P2549R1 unexpected<E>::error()
// P2652R2 Disallowing User Specialization Of allocator_traits

// _HAS_CXX23 and _SILENCE_ALL_CXX23_DEPRECATION_WARNINGS control:
// P1413R3 Deprecate aligned_storage And aligned_union
Expand Down
3 changes: 3 additions & 0 deletions tests/libcxx/expected_results.txt
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ std/ranges/range.access/rbegin.pass.cpp FAIL
std/ranges/range.access/rend.pass.cpp FAIL
std/ranges/range.access/size.pass.cpp FAIL

# libc++ doesn't implement P2652R2 "Disallowing User Specialization Of allocator_traits"
std/utilities/memory/allocator.traits/allocate_at_least.pass.cpp FAIL

# libc++ doesn't implement P2770R0 "Stashing stashing iterators for proper flattening"
std/ranges/range.adaptors/range.join.view/end.pass.cpp FAIL
std/ranges/range.adaptors/range.join.view/iterator/ctor.other.pass.cpp FAIL
Expand Down
2 changes: 1 addition & 1 deletion tests/std/tests/P0401R6_allocate_at_least/env.lst
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\concepts_latest_matrix.lst
RUNALL_INCLUDE ..\usual_latest_matrix.lst
78 changes: 76 additions & 2 deletions tests/std/tests/P0401R6_allocate_at_least/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@

#include <algorithm>
#include <cassert>
#ifdef __cpp_lib_concepts // TRANSITION, GH-395
#include <concepts>
#endif // __cpp_lib_concepts
#include <cstdint>
#include <memory>
#include <numeric>
#include <type_traits>
Expand Down Expand Up @@ -45,11 +48,42 @@ struct strict_allocator {
}
};

struct small_allocator {
using value_type = int;
using size_type = uint32_t;

[[nodiscard]] constexpr int* allocate(const size_type count) {
return allocator<int>{}.allocate(count);
}

constexpr void deallocate(int* ptr, const size_type count) {
allocator<int>{}.deallocate(ptr, count);
}
};

struct huge_allocator {
using value_type = int;
using size_type = uint64_t;

[[nodiscard]] constexpr int* allocate(const size_type count) {
return allocator<int>{}.allocate(static_cast<size_t>(count));
}

constexpr void deallocate(int* ptr, const size_type count) {
allocator<int>{}.deallocate(ptr, static_cast<size_t>(count));
}
};

constexpr bool test() {
{
allocator<int> al;

#ifdef __cpp_lib_concepts // TRANSITION, GH-395
same_as<allocation_result<int*>> auto result = al.allocate_at_least(5);
#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv
auto result = al.allocate_at_least(5);
static_assert(is_same_v<decltype(result), allocation_result<int*>>);
#endif // ^^^ !defined(__cpp_lib_concepts) ^^^
assert(result.ptr);
assert(result.count >= 5);
al.deallocate(result.ptr, 5);
Expand All @@ -68,7 +102,12 @@ constexpr bool test() {
{
generous_allocator al;

same_as<allocation_result<int*>> auto result = allocate_at_least(al, 4);
#ifdef __cpp_lib_concepts // TRANSITION, GH-395
same_as<allocation_result<int*>> auto result = allocator_traits<generous_allocator>::allocate_at_least(al, 4);
#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv
auto result = allocator_traits<generous_allocator>::allocate_at_least(al, 4);
static_assert(is_same_v<decltype(result), allocation_result<int*>>);
#endif // ^^^ !defined(__cpp_lib_concepts) ^^^
assert(result.ptr);
assert(result.count == 16);
al.deallocate(result.ptr, result.count);
Expand All @@ -77,7 +116,42 @@ constexpr bool test() {
{
strict_allocator al;

same_as<allocation_result<int*>> auto result = allocate_at_least(al, 4);
#ifdef __cpp_lib_concepts // TRANSITION, GH-395
same_as<allocation_result<int*>> auto result = allocator_traits<strict_allocator>::allocate_at_least(al, 4);
#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv
auto result = allocator_traits<strict_allocator>::allocate_at_least(al, 4);
static_assert(is_same_v<decltype(result), allocation_result<int*>>);
#endif // ^^^ !defined(__cpp_lib_concepts) ^^^
assert(result.ptr);
assert(result.count == 4);
al.deallocate(result.ptr, result.count);
}

{
small_allocator al;

#ifdef __cpp_lib_concepts // TRANSITION, GH-395
same_as<allocation_result<int*, uint32_t>> auto result =
allocator_traits<small_allocator>::allocate_at_least(al, 4);
#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv
auto result = allocator_traits<small_allocator>::allocate_at_least(al, 4);
static_assert(is_same_v<decltype(result), allocation_result<int*, uint32_t>>);
#endif // ^^^ !defined(__cpp_lib_concepts) ^^^
assert(result.ptr);
assert(result.count == 4);
al.deallocate(result.ptr, result.count);
}

{
huge_allocator al;

#ifdef __cpp_lib_concepts // TRANSITION, GH-395
same_as<allocation_result<int*, uint64_t>> auto result =
allocator_traits<huge_allocator>::allocate_at_least(al, 4);
#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv
auto result = allocator_traits<huge_allocator>::allocate_at_least(al, 4);
static_assert(is_same_v<decltype(result), allocation_result<int*, uint64_t>>);
#endif // ^^^ !defined(__cpp_lib_concepts) ^^^
assert(result.ptr);
assert(result.count == 4);
al.deallocate(result.ptr, result.count);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -449,10 +449,9 @@ template class std::basic_osyncstream<char, std::char_traits<char>, fancy_alloca
STATIC_ASSERT(std::is_standard_layout_v<std::allocation_result<fancy_pointer<int>>>);
STATIC_ASSERT(!std::is_trivially_copyable_v<std::allocation_result<fancy_pointer<int>>>);

#ifdef __cpp_lib_concepts
STATIC_ASSERT(std::is_same_v<decltype(std::allocate_at_least(std::declval<fancy_allocator<int>&>(), std::size_t{})),
STATIC_ASSERT(std::is_same_v<decltype(std::allocator_traits<fancy_allocator<int>>::allocate_at_least(
std::declval<fancy_allocator<int>&>(), std::size_t{})),
std::allocation_result<fancy_pointer<int>>>);
#endif // __cpp_lib_concepts
#endif // _HAS_CXX23

void instantiate() {
Expand Down