Skip to content

Commit 628c67f

Browse files
committed
Revert "[libc++] LWG3870: Remove voidify (llvm#110355)"
This reverts commit 78f9a8b.
1 parent 725eb6b commit 628c67f

21 files changed

+298
-24
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)","|Complete|","20.0",""
299+
"`LWG3870 <https://wg21.link/LWG3870>`__","Remove ``voidify``","2023-02 (Issaquah)","","",""
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: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@ set(files
560560
__memory/unique_temporary_buffer.h
561561
__memory/uses_allocator.h
562562
__memory/uses_allocator_construction.h
563+
__memory/voidify.h
563564
__memory_resource/memory_resource.h
564565
__memory_resource/monotonic_buffer_resource.h
565566
__memory_resource/polymorphic_allocator.h

libcxx/include/__memory/construct_at.h

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

4344
#endif
@@ -48,7 +49,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp* __construct_at(_Tp* __l
4849
return std::construct_at(__location, std::forward<_Args>(__args)...);
4950
#else
5051
return _LIBCPP_ASSERT_NON_NULL(__location != nullptr, "null pointer given to construct_at"),
51-
::new (static_cast<void*>(__location)) _Tp(std::forward<_Args>(__args)...);
52+
::new (std::__voidify(*__location)) _Tp(std::forward<_Args>(__args)...);
5253
#endif
5354
}
5455

libcxx/include/__memory/shared_ptr.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -248,35 +248,33 @@ 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-
253251
template <class... _Args,
254252
class _Allocator = _Alloc,
255253
__enable_if_t<is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0>
256254
_LIBCPP_HIDE_FROM_ABI explicit __shared_ptr_emplace(_Alloc __a, _Args&&...) : __storage_(std::move(__a)) {
257255
static_assert(
258256
sizeof...(_Args) == 0, "No argument should be provided to the control block when using _for_overwrite");
259-
::new (static_cast<void*>(__get_elem())) __value_type;
257+
::new ((void*)__get_elem()) _Tp;
260258
}
261259

262260
template <class... _Args,
263261
class _Allocator = _Alloc,
264262
__enable_if_t<!is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0>
265263
_LIBCPP_HIDE_FROM_ABI explicit __shared_ptr_emplace(_Alloc __a, _Args&&... __args) : __storage_(std::move(__a)) {
266-
using _TpAlloc = typename __allocator_traits_rebind<_Alloc, __value_type>::type;
264+
using _TpAlloc = typename __allocator_traits_rebind<_Alloc, __remove_cv_t<_Tp> >::type;
267265
_TpAlloc __tmp(*__get_alloc());
268266
allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), std::forward<_Args>(__args)...);
269267
}
270268

271269
_LIBCPP_HIDE_FROM_ABI _Alloc* __get_alloc() _NOEXCEPT { return __storage_.__get_alloc(); }
272270

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

275273
private:
276274
template <class _Allocator = _Alloc,
277275
__enable_if_t<is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0>
278276
_LIBCPP_HIDE_FROM_ABI void __on_zero_shared_impl() _NOEXCEPT {
279-
__get_elem()->~__value_type();
277+
__get_elem()->~_Tp();
280278
}
281279

282280
template <class _Allocator = _Alloc,
@@ -302,7 +300,7 @@ struct __shared_ptr_emplace : __shared_weak_count {
302300
// through `std::allocate_shared` and `std::make_shared`.
303301
struct _Storage {
304302
struct _Data {
305-
_LIBCPP_COMPRESSED_PAIR(_Alloc, __alloc_, __value_type, __elem_);
303+
_LIBCPP_COMPRESSED_PAIR(_Alloc, __alloc_, _Tp, __elem_);
306304
};
307305

308306
_ALIGNAS_TYPE(_Data) char __buffer_[sizeof(_Data)];
@@ -314,7 +312,7 @@ struct __shared_ptr_emplace : __shared_weak_count {
314312
return std::addressof(reinterpret_cast<_Data*>(__buffer_)->__alloc_);
315313
}
316314

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

libcxx/include/__memory/uninitialized_algorithms.h

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <__memory/allocator_traits.h>
2222
#include <__memory/construct_at.h>
2323
#include <__memory/pointer_traits.h>
24+
#include <__memory/voidify.h>
2425
#include <__type_traits/enable_if.h>
2526
#include <__type_traits/extent.h>
2627
#include <__type_traits/is_array.h>
@@ -63,7 +64,7 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitiali
6364
try {
6465
#endif
6566
for (; __ifirst != __ilast && !__stop_copying(__idx); ++__ifirst, (void)++__idx)
66-
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(*__ifirst);
67+
::new (std::__voidify(*__idx)) _ValueType(*__ifirst);
6768
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
6869
} catch (...) {
6970
std::__destroy(__ofirst, __idx);
@@ -93,7 +94,7 @@ __uninitialized_copy_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __of
9394
try {
9495
#endif
9596
for (; __n > 0 && !__stop_copying(__idx); ++__ifirst, (void)++__idx, (void)--__n)
96-
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(*__ifirst);
97+
::new (std::__voidify(*__idx)) _ValueType(*__ifirst);
9798
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
9899
} catch (...) {
99100
std::__destroy(__ofirst, __idx);
@@ -123,7 +124,7 @@ __uninitialized_fill(_ForwardIterator __first, _Sentinel __last, const _Tp& __x)
123124
try {
124125
#endif
125126
for (; __idx != __last; ++__idx)
126-
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(__x);
127+
::new (std::__voidify(*__idx)) _ValueType(__x);
127128
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
128129
} catch (...) {
129130
std::__destroy(__first, __idx);
@@ -151,7 +152,7 @@ __uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) {
151152
try {
152153
#endif
153154
for (; __n > 0; ++__idx, (void)--__n)
154-
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(__x);
155+
::new (std::__voidify(*__idx)) _ValueType(__x);
155156
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
156157
} catch (...) {
157158
std::__destroy(__first, __idx);
@@ -181,7 +182,7 @@ __uninitialized_default_construct(_ForwardIterator __first, _Sentinel __last) {
181182
try {
182183
# endif
183184
for (; __idx != __last; ++__idx)
184-
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType;
185+
::new (std::__voidify(*__idx)) _ValueType;
185186
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
186187
} catch (...) {
187188
std::__destroy(__first, __idx);
@@ -207,7 +208,7 @@ inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_default_construct_
207208
try {
208209
# endif
209210
for (; __n > 0; ++__idx, (void)--__n)
210-
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType;
211+
::new (std::__voidify(*__idx)) _ValueType;
211212
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
212213
} catch (...) {
213214
std::__destroy(__first, __idx);
@@ -234,7 +235,7 @@ __uninitialized_value_construct(_ForwardIterator __first, _Sentinel __last) {
234235
try {
235236
# endif
236237
for (; __idx != __last; ++__idx)
237-
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType();
238+
::new (std::__voidify(*__idx)) _ValueType();
238239
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
239240
} catch (...) {
240241
std::__destroy(__first, __idx);
@@ -260,7 +261,7 @@ inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_value_construct_n(
260261
try {
261262
# endif
262263
for (; __n > 0; ++__idx, (void)--__n)
263-
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType();
264+
::new (std::__voidify(*__idx)) _ValueType();
264265
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
265266
} catch (...) {
266267
std::__destroy(__first, __idx);
@@ -296,7 +297,7 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitiali
296297
try {
297298
# endif
298299
for (; __ifirst != __ilast && !__stop_moving(__idx); ++__idx, (void)++__ifirst) {
299-
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(__iter_move(__ifirst));
300+
::new (std::__voidify(*__idx)) _ValueType(__iter_move(__ifirst));
300301
}
301302
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
302303
} catch (...) {
@@ -334,7 +335,7 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitiali
334335
try {
335336
# endif
336337
for (; __n > 0 && !__stop_moving(__idx); ++__idx, (void)++__ifirst, --__n)
337-
::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(__iter_move(__ifirst));
338+
::new (std::__voidify(*__idx)) _ValueType(__iter_move(__ifirst));
338339
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
339340
} catch (...) {
340341
std::__destroy(__ofirst, __idx);

libcxx/include/__memory/voidify.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef _LIBCPP___MEMORY_VOIDIFY_H
11+
#define _LIBCPP___MEMORY_VOIDIFY_H
12+
13+
#include <__config>
14+
#include <__memory/addressof.h>
15+
16+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
17+
# pragma GCC system_header
18+
#endif
19+
20+
_LIBCPP_BEGIN_NAMESPACE_STD
21+
22+
template <typename _Tp>
23+
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void* __voidify(_Tp& __from) {
24+
// Cast away cv-qualifiers to allow modifying elements of a range through const iterators.
25+
return const_cast<void*>(static_cast<const volatile void*>(std::addressof(__from)));
26+
}
27+
28+
_LIBCPP_END_NAMESPACE_STD
29+
30+
#endif // _LIBCPP___MEMORY_VOIDIFY_H

libcxx/include/module.modulemap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2237,3 +2237,5 @@ module std_private_mbstate_t [system] {
22372237
header "__mbstate_t.h"
22382238
export *
22392239
}
2240+
2241+
module std_private_memory_voidify [system] { header "__memory/voidify.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-
remove_cv_t<value_type> __val_;
290+
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-
remove_cv_t<value_type> __val_;
326+
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-
static_cast<_Tp&>(this->__val_) = std::forward<_That>(__opt).__get();
380+
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: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,21 @@ 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+
8398
return true;
8499
}
85100

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,16 @@ 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+
102112
return true;
103113
}
104114

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,5 +163,30 @@ 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+
166191
return 0;
167192
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,5 +75,17 @@ 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+
7890
return 0;
7991
}

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,5 +183,30 @@ 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+
186211
return 0;
187212
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,17 @@ int main(int, char**) {
9494
}
9595
#endif // TEST_HAS_NO_EXCEPTIONS
9696

97+
// Works with const iterators.
98+
{
99+
constexpr int N = 5;
100+
Buffer<Counted, N> buf;
101+
102+
std::ranges::uninitialized_value_construct_n(buf.cbegin(), N);
103+
assert(Counted::current_objects == N);
104+
assert(Counted::total_objects == N);
105+
std::destroy(buf.begin(), buf.end());
106+
Counted::reset();
107+
}
108+
97109
return 0;
98110
}

0 commit comments

Comments
 (0)