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 | // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 |
10 | |
11 | // <memory> |
12 | |
13 | // [out.ptr], function template out_ptr |
14 | // template<class Pointer = void, class Smart, class... Args> |
15 | // auto out_ptr(Smart& s, Args&&... args); // since c++23 |
16 | |
17 | #include <cassert> |
18 | #include <memory> |
19 | #include <utility> |
20 | |
21 | #include "../types.h" |
22 | |
23 | // Test updating an `out_ptr_t`-managed pointer for an API with a non-void pointer type. |
24 | // The API returns a new valid object. |
25 | void test_get_int_p() { |
26 | auto get_int_p = [](int** pp) { *pp = new int{84}; }; |
27 | |
28 | // raw pointer |
29 | { |
30 | int* rPtr; |
31 | |
32 | get_int_p(std::out_ptr<int*>(rPtr)); |
33 | assert(*rPtr == 84); |
34 | |
35 | delete rPtr; |
36 | } |
37 | |
38 | // std::unique_ptr |
39 | { |
40 | std::unique_ptr<int> uPtr; |
41 | |
42 | get_int_p(std::out_ptr(uPtr)); |
43 | assert(*uPtr == 84); |
44 | } |
45 | |
46 | { |
47 | MoveOnlyDeleter<int> del; |
48 | std::unique_ptr<int, MoveOnlyDeleter<int>> uPtr; |
49 | |
50 | get_int_p(std::out_ptr(uPtr, std::move(del))); |
51 | assert(*uPtr == 84); |
52 | assert(uPtr.get_deleter().wasMoveInitilized == true); |
53 | } |
54 | |
55 | // std::shared_ptr |
56 | { |
57 | std::shared_ptr<int> sPtr; |
58 | |
59 | get_int_p(std::out_ptr(sPtr, [](auto* p) { |
60 | assert(*p == 84); |
61 | |
62 | delete p; |
63 | })); |
64 | assert(*sPtr == 84); |
65 | } |
66 | |
67 | // pointer-like ConstructiblePtr |
68 | { |
69 | ConstructiblePtr<int> cPtr; |
70 | |
71 | get_int_p(std::out_ptr(cPtr)); |
72 | assert(cPtr == 84); |
73 | } |
74 | |
75 | // pointer-like ResettablePtr |
76 | { |
77 | ResettablePtr<int> rPtr{nullptr}; |
78 | |
79 | get_int_p(std::out_ptr(rPtr)); |
80 | assert(rPtr == 84); |
81 | } |
82 | |
83 | // NonConstructiblePtr |
84 | { |
85 | NonConstructiblePtr<int> nPtr; |
86 | |
87 | get_int_p(std::out_ptr(nPtr)); |
88 | assert(nPtr == 84); |
89 | } |
90 | } |
91 | |
92 | // Test updating an `out_ptr_t`-managed pointer for an API with a non-void pointer type. |
93 | // The API returns `nullptr`. |
94 | void test_get_int_p_nullptr() { |
95 | auto get_int_p_nullptr = [](int** pp) { *pp = nullptr; }; |
96 | // raw pointer |
97 | { |
98 | int* rPtr; |
99 | |
100 | get_int_p_nullptr(std::out_ptr<int*>(rPtr)); |
101 | assert(rPtr == nullptr); |
102 | |
103 | delete rPtr; |
104 | } |
105 | |
106 | // std::unique_ptr |
107 | { |
108 | std::unique_ptr<int> uPtr; |
109 | |
110 | get_int_p_nullptr(std::out_ptr(uPtr)); |
111 | assert(uPtr == nullptr); |
112 | } |
113 | |
114 | // std::shared_ptr |
115 | { |
116 | std::shared_ptr<int> sPtr; |
117 | |
118 | get_int_p_nullptr(std::out_ptr(sPtr, [](auto* p) { |
119 | assert(p == nullptr); |
120 | |
121 | delete p; |
122 | })); |
123 | assert(sPtr == nullptr); |
124 | } |
125 | } |
126 | |
127 | // Test updating an `out_ptr_t`-managed pointer for an API with a void pointer type. |
128 | // The API returns a new valid object. |
129 | void test_get_int_void_p() { |
130 | auto get_int_void_p = [](void** pp) { *(reinterpret_cast<int**>(pp)) = new int{84}; }; |
131 | |
132 | // raw pointer |
133 | { |
134 | int* rPtr; |
135 | |
136 | get_int_void_p(std::out_ptr(rPtr)); |
137 | assert(*rPtr == 84); |
138 | |
139 | delete rPtr; |
140 | } |
141 | |
142 | // std::unique_ptr |
143 | { |
144 | std::unique_ptr<int> uPtr; |
145 | |
146 | get_int_void_p(std::out_ptr(uPtr)); |
147 | assert(*uPtr == 84); |
148 | } |
149 | |
150 | // std::shared_ptr |
151 | { |
152 | std::shared_ptr<int> sPtr; |
153 | |
154 | get_int_void_p(std::out_ptr(sPtr, [](auto* p) { |
155 | assert(*p == 84); |
156 | |
157 | delete p; |
158 | })); |
159 | assert(*sPtr == 84); |
160 | } |
161 | |
162 | // pointer-like ConstructiblePtr |
163 | { |
164 | ConstructiblePtr<int> cPtr; |
165 | |
166 | get_int_void_p(std::out_ptr(cPtr)); |
167 | assert(cPtr == 84); |
168 | } |
169 | |
170 | // pointer-like ResettablePtr |
171 | { |
172 | ResettablePtr<int> rPtr{nullptr}; |
173 | |
174 | get_int_void_p(std::out_ptr(rPtr)); |
175 | assert(rPtr == 84); |
176 | } |
177 | |
178 | // NonConstructiblePtr |
179 | { |
180 | NonConstructiblePtr<int> nPtr; |
181 | |
182 | get_int_void_p(std::out_ptr(nPtr)); |
183 | assert(nPtr == 84); |
184 | } |
185 | } |
186 | |
187 | // Test updating an `out_ptr_t`-managed pointer for an API with a void pointer type. |
188 | // The API returns `nullptr`. |
189 | void test_get_int_void_p_nullptr() { |
190 | auto get_int_void_p_nullptr = [](void** pp) { *pp = nullptr; }; |
191 | |
192 | // raw pointer |
193 | { |
194 | int* rPtr; |
195 | |
196 | get_int_void_p_nullptr(std::out_ptr<int*>(rPtr)); |
197 | assert(rPtr == nullptr); |
198 | |
199 | delete rPtr; |
200 | } |
201 | |
202 | // std::unique_ptr |
203 | { |
204 | std::unique_ptr<int> uPtr; |
205 | |
206 | get_int_void_p_nullptr(std::out_ptr(uPtr)); |
207 | assert(uPtr == nullptr); |
208 | } |
209 | |
210 | // std::shared_ptr |
211 | { |
212 | std::shared_ptr<int> sPtr; |
213 | |
214 | get_int_void_p_nullptr(std::out_ptr(sPtr, [](auto* p) { |
215 | assert(p == nullptr); |
216 | |
217 | delete p; |
218 | })); |
219 | assert(sPtr == nullptr); |
220 | } |
221 | } |
222 | |
223 | int main(int, char**) { |
224 | test_get_int_p(); |
225 | test_get_int_p_nullptr(); |
226 | test_get_int_void_p(); |
227 | test_get_int_void_p_nullptr(); |
228 | |
229 | return 0; |
230 | } |
231 | |