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 | // [inout.ptr], function template inout_ptr |
14 | // template<class Pointer = void, class Smart, class... Args> |
15 | // auto inout_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 the ownership of an `inout_ptr_t`-managed pointer for an API with a non-void pointer type. |
24 | // The API returns a new valid object. |
25 | void test_replace_int_p() { |
26 | auto replace_int_p = [](int** pp) { |
27 | assert(**pp == 90); |
28 | |
29 | delete *pp; |
30 | *pp = new int{84}; |
31 | }; |
32 | |
33 | // raw pointer |
34 | { |
35 | auto rPtr = new int{90}; |
36 | |
37 | replace_int_p(std::inout_ptr<int*>(rPtr)); |
38 | assert(*rPtr == 84); |
39 | |
40 | delete rPtr; |
41 | } |
42 | |
43 | // std::unique_ptr |
44 | { |
45 | auto uPtr = std::make_unique<int>(args: 90); |
46 | |
47 | replace_int_p(std::inout_ptr(uPtr)); |
48 | assert(*uPtr == 84); |
49 | } |
50 | |
51 | { |
52 | MoveOnlyDeleter<int> del; |
53 | std::unique_ptr<int, MoveOnlyDeleter<int>> uPtr{new int{90}}; |
54 | |
55 | replace_int_p(std::inout_ptr(uPtr, std::move(del))); |
56 | assert(*uPtr == 84); |
57 | assert(uPtr.get_deleter().wasMoveInitilized == true); |
58 | } |
59 | |
60 | // pointer-like ConstructiblePtr |
61 | { |
62 | ConstructiblePtr<int> cPtr(new int{90}); |
63 | |
64 | replace_int_p(std::inout_ptr(cPtr)); |
65 | assert(cPtr == 84); |
66 | } |
67 | |
68 | // pointer-like ResettablePtr |
69 | { |
70 | ResettablePtr<int> rPtr(new int{90}); |
71 | |
72 | replace_int_p(std::inout_ptr(rPtr)); |
73 | assert(rPtr == 84); |
74 | } |
75 | |
76 | // pointer-like NonConstructiblePtr |
77 | { |
78 | NonConstructiblePtr<int> nPtr; |
79 | nPtr.reset(p: new int{90}); |
80 | |
81 | replace_int_p(std::inout_ptr(nPtr)); |
82 | assert(nPtr == 84); |
83 | } |
84 | } |
85 | |
86 | // Test updating the ownership of an `inout_ptr_t`-managed pointer for an API with a non-void pointer type. |
87 | // The API returns `nullptr`. |
88 | void test_replace_int_p_with_nullptr() { |
89 | auto replace_int_p_with_nullptr = [](int** pp) -> void { |
90 | assert(**pp == 90); |
91 | |
92 | delete *pp; |
93 | *pp = nullptr; |
94 | }; |
95 | |
96 | // raw pointer |
97 | { |
98 | // LWG-3897 inout_ptr will not update raw pointer to null |
99 | auto rPtr = new int{90}; |
100 | |
101 | replace_int_p_with_nullptr(std::inout_ptr<int*>(rPtr)); |
102 | assert(rPtr == nullptr); |
103 | } |
104 | |
105 | // std::unique_ptr |
106 | { |
107 | auto uPtr = std::make_unique<int>(args: 90); |
108 | |
109 | replace_int_p_with_nullptr(std::inout_ptr(uPtr)); |
110 | assert(uPtr == nullptr); |
111 | } |
112 | } |
113 | |
114 | // Test updating the ownership of an `inout_ptr_t`-managed pointer for an API with a void pointer type. |
115 | // The API returns a new valid object. |
116 | void test_replace_int_void_p() { |
117 | auto replace_int_void_p = [](void** pp) { |
118 | assert(*(static_cast<int*>(*pp)) == 90); |
119 | |
120 | delete static_cast<int*>(*pp); |
121 | *pp = new int{84}; |
122 | }; |
123 | |
124 | // raw pointer |
125 | { |
126 | auto rPtr = new int{90}; |
127 | |
128 | replace_int_void_p(std::inout_ptr<int*>(rPtr)); |
129 | assert(*rPtr == 84); |
130 | |
131 | delete rPtr; |
132 | } |
133 | |
134 | // std::unique_ptr |
135 | { |
136 | auto uPtr = std::make_unique<int>(args: 90); |
137 | |
138 | replace_int_void_p(std::inout_ptr(uPtr)); |
139 | assert(*uPtr == 84); |
140 | } |
141 | } |
142 | |
143 | // Test updating the ownership of an `inout_ptr_t`-managed pointer for an API with a non-void pointer type. |
144 | // The API returns `nullptr`. |
145 | void test_replace_int_void_p_with_nullptr() { |
146 | auto replace_int_void_p_with_nullptr = [](void** pp) { |
147 | assert(*(static_cast<int*>(*pp)) == 90); |
148 | |
149 | delete static_cast<int*>(*pp); |
150 | *pp = nullptr; |
151 | }; |
152 | |
153 | // raw pointer |
154 | { |
155 | auto rPtr = new int{90}; |
156 | |
157 | replace_int_void_p_with_nullptr(std::inout_ptr<int*>(rPtr)); |
158 | assert(rPtr == nullptr); |
159 | } |
160 | |
161 | // std::unique_ptr |
162 | { |
163 | auto uPtr = std::make_unique<int>(args: 90); |
164 | |
165 | replace_int_void_p_with_nullptr(std::inout_ptr(uPtr)); |
166 | assert(uPtr == nullptr); |
167 | } |
168 | } |
169 | |
170 | // Test updating the ownership of an `inout_ptr_t`-managed pointer for an API with a void pointer type. |
171 | // The API returns a new valid object. |
172 | void test_replace_nullptr_with_int_p() { |
173 | auto replace_nullptr_with_int_p = [](int** pp) { |
174 | assert(*pp == nullptr); |
175 | |
176 | *pp = new int{84}; |
177 | }; |
178 | |
179 | // raw pointer |
180 | { |
181 | int* rPtr = nullptr; |
182 | |
183 | replace_nullptr_with_int_p(std::inout_ptr<int*>(rPtr)); |
184 | assert(*rPtr == 84); |
185 | |
186 | delete rPtr; |
187 | } |
188 | |
189 | // std::unique_ptr |
190 | { |
191 | std::unique_ptr<int> uPtr; |
192 | |
193 | replace_nullptr_with_int_p(std::inout_ptr(uPtr)); |
194 | assert(*uPtr == 84); |
195 | } |
196 | } |
197 | |
198 | int main(int, char**) { |
199 | test_replace_int_p(); |
200 | test_replace_int_p_with_nullptr(); |
201 | test_replace_int_void_p(); |
202 | test_replace_int_void_p_with_nullptr(); |
203 | test_replace_nullptr_with_int_p(); |
204 | |
205 | return 0; |
206 | } |
207 | |