Skip to content

Commit 5cb4200

Browse files
zoecarvertstellar
authored andcommitted
[libcxx] Allow shared_ptr's unique_ptr converting constructor to support array types.
Refs: https://bugs.llvm.org/show_bug.cgi?id=32147 Differential Revision: https://reviews.llvm.org/D80882 (cherry picked from commit 097d77d)
1 parent 0680e2b commit 5cb4200

File tree

3 files changed

+178
-10
lines changed

3 files changed

+178
-10
lines changed

libcxx/include/memory

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2771,7 +2771,6 @@ public:
27712771
typename enable_if
27722772
<
27732773
!is_lvalue_reference<_Dp>::value &&
2774-
!is_array<_Yp>::value &&
27752774
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value,
27762775
__nat
27772776
>::type = __nat());
@@ -2780,7 +2779,6 @@ public:
27802779
typename enable_if
27812780
<
27822781
is_lvalue_reference<_Dp>::value &&
2783-
!is_array<_Yp>::value &&
27842782
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value,
27852783
__nat
27862784
>::type = __nat());
@@ -2821,7 +2819,6 @@ public:
28212819
template <class _Yp, class _Dp>
28222820
typename enable_if
28232821
<
2824-
!is_array<_Yp>::value &&
28252822
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value,
28262823
shared_ptr&
28272824
>::type
@@ -3183,7 +3180,6 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r,
31833180
typename enable_if
31843181
<
31853182
!is_lvalue_reference<_Dp>::value &&
3186-
!is_array<_Yp>::value &&
31873183
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value,
31883184
__nat
31893185
>::type)
@@ -3196,7 +3192,7 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r,
31963192
#endif
31973193
{
31983194
typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
3199-
typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT > _CntrlBlk;
3195+
typedef __shared_ptr_pointer<typename unique_ptr<_Yp, _Dp>::pointer, _Dp, _AllocT > _CntrlBlk;
32003196
__cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), _AllocT());
32013197
__enable_weak_this(__r.get(), __r.get());
32023198
}
@@ -3209,7 +3205,6 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r,
32093205
typename enable_if
32103206
<
32113207
is_lvalue_reference<_Dp>::value &&
3212-
!is_array<_Yp>::value &&
32133208
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value,
32143209
__nat
32153210
>::type)
@@ -3222,7 +3217,7 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r,
32223217
#endif
32233218
{
32243219
typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
3225-
typedef __shared_ptr_pointer<_Yp*,
3220+
typedef __shared_ptr_pointer<typename unique_ptr<_Yp, _Dp>::pointer,
32263221
reference_wrapper<typename remove_reference<_Dp>::type>,
32273222
_AllocT > _CntrlBlk;
32283223
__cntrl_ = new _CntrlBlk(__r.get(), _VSTD::ref(__r.get_deleter()), _AllocT());
@@ -3306,7 +3301,6 @@ template <class _Yp, class _Dp>
33063301
inline
33073302
typename enable_if
33083303
<
3309-
!is_array<_Yp>::value &&
33103304
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer,
33113305
typename shared_ptr<_Tp>::element_type*>::value,
33123306
shared_ptr<_Tp>&

libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.assign/unique_ptr_Y.pass.cpp

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,19 @@ struct A
4141

4242
int A::count = 0;
4343

44+
template <class T>
45+
struct StatefulArrayDeleter {
46+
int state = 0;
47+
48+
StatefulArrayDeleter(int val = 0) : state(val) {}
49+
StatefulArrayDeleter(StatefulArrayDeleter const&) { assert(false); }
50+
51+
void operator()(T* ptr) {
52+
assert(state == 42);
53+
delete []ptr;
54+
}
55+
};
56+
4457
int main(int, char**)
4558
{
4659
{
@@ -112,5 +125,82 @@ int main(int, char**)
112125
assert(B::count == 0);
113126
assert(A::count == 0);
114127

128+
{
129+
std::unique_ptr<A[]> ptr(new A[8]);
130+
A* raw_ptr = ptr.get();
131+
std::shared_ptr<B> p;
132+
p = std::move(ptr);
133+
assert(A::count == 8);
134+
assert(B::count == 8);
135+
assert(p.use_count() == 1);
136+
assert(p.get() == raw_ptr);
137+
assert(ptr.get() == 0);
138+
}
139+
assert(A::count == 0);
140+
assert(B::count == 0);
141+
142+
{
143+
std::unique_ptr<A[]> ptr(new A[8]);
144+
A* raw_ptr = ptr.get();
145+
std::shared_ptr<A> p;
146+
p = std::move(ptr);
147+
assert(A::count == 8);
148+
assert(p.use_count() == 1);
149+
assert(p.get() == raw_ptr);
150+
assert(ptr.get() == 0);
151+
}
152+
assert(A::count == 0);
153+
154+
{
155+
std::unique_ptr<int[]> ptr(new int[8]);
156+
std::shared_ptr<int> p;
157+
p = std::move(ptr);
158+
}
159+
160+
#if TEST_STD_VER > 14
161+
{
162+
StatefulArrayDeleter<A> d;
163+
std::unique_ptr<A[], StatefulArrayDeleter<A>&> u(new A[4], d);
164+
std::shared_ptr<A[]> p;
165+
p = std::move(u);
166+
d.state = 42;
167+
assert(A::count == 4);
168+
}
169+
assert(A::count == 0);
170+
assert(B::count == 0);
171+
172+
{
173+
std::unique_ptr<A[]> ptr(new A[8]);
174+
A* raw_ptr = ptr.get();
175+
std::shared_ptr<B[]> p;
176+
p = std::move(ptr);
177+
assert(A::count == 8);
178+
assert(B::count == 8);
179+
assert(p.use_count() == 1);
180+
assert(p.get() == raw_ptr);
181+
assert(ptr.get() == 0);
182+
}
183+
assert(A::count == 0);
184+
assert(B::count == 0);
185+
186+
{
187+
std::unique_ptr<A[]> ptr(new A[8]);
188+
A* raw_ptr = ptr.get();
189+
std::shared_ptr<A[]> p;
190+
p = std::move(ptr);
191+
assert(A::count == 8);
192+
assert(p.use_count() == 1);
193+
assert(p.get() == raw_ptr);
194+
assert(ptr.get() == 0);
195+
}
196+
assert(A::count == 0);
197+
198+
{
199+
std::unique_ptr<int[]> ptr(new int[8]);
200+
std::shared_ptr<int[]> p;
201+
p = std::move(ptr);
202+
}
203+
#endif // TEST_STD_VER >= 14
204+
115205
return 0;
116206
}

libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
// <memory>
1212

13-
// template <class Y, class D> explicit shared_ptr(unique_ptr<Y, D>&&r);
13+
// template <class Y, class D> shared_ptr(unique_ptr<Y, D>&&r);
1414

1515
#include <memory>
1616
#include <new>
@@ -69,6 +69,19 @@ struct StatefulDeleter {
6969
}
7070
};
7171

72+
template <class T>
73+
struct StatefulArrayDeleter {
74+
int state = 0;
75+
76+
StatefulArrayDeleter(int val = 0) : state(val) {}
77+
StatefulArrayDeleter(StatefulArrayDeleter const&) { assert(false); }
78+
79+
void operator()(T* ptr) {
80+
assert(state == 42);
81+
delete []ptr;
82+
}
83+
};
84+
7285
int main(int, char**)
7386
{
7487
{
@@ -135,5 +148,76 @@ int main(int, char**)
135148
std::shared_ptr<int> s = std::move(u);
136149
}
137150

138-
return 0;
151+
assert(A::count == 0);
152+
{
153+
std::unique_ptr<A[]> ptr(new A[8]);
154+
A* raw_ptr = ptr.get();
155+
std::shared_ptr<B> p(std::move(ptr));
156+
assert(A::count == 8);
157+
assert(B::count == 8);
158+
assert(p.use_count() == 1);
159+
assert(p.get() == raw_ptr);
160+
assert(ptr.get() == 0);
161+
}
162+
assert(A::count == 0);
163+
assert(B::count == 0);
164+
165+
{
166+
std::unique_ptr<A[]> ptr(new A[8]);
167+
A* raw_ptr = ptr.get();
168+
std::shared_ptr<A> p(std::move(ptr));
169+
assert(A::count == 8);
170+
assert(p.use_count() == 1);
171+
assert(p.get() == raw_ptr);
172+
assert(ptr.get() == 0);
173+
}
174+
assert(A::count == 0);
175+
176+
{
177+
std::unique_ptr<int[]> ptr(new int[8]);
178+
std::shared_ptr<int> p(std::move(ptr));
179+
}
180+
181+
#if TEST_STD_VER > 14
182+
{
183+
StatefulArrayDeleter<A> d;
184+
std::unique_ptr<A[], StatefulArrayDeleter<A>&> u(new A[4], d);
185+
std::shared_ptr<A[]> p(std::move(u));
186+
d.state = 42;
187+
assert(A::count == 4);
188+
}
189+
assert(A::count == 0);
190+
assert(B::count == 0);
191+
192+
{
193+
std::unique_ptr<A[]> ptr(new A[8]);
194+
A* raw_ptr = ptr.get();
195+
std::shared_ptr<B[]> p(std::move(ptr));
196+
assert(A::count == 8);
197+
assert(B::count == 8);
198+
assert(p.use_count() == 1);
199+
assert(p.get() == raw_ptr);
200+
assert(ptr.get() == 0);
201+
}
202+
assert(A::count == 0);
203+
assert(B::count == 0);
204+
205+
{
206+
std::unique_ptr<A[]> ptr(new A[8]);
207+
A* raw_ptr = ptr.get();
208+
std::shared_ptr<A[]> p(std::move(ptr));
209+
assert(A::count == 8);
210+
assert(p.use_count() == 1);
211+
assert(p.get() == raw_ptr);
212+
assert(ptr.get() == 0);
213+
}
214+
assert(A::count == 0);
215+
216+
{
217+
std::unique_ptr<int[]> ptr(new int[8]);
218+
std::shared_ptr<int[]> p(std::move(ptr));
219+
}
220+
#endif // TEST_STD_VER >= 14
221+
222+
return 0;
139223
}

0 commit comments

Comments
 (0)