Skip to content

Commit f1bfc5b

Browse files
committed
[libc++] Don't use std::allocator inside <any>
1 parent 1ab4113 commit f1bfc5b

File tree

3 files changed

+53
-109
lines changed

3 files changed

+53
-109
lines changed

libcxx/include/any

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,8 @@ namespace std {
8484
# include <__cxx03/__config>
8585
#else
8686
# include <__config>
87-
# include <__memory/allocator.h>
88-
# include <__memory/allocator_destructor.h>
89-
# include <__memory/allocator_traits.h>
90-
# include <__memory/unique_ptr.h>
87+
# include <__memory/construct_at.h>
88+
# include <__new/allocate.h>
9189
# include <__type_traits/add_cv_quals.h>
9290
# include <__type_traits/add_pointer.h>
9391
# include <__type_traits/aligned_storage.h>
@@ -103,6 +101,7 @@ namespace std {
103101
# include <__type_traits/remove_cv.h>
104102
# include <__type_traits/remove_cvref.h>
105103
# include <__type_traits/remove_reference.h>
104+
# include <__utility/exception_guard.h>
106105
# include <__utility/forward.h>
107106
# include <__utility/in_place.h>
108107
# include <__utility/move.h>
@@ -339,22 +338,14 @@ struct _SmallHandler {
339338

340339
template <class... _Args>
341340
_LIBCPP_HIDE_FROM_ABI static _Tp& __create(any& __dest, _Args&&... __args) {
342-
typedef allocator<_Tp> _Alloc;
343-
typedef allocator_traits<_Alloc> _ATraits;
344-
_Alloc __a;
345-
_Tp* __ret = static_cast<_Tp*>(static_cast<void*>(&__dest.__s_.__buf));
346-
_ATraits::construct(__a, __ret, std::forward<_Args>(__args)...);
341+
auto __ret = std::__construct_at(reinterpret_cast<_Tp*>(&__dest.__s_.__buf), std::forward<_Args>(__args)...);
347342
__dest.__h_ = &_SmallHandler::__handle;
348343
return *__ret;
349344
}
350345

351346
private:
352347
_LIBCPP_HIDE_FROM_ABI static void __destroy(any& __this) {
353-
typedef allocator<_Tp> _Alloc;
354-
typedef allocator_traits<_Alloc> _ATraits;
355-
_Alloc __a;
356-
_Tp* __p = static_cast<_Tp*>(static_cast<void*>(&__this.__s_.__buf));
357-
_ATraits::destroy(__a, __p);
348+
std::__destroy_at(reinterpret_cast<_Tp*>(&__this.__s_.__buf));
358349
__this.__h_ = nullptr;
359350
}
360351

@@ -406,26 +397,20 @@ struct _LargeHandler {
406397

407398
template <class... _Args>
408399
_LIBCPP_HIDE_FROM_ABI static _Tp& __create(any& __dest, _Args&&... __args) {
409-
typedef allocator<_Tp> _Alloc;
410-
typedef allocator_traits<_Alloc> _ATraits;
411-
typedef __allocator_destructor<_Alloc> _Dp;
412-
_Alloc __a;
413-
unique_ptr<_Tp, _Dp> __hold(_ATraits::allocate(__a, 1), _Dp(__a, 1));
414-
_Tp* __ret = __hold.get();
415-
_ATraits::construct(__a, __ret, std::forward<_Args>(__args)...);
416-
__dest.__s_.__ptr = __hold.release();
400+
_Tp* __ptr = static_cast<_Tp*>(std::__libcpp_allocate<_Tp>(__element_count(1)));
401+
std::__exception_guard __guard([&] { std::__libcpp_deallocate<_Tp>(__ptr, __element_count(1)); });
402+
std::__construct_at(__ptr, std::forward<_Args>(__args)...);
403+
__guard.__complete();
404+
__dest.__s_.__ptr = __ptr;
417405
__dest.__h_ = &_LargeHandler::__handle;
418-
return *__ret;
406+
return *__ptr;
419407
}
420408

421409
private:
422410
_LIBCPP_HIDE_FROM_ABI static void __destroy(any& __this) {
423-
typedef allocator<_Tp> _Alloc;
424-
typedef allocator_traits<_Alloc> _ATraits;
425-
_Alloc __a;
426411
_Tp* __p = static_cast<_Tp*>(__this.__s_.__ptr);
427-
_ATraits::destroy(__a, __p);
428-
_ATraits::deallocate(__a, __p, 1);
412+
std::__destroy_at(__p);
413+
std::__libcpp_deallocate<_Tp>(__p, __element_count(1));
429414
__this.__h_ = nullptr;
430415
}
431416

@@ -613,6 +598,11 @@ _LIBCPP_POP_MACROS
613598
# include <type_traits>
614599
# include <variant>
615600
# endif
601+
602+
# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) & _LIBCPP_STD_VER <= 23
603+
# include <cstring>
604+
# include <limits>
605+
# endif
616606
#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
617607

618608
#endif // _LIBCPP_ANY

libcxx/test/libcxx/transitive_includes/cxx26.csv

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ algorithm ratio
1414
algorithm tuple
1515
algorithm version
1616
any cstdint
17-
any cstring
1817
any initializer_list
19-
any limits
2018
any typeinfo
2119
any version
2220
array cctype

libcxx/test/libcxx/utilities/any/allocator.pass.cpp

Lines changed: 35 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -17,111 +17,67 @@
1717
#include <any>
1818
#include <cassert>
1919
#include <cstddef>
20-
#include <memory>
2120
#include <new>
22-
#include <type_traits>
23-
#include <utility>
2421

25-
#include "test_macros.h"
22+
// Make sure we don't fit in std::any's SBO
23+
int allocated_count = 0;
24+
int constructed_count = 0;
2625

26+
struct Large {
27+
Large() { ++constructed_count; }
2728

28-
// Make sure we don't fit in std::any's SBO
29-
struct Large { char big[sizeof(std::any) + 1]; };
29+
Large(const Large&) { ++constructed_count; }
3030

31-
// Make sure we fit in std::any's SBO
32-
struct Small { };
33-
34-
bool Large_was_allocated = false;
35-
bool Large_was_constructed = false;
36-
bool Large_was_destroyed = false;
37-
bool Large_was_deallocated = false;
38-
39-
bool Small_was_constructed = false;
40-
bool Small_was_destroyed = false;
41-
42-
template <>
43-
struct std::allocator<Large> {
44-
using value_type = Large;
45-
using size_type = std::size_t;
46-
using difference_type = std::ptrdiff_t;
47-
using propagate_on_container_move_assignment = std::true_type;
48-
using is_always_equal = std::true_type;
49-
50-
Large* allocate(std::size_t n) {
51-
Large_was_allocated = true;
52-
return static_cast<Large*>(::operator new(n * sizeof(Large)));
53-
}
31+
~Large() { --constructed_count; }
5432

55-
template <typename... Args>
56-
void construct(Large* p, Args&&... args) {
57-
new (p) Large(std::forward<Args>(args)...);
58-
Large_was_constructed = true;
59-
}
33+
char big[sizeof(std::any) + 1];
6034

61-
void destroy(Large* p) {
62-
p->~Large();
63-
Large_was_destroyed = true;
35+
static void* operator new(size_t n) {
36+
++allocated_count;
37+
return ::operator new(n);
6438
}
6539

66-
void deallocate(Large* p, std::size_t) {
67-
Large_was_deallocated = true;
68-
return ::operator delete(p);
40+
static void operator delete(void* ptr) {
41+
--allocated_count;
42+
::operator delete(ptr);
6943
}
7044
};
7145

72-
template <>
73-
struct std::allocator<Small> {
74-
using value_type = Small;
75-
using size_type = std::size_t;
76-
using difference_type = std::ptrdiff_t;
77-
using propagate_on_container_move_assignment = std::true_type;
78-
using is_always_equal = std::true_type;
79-
80-
Small* allocate(std::size_t) {
81-
assert(false);
82-
return nullptr;
83-
}
46+
// Make sure we fit in std::any's SBO
47+
struct Small {
48+
Small() { ++constructed_count; }
8449

85-
template <typename... Args>
86-
void construct(Small* p, Args&&... args) {
87-
new (p) Small(std::forward<Args>(args)...);
88-
Small_was_constructed = true;
89-
}
50+
Small(const Small&) { ++constructed_count; }
51+
52+
~Small() { --constructed_count; }
9053

91-
void destroy(Small* p) {
92-
p->~Small();
93-
Small_was_destroyed = true;
54+
static void* operator new(size_t n) {
55+
++allocated_count;
56+
return ::operator new(n);
9457
}
9558

96-
void deallocate(Small*, std::size_t) { assert(false); }
59+
static void operator delete(void* ptr) {
60+
--allocated_count;
61+
::operator delete(ptr);
62+
}
9763
};
9864

9965
int main(int, char**) {
10066
// Test large types
10167
{
102-
{
103-
std::any a = Large();
104-
(void)a;
105-
106-
assert(Large_was_allocated);
107-
assert(Large_was_constructed);
108-
}
109-
110-
assert(Large_was_destroyed);
111-
assert(Large_was_deallocated);
68+
[[maybe_unused]] std::any a = Large();
69+
assert(constructed_count == 1);
11270
}
71+
assert(allocated_count == 0);
72+
assert(constructed_count == 0);
11373

11474
// Test small types
11575
{
116-
{
117-
std::any a = Small();
118-
(void)a;
119-
120-
assert(Small_was_constructed);
121-
}
122-
123-
assert(Small_was_destroyed);
76+
[[maybe_unused]] std::any a = Small();
77+
assert(constructed_count == 1);
12478
}
79+
assert(allocated_count == 0);
80+
assert(constructed_count == 0);
12581

12682
return 0;
12783
}

0 commit comments

Comments
 (0)