Skip to content

Commit 78f9a8b

Browse files
[libc++] LWG3870: Remove voidify (#110355)
Instead of changing the cast sequence to implicit conversion in _`voidify`_, I think it is better to totally remove `__voidify` and use `static_cast` to `void*`, which has equivalent effects. Test coverage for const iterators are removed. Now most affected algorithms are underconstrained, for which I submitted [LWG3888](https://cplusplus.github.io/LWG/issue3888). I'm not sure whether we should speculatively implement it at this moment, and thus haven't added any `*.verify.cpp`. In some control block types and `optional`, the stored objects are changed to have cv-unqualified type. Fixes #105119.
1 parent e22b07e commit 78f9a8b

21 files changed

+24
-297
lines changed

libcxx/docs/Status/Cxx23Issues.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@
296296
"`LWG3862 <https://wg21.link/LWG3862>`__","``basic_const_iterator``'s ``common_type`` specialization is underconstrained","2023-02 (Issaquah)","","",""
297297
"`LWG3865 <https://wg21.link/LWG3865>`__","Sorting a range of ``pairs``","2023-02 (Issaquah)","|Complete|","17.0",""
298298
"`LWG3869 <https://wg21.link/LWG3869>`__","Deprecate ``std::errc`` constants related to UNIX STREAMS","2023-02 (Issaquah)","|Complete|","19.0",""
299-
"`LWG3870 <https://wg21.link/LWG3870>`__","Remove ``voidify``","2023-02 (Issaquah)","","",""
299+
"`LWG3870 <https://wg21.link/LWG3870>`__","Remove ``voidify``","2023-02 (Issaquah)","|Complete|","20.0",""
300300
"`LWG3871 <https://wg21.link/LWG3871>`__","Adjust note about ``terminate``","2023-02 (Issaquah)","","",""
301301
"`LWG3872 <https://wg21.link/LWG3872>`__","``basic_const_iterator`` should have custom ``iter_move``","2023-02 (Issaquah)","","",""
302302
"`LWG3875 <https://wg21.link/LWG3875>`__","``std::ranges::repeat_view<T, IntegerClass>::iterator`` may be ill-formed","2023-02 (Issaquah)","|Complete|","17.0",""

libcxx/include/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,6 @@ set(files
560560
__memory/unique_temporary_buffer.h
561561
__memory/uses_allocator.h
562562
__memory/uses_allocator_construction.h
563-
__memory/voidify.h
564563
__memory_resource/memory_resource.h
565564
__memory_resource/monotonic_buffer_resource.h
566565
__memory_resource/polymorphic_allocator.h

libcxx/include/__memory/construct_at.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include <__config>
1515
#include <__iterator/access.h>
1616
#include <__memory/addressof.h>
17-
#include <__memory/voidify.h>
1817
#include <__type_traits/enable_if.h>
1918
#include <__type_traits/is_array.h>
2019
#include <__utility/declval.h>
@@ -38,7 +37,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
3837
template <class _Tp, class... _Args, class = decltype(::new(std::declval<void*>()) _Tp(std::declval<_Args>()...))>
3938
_LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* __location, _Args&&... __args) {
4039
_LIBCPP_ASSERT_NON_NULL(__location != nullptr, "null pointer given to construct_at");
41-
return ::new (std::__voidify(*__location)) _Tp(std::forward<_Args>(__args)...);
40+
return ::new (static_cast<void*>(__location)) _Tp(std::forward<_Args>(__args)...);
4241
}
4342

4443
#endif
@@ -49,7 +48,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp* __construct_at(_Tp* __l
4948
return std::construct_at(__location, std::forward<_Args>(__args)...);
5049
#else
5150
return _LIBCPP_ASSERT_NON_NULL(__location != nullptr, "null pointer given to construct_at"),
52-
::new (std::__voidify(*__location)) _Tp(std::forward<_Args>(__args)...);
51+
::new (static_cast<void*>(__location)) _Tp(std::forward<_Args>(__args)...);
5352
#endif
5453
}
5554

libcxx/include/__memory/shared_ptr.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -248,33 +248,35 @@ struct __for_overwrite_tag {};
248248

249249
template <class _Tp, class _Alloc>
250250
struct __shared_ptr_emplace : __shared_weak_count {
251+
using __value_type = __remove_cv_t<_Tp>;
252+
251253
template <class... _Args,
252254
class _Allocator = _Alloc,
253255
__enable_if_t<is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0>
254256
_LIBCPP_HIDE_FROM_ABI explicit __shared_ptr_emplace(_Alloc __a, _Args&&...) : __storage_(std::move(__a)) {
255257
static_assert(
256258
sizeof...(_Args) == 0, "No argument should be provided to the control block when using _for_overwrite");
257-
::new ((void*)__get_elem()) _Tp;
259+
::new (static_cast<void*>(__get_elem())) __value_type;
258260
}
259261

260262
template <class... _Args,
261263
class _Allocator = _Alloc,
262264
__enable_if_t<!is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0>
263265
_LIBCPP_HIDE_FROM_ABI explicit __shared_ptr_emplace(_Alloc __a, _Args&&... __args) : __storage_(std::move(__a)) {
264-
using _TpAlloc = typename __allocator_traits_rebind<_Alloc, __remove_cv_t<_Tp> >::type;
266+
using _TpAlloc = typename __allocator_traits_rebind<_Alloc, __value_type>::type;
265267
_TpAlloc __tmp(*__get_alloc());
266268
allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), std::forward<_Args>(__args)...);
267269
}
268270

269271
_LIBCPP_HIDE_FROM_ABI _Alloc* __get_alloc() _NOEXCEPT { return __storage_.__get_alloc(); }
270272

271-
_LIBCPP_HIDE_FROM_ABI _Tp* __get_elem() _NOEXCEPT { return __storage_.__get_elem(); }
273+
_LIBCPP_HIDE_FROM_ABI __value_type* __get_elem() _NOEXCEPT { return __storage_.__get_elem(); }
272274

273275
private:
274276
template <class _Allocator = _Alloc,
275277
__enable_if_t<is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0>
276278
_LIBCPP_HIDE_FROM_ABI void __on_zero_shared_impl() _NOEXCEPT {
277-
__get_elem()->~_Tp();
279+
__get_elem()->~__value_type();
278280
}
279281

280282
template <class _Allocator = _Alloc,
@@ -300,7 +302,7 @@ struct __shared_ptr_emplace : __shared_weak_count {
300302
// through `std::allocate_shared` and `std::make_shared`.
301303
struct _Storage {
302304
struct _Data {
303-
_LIBCPP_COMPRESSED_PAIR(_Alloc, __alloc_, _Tp, __elem_);
305+
_LIBCPP_COMPRESSED_PAIR(_Alloc, __alloc_, __value_type, __elem_);
304306
};
305307

306308
_ALIGNAS_TYPE(_Data) char __buffer_[sizeof(_Data)];
@@ -312,7 +314,7 @@ struct __shared_ptr_emplace : __shared_weak_count {
312314
return std::addressof(reinterpret_cast<_Data*>(__buffer_)->__alloc_);
313315
}
314316

315-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _Tp* __get_elem() _NOEXCEPT {
317+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI __value_type* __get_elem() _NOEXCEPT {
316318
return std::addressof(reinterpret_cast<_Data*>(__buffer_)->__elem_);
317319
}
318320
};

libcxx/include/__memory/uninitialized_algorithms.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#include <__memory/allocator_traits.h>
2222
#include <__memory/construct_at.h>
2323
#include <__memory/pointer_traits.h>
24-
#include <__memory/voidify.h>
2524
#include <__type_traits/enable_if.h>
2625
#include <__type_traits/extent.h>
2726
#include <__type_traits/is_array.h>
@@ -64,7 +63,7 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitiali
6463
try {
6564
#endif
6665
for (; __ifirst != __ilast && !__stop_copying(__idx); ++__ifirst, (void)++__idx)
67-
::new (std::__voidify(*__idx)) _ValueType(*__ifirst);
66+
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(*__ifirst);
6867
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
6968
} catch (...) {
7069
std::__destroy(__ofirst, __idx);
@@ -94,7 +93,7 @@ __uninitialized_copy_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __of
9493
try {
9594
#endif
9695
for (; __n > 0 && !__stop_copying(__idx); ++__ifirst, (void)++__idx, (void)--__n)
97-
::new (std::__voidify(*__idx)) _ValueType(*__ifirst);
96+
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(*__ifirst);
9897
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
9998
} catch (...) {
10099
std::__destroy(__ofirst, __idx);
@@ -124,7 +123,7 @@ __uninitialized_fill(_ForwardIterator __first, _Sentinel __last, const _Tp& __x)
124123
try {
125124
#endif
126125
for (; __idx != __last; ++__idx)
127-
::new (std::__voidify(*__idx)) _ValueType(__x);
126+
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(__x);
128127
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
129128
} catch (...) {
130129
std::__destroy(__first, __idx);
@@ -152,7 +151,7 @@ __uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) {
152151
try {
153152
#endif
154153
for (; __n > 0; ++__idx, (void)--__n)
155-
::new (std::__voidify(*__idx)) _ValueType(__x);
154+
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(__x);
156155
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
157156
} catch (...) {
158157
std::__destroy(__first, __idx);
@@ -182,7 +181,7 @@ __uninitialized_default_construct(_ForwardIterator __first, _Sentinel __last) {
182181
try {
183182
# endif
184183
for (; __idx != __last; ++__idx)
185-
::new (std::__voidify(*__idx)) _ValueType;
184+
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType;
186185
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
187186
} catch (...) {
188187
std::__destroy(__first, __idx);
@@ -208,7 +207,7 @@ inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_default_construct_
208207
try {
209208
# endif
210209
for (; __n > 0; ++__idx, (void)--__n)
211-
::new (std::__voidify(*__idx)) _ValueType;
210+
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType;
212211
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
213212
} catch (...) {
214213
std::__destroy(__first, __idx);
@@ -235,7 +234,7 @@ __uninitialized_value_construct(_ForwardIterator __first, _Sentinel __last) {
235234
try {
236235
# endif
237236
for (; __idx != __last; ++__idx)
238-
::new (std::__voidify(*__idx)) _ValueType();
237+
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType();
239238
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
240239
} catch (...) {
241240
std::__destroy(__first, __idx);
@@ -261,7 +260,7 @@ inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_value_construct_n(
261260
try {
262261
# endif
263262
for (; __n > 0; ++__idx, (void)--__n)
264-
::new (std::__voidify(*__idx)) _ValueType();
263+
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType();
265264
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
266265
} catch (...) {
267266
std::__destroy(__first, __idx);
@@ -297,7 +296,7 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitiali
297296
try {
298297
# endif
299298
for (; __ifirst != __ilast && !__stop_moving(__idx); ++__idx, (void)++__ifirst) {
300-
::new (std::__voidify(*__idx)) _ValueType(__iter_move(__ifirst));
299+
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(__iter_move(__ifirst));
301300
}
302301
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
303302
} catch (...) {
@@ -335,7 +334,7 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitiali
335334
try {
336335
# endif
337336
for (; __n > 0 && !__stop_moving(__idx); ++__idx, (void)++__ifirst, --__n)
338-
::new (std::__voidify(*__idx)) _ValueType(__iter_move(__ifirst));
337+
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(__iter_move(__ifirst));
339338
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
340339
} catch (...) {
341340
std::__destroy(__ofirst, __idx);

libcxx/include/__memory/voidify.h

Lines changed: 0 additions & 30 deletions
This file was deleted.

libcxx/include/module.modulemap

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1550,7 +1550,6 @@ module std_private_memory_unique_temporary_buffer [system] {
15501550
}
15511551
module std_private_memory_uses_allocator [system] { header "__memory/uses_allocator.h" }
15521552
module std_private_memory_uses_allocator_construction [system] { header "__memory/uses_allocator_construction.h" }
1553-
module std_private_memory_voidify [system] { header "__memory/voidify.h" }
15541553

15551554
module std_private_memory_resource_memory_resource [system] { header "__memory_resource/memory_resource.h" }
15561555
module std_private_memory_resource_memory_resource_fwd [system] { header "__fwd/memory_resource.h" }

libcxx/include/optional

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ struct __optional_destruct_base<_Tp, false> {
287287
static_assert(is_object_v<value_type>, "instantiation of optional with a non-object type is undefined behavior");
288288
union {
289289
char __null_state_;
290-
value_type __val_;
290+
remove_cv_t<value_type> __val_;
291291
};
292292
bool __engaged_;
293293

@@ -323,7 +323,7 @@ struct __optional_destruct_base<_Tp, true> {
323323
static_assert(is_object_v<value_type>, "instantiation of optional with a non-object type is undefined behavior");
324324
union {
325325
char __null_state_;
326-
value_type __val_;
326+
remove_cv_t<value_type> __val_;
327327
};
328328
bool __engaged_;
329329

@@ -377,7 +377,7 @@ struct __optional_storage_base : __optional_destruct_base<_Tp> {
377377
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) {
378378
if (this->__engaged_ == __opt.has_value()) {
379379
if (this->__engaged_)
380-
this->__val_ = std::forward<_That>(__opt).__get();
380+
static_cast<_Tp&>(this->__val_) = std::forward<_That>(__opt).__get();
381381
} else {
382382
if (this->__engaged_)
383383
this->reset();

libcxx/test/std/utilities/memory/specialized.algorithms/specialized.construct/construct_at.pass.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -80,21 +80,6 @@ constexpr bool test()
8080
a.deallocate(p, 2);
8181
}
8282

83-
{
84-
std::allocator<Counted> a;
85-
Counted const* p = a.allocate(2);
86-
int count = 0;
87-
std::construct_at(p, count);
88-
assert(count == 1);
89-
std::construct_at(p+1, count);
90-
assert(count == 2);
91-
(p+1)->~Counted();
92-
assert(count == 1);
93-
p->~Counted();
94-
assert(count == 0);
95-
a.deallocate(const_cast<Counted*>(p), 2);
96-
}
97-
9883
return true;
9984
}
10085

libcxx/test/std/utilities/memory/specialized.algorithms/specialized.construct/ranges_construct_at.pass.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,6 @@ constexpr bool test() {
9999
alloc.deallocate(out, 2);
100100
}
101101

102-
// Works with const pointers.
103-
{
104-
int x = 1;
105-
const int* ptr = &x;
106-
107-
const int* result = std::ranges::construct_at(ptr, 42);
108-
assert(result == ptr);
109-
assert(x == 42);
110-
}
111-
112102
return true;
113103
}
114104

libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/ranges_uninitialized_default_construct.pass.cpp

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -163,30 +163,5 @@ int main(int, char**) {
163163
}
164164
#endif // TEST_HAS_NO_EXCEPTIONS
165165

166-
// Works with const iterators, (iter, sentinel) overload.
167-
{
168-
constexpr int N = 5;
169-
Buffer<Counted, N> buf;
170-
171-
std::ranges::uninitialized_default_construct(buf.cbegin(), buf.cend());
172-
assert(Counted::current_objects == N);
173-
assert(Counted::total_objects == N);
174-
std::destroy(buf.begin(), buf.end());
175-
Counted::reset();
176-
}
177-
178-
// Works with const iterators, (range) overload.
179-
{
180-
constexpr int N = 5;
181-
Buffer<Counted, N> buf;
182-
auto range = std::ranges::subrange(buf.cbegin(), buf.cend());
183-
184-
std::ranges::uninitialized_default_construct(range);
185-
assert(Counted::current_objects == N);
186-
assert(Counted::total_objects == N);
187-
std::destroy(buf.begin(), buf.end());
188-
Counted::reset();
189-
}
190-
191166
return 0;
192167
}

libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/ranges_uninitialized_default_construct_n.pass.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,5 @@ int main(int, char**) {
7575
}
7676
#endif // TEST_HAS_NO_EXCEPTIONS
7777

78-
// Works with const iterators.
79-
{
80-
constexpr int N = 5;
81-
Buffer<Counted, N> buf;
82-
83-
std::ranges::uninitialized_default_construct_n(buf.cbegin(), N);
84-
assert(Counted::current_objects == N);
85-
assert(Counted::total_objects == N);
86-
std::destroy(buf.begin(), buf.end());
87-
Counted::reset();
88-
}
89-
9078
return 0;
9179
}

libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/ranges_uninitialized_value_construct.pass.cpp

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -183,30 +183,5 @@ int main(int, char**) {
183183
}
184184
#endif // TEST_HAS_NO_EXCEPTIONS
185185

186-
// Works with const iterators, (iter, sentinel) overload.
187-
{
188-
constexpr int N = 5;
189-
Buffer<Counted, N> buf;
190-
191-
std::ranges::uninitialized_value_construct(buf.cbegin(), buf.cend());
192-
assert(Counted::current_objects == N);
193-
assert(Counted::total_objects == N);
194-
std::destroy(buf.begin(), buf.end());
195-
Counted::reset();
196-
}
197-
198-
// Works with const iterators, (range) overload.
199-
{
200-
constexpr int N = 5;
201-
Buffer<Counted, N> buf;
202-
203-
auto range = std::ranges::subrange(buf.cbegin(), buf.cend());
204-
std::ranges::uninitialized_value_construct(range);
205-
assert(Counted::current_objects == N);
206-
assert(Counted::total_objects == N);
207-
std::destroy(buf.begin(), buf.end());
208-
Counted::reset();
209-
}
210-
211186
return 0;
212187
}

0 commit comments

Comments
 (0)