1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // <memory>
10 
11 // unique_ptr
12 
13 // Test unique_ptr move ctor
14 
15 #include <memory>
16 #include <utility>
17 #include <cassert>
18 
19 #include "test_macros.h"
20 #include "unique_ptr_test_helper.h"
21 
22 //=============================================================================
23 // TESTING unique_ptr(unique_ptr&&)
24 //
25 // Concerns
26 //   1 The moved from pointer is empty and the new pointer stores the old value.
27 //   2 The only requirement on the deleter is that it is MoveConstructible
28 //     or a reference.
29 //   3 The constructor works for explicitly moved values (i.e. std::move(x))
30 //   4 The constructor works for true temporaries (e.g. a return value)
31 //
32 // Plan
33 //  1 Explicitly construct unique_ptr<T, D> for various deleter types 'D'.
34 //    check that the value and deleter have been properly moved. (C-1,2,3)
35 //
36 //  2 Use the expression 'sink(source())' to move construct a unique_ptr<T, D>
37 //    from a temporary. 'source' should return the unique_ptr by value and
38 //    'sink' should accept the unique_ptr by value. (C-1,2,4)
39 
40 template <class VT>
source1()41 TEST_CONSTEXPR_CXX23 std::unique_ptr<VT> source1() {
42   return std::unique_ptr<VT>(newValue<VT>(1));
43 }
44 
45 template <class VT>
source2()46 TEST_CONSTEXPR_CXX23 std::unique_ptr<VT, Deleter<VT> > source2() {
47   return std::unique_ptr<VT, Deleter<VT> >(newValue<VT>(1), Deleter<VT>(5));
48 }
49 
50 template <class VT>
source3()51 std::unique_ptr<VT, NCDeleter<VT>&> source3() {
52   static NCDeleter<VT> d(5);
53   return std::unique_ptr<VT, NCDeleter<VT>&>(newValue<VT>(1), d);
54 }
55 
56 template <class VT>
sink1(std::unique_ptr<VT> p)57 TEST_CONSTEXPR_CXX23 void sink1(std::unique_ptr<VT> p) {
58   assert(p.get() != nullptr);
59 }
60 
61 template <class VT>
sink2(std::unique_ptr<VT,Deleter<VT>> p)62 TEST_CONSTEXPR_CXX23 void sink2(std::unique_ptr<VT, Deleter<VT> > p) {
63   assert(p.get() != nullptr);
64   assert(p.get_deleter().state() == 5);
65 }
66 
67 template <class VT>
sink3(std::unique_ptr<VT,NCDeleter<VT> &> p)68 void sink3(std::unique_ptr<VT, NCDeleter<VT>&> p) {
69   assert(p.get() != nullptr);
70   assert(p.get_deleter().state() == 5);
71   assert(&p.get_deleter() == &source3<VT>().get_deleter());
72 }
73 
74 template <class ValueT>
test_sfinae()75 TEST_CONSTEXPR_CXX23 void test_sfinae() {
76   typedef std::unique_ptr<ValueT> U;
77   { // Ensure unique_ptr is non-copyable
78     static_assert((!std::is_constructible<U, U const&>::value), "");
79     static_assert((!std::is_constructible<U, U&>::value), "");
80   }
81 }
82 
83 template <bool IsArray>
test_basic()84 TEST_CONSTEXPR_CXX23 void test_basic() {
85   typedef typename std::conditional<!IsArray, A, A[]>::type VT;
86   const int expect_alive = IsArray ? 5 : 1;
87   {
88     typedef std::unique_ptr<VT> APtr;
89     APtr s(newValue<VT>(expect_alive));
90     A* p = s.get();
91     APtr s2 = std::move(s);
92     assert(s2.get() == p);
93     assert(s.get() == 0);
94     if (!TEST_IS_CONSTANT_EVALUATED)
95       assert(A::count == expect_alive);
96   }
97   if (!TEST_IS_CONSTANT_EVALUATED)
98     assert(A::count == 0);
99   {
100     typedef Deleter<VT> MoveDel;
101     typedef std::unique_ptr<VT, MoveDel> APtr;
102     MoveDel d(5);
103     APtr s(newValue<VT>(expect_alive), std::move(d));
104     assert(d.state() == 0);
105     assert(s.get_deleter().state() == 5);
106     A* p = s.get();
107     APtr s2 = std::move(s);
108     assert(s2.get() == p);
109     assert(s.get() == 0);
110     if (!TEST_IS_CONSTANT_EVALUATED)
111       assert(A::count == expect_alive);
112     assert(s2.get_deleter().state() == 5);
113     assert(s.get_deleter().state() == 0);
114   }
115   if (!TEST_IS_CONSTANT_EVALUATED)
116     assert(A::count == 0);
117   {
118     typedef NCDeleter<VT> NonCopyDel;
119     typedef std::unique_ptr<VT, NonCopyDel&> APtr;
120 
121     NonCopyDel d;
122     APtr s(newValue<VT>(expect_alive), d);
123     A* p = s.get();
124     APtr s2 = std::move(s);
125     assert(s2.get() == p);
126     assert(s.get() == 0);
127     if (!TEST_IS_CONSTANT_EVALUATED)
128       assert(A::count == expect_alive);
129     d.set_state(6);
130     assert(s2.get_deleter().state() == d.state());
131     assert(s.get_deleter().state() == d.state());
132   }
133   if (!TEST_IS_CONSTANT_EVALUATED)
134     assert(A::count == 0);
135   {
136     sink1<VT>(source1<VT>());
137     if (!TEST_IS_CONSTANT_EVALUATED)
138       assert(A::count == 0);
139     sink2<VT>(source2<VT>());
140     if (!TEST_IS_CONSTANT_EVALUATED)
141       assert(A::count == 0);
142   }
143   if (!TEST_IS_CONSTANT_EVALUATED)
144     assert(A::count == 0);
145 }
146 
147 template <class VT>
test_noexcept()148 TEST_CONSTEXPR_CXX23 void test_noexcept() {
149 #if TEST_STD_VER >= 11
150   {
151     typedef std::unique_ptr<VT> U;
152     static_assert(std::is_nothrow_move_constructible<U>::value, "");
153   }
154   {
155     typedef std::unique_ptr<VT, Deleter<VT> > U;
156     static_assert(std::is_nothrow_move_constructible<U>::value, "");
157   }
158   {
159     typedef std::unique_ptr<VT, NCDeleter<VT> &> U;
160     static_assert(std::is_nothrow_move_constructible<U>::value, "");
161   }
162   {
163     typedef std::unique_ptr<VT, const NCConstDeleter<VT> &> U;
164     static_assert(std::is_nothrow_move_constructible<U>::value, "");
165   }
166 #endif
167 }
168 
test()169 TEST_CONSTEXPR_CXX23 bool test() {
170   {
171     test_basic</*IsArray*/ false>();
172     test_sfinae<int>();
173     test_noexcept<int>();
174   }
175   {
176     test_basic</*IsArray*/ true>();
177     test_sfinae<int[]>();
178     test_noexcept<int[]>();
179   }
180 
181   return true;
182 }
183 
184 template <bool IsArray>
test_sink3()185 void test_sink3() {
186   typedef typename std::conditional<!IsArray, A, A[]>::type VT;
187   sink3<VT>(source3<VT>());
188   assert(A::count == 0);
189 }
190 
main(int,char **)191 int main(int, char**) {
192   test_sink3</*IsArray*/ false>();
193   test_sink3</*IsArray*/ true>();
194   test();
195 #if TEST_STD_VER >= 23
196   static_assert(test());
197 #endif
198 
199   return 0;
200 }
201