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.
25void 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`.
88void 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.
116void 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`.
145void 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.
172void 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
198int 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

source code of libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr.general.pass.cpp