1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
15 // template<class T> shared_ptr<T> make_shared(size_t N); // T is U[]
18 // shared_ptr<T> make_shared(size_t N, const remove_extent_t<T>& u); // T is U[]
20 // Ignore error about requesting a large alignment not being ABI compatible with older AIX systems.
22 # pragma clang diagnostic ignored "-Waix-compat"
27 #include <cstdint> // std::uintptr_t
31 #include "operator_hijacker.h"
32 #include "test_macros.h"
35 template <class T
, class ...Args
>
36 concept CanMakeShared
= requires(Args
&& ...args
) {
37 { std::make_shared
<T
>(std::forward
<Args
>(args
)...) } -> std::same_as
<std::shared_ptr
<T
>>;
40 int main(int, char**) {
41 // Check behavior for a zero-sized array
43 // Without passing an initial value
46 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(0);
47 assert(ptr
!= nullptr);
50 // Passing an initial value
53 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(0, 42);
54 assert(ptr
!= nullptr);
58 // Check behavior for a 1-sized array
60 // Without passing an initial value
63 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(1);
64 assert(ptr
!= nullptr);
68 // Passing an initial value
71 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(1, 42);
72 assert(ptr
!= nullptr);
77 // Make sure we initialize elements correctly
79 // Without passing an initial value
82 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8);
83 for (unsigned i
= 0; i
< 8; ++i
) {
88 using Array
= int[][3];
89 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8);
90 for (unsigned i
= 0; i
< 8; ++i
) {
91 assert(ptr
[i
][0] == 0);
92 assert(ptr
[i
][1] == 0);
93 assert(ptr
[i
][2] == 0);
97 using Array
= int[][3][2];
98 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8);
99 for (unsigned i
= 0; i
< 8; ++i
) {
100 assert(ptr
[i
][0][0] == 0);
101 assert(ptr
[i
][0][1] == 0);
102 assert(ptr
[i
][1][0] == 0);
103 assert(ptr
[i
][1][1] == 0);
104 assert(ptr
[i
][2][0] == 0);
105 assert(ptr
[i
][2][1] == 0);
109 // Passing an initial value
113 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8, init
);
114 for (unsigned i
= 0; i
< 8; ++i
) {
115 assert(ptr
[i
] == init
);
119 using Array
= int[][3];
120 int init
[3] = {42, 43, 44};
121 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8, init
);
122 for (unsigned i
= 0; i
< 8; ++i
) {
123 assert(ptr
[i
][0] == 42);
124 assert(ptr
[i
][1] == 43);
125 assert(ptr
[i
][2] == 44);
129 using Array
= int[][3][2];
130 int init
[3][2] = {{31, 32}, {41, 42}, {51, 52}};
131 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8, init
);
132 for (unsigned i
= 0; i
< 8; ++i
) {
133 assert(ptr
[i
][0][0] == 31);
134 assert(ptr
[i
][0][1] == 32);
135 assert(ptr
[i
][1][0] == 41);
136 assert(ptr
[i
][1][1] == 42);
137 assert(ptr
[i
][2][0] == 51);
138 assert(ptr
[i
][2][1] == 52);
143 // Make sure array elements are destroyed in reverse order
145 // Without passing an initial value
147 using Array
= DestroyInReverseOrder
[];
148 DestroyInReverseOrder::reset();
150 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8);
151 assert(DestroyInReverseOrder::alive() == 8);
153 assert(DestroyInReverseOrder::alive() == 0);
156 using Array
= DestroyInReverseOrder
[][3];
157 DestroyInReverseOrder::reset();
159 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8);
160 assert(DestroyInReverseOrder::alive() == 8 * 3);
162 assert(DestroyInReverseOrder::alive() == 0);
165 using Array
= DestroyInReverseOrder
[][3][2];
166 DestroyInReverseOrder::reset();
168 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8);
169 assert(DestroyInReverseOrder::alive() == 8 * 3 * 2);
171 assert(DestroyInReverseOrder::alive() == 0);
174 // Passing an initial value
176 using Array
= DestroyInReverseOrder
[];
178 DestroyInReverseOrder
init(&count
);
181 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8, init
);
182 assert(count
== 8 + init_count
);
184 assert(count
== init_count
);
187 using Array
= DestroyInReverseOrder
[][3];
189 DestroyInReverseOrder init
[3] = {&count
, &count
, &count
};
192 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8, init
);
193 assert(count
== 8 * 3 + init_count
);
195 assert(count
== init_count
);
198 using Array
= DestroyInReverseOrder
[][3][2];
200 DestroyInReverseOrder init
[3][2] = {{&count
, &count
}, {&count
, &count
}, {&count
, &count
}};
201 int init_count
= 3 * 2;
203 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8, init
);
204 assert(count
== 8 * 3 * 2 + init_count
);
206 assert(count
== init_count
);
210 // Count the number of copies being made
212 // Without passing an initial value
214 using Array
= CountCopies
[];
215 CountCopies::reset();
216 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8);
217 assert(CountCopies::copies() == 0);
220 using Array
= CountCopies
[][3];
221 CountCopies::reset();
222 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8);
223 assert(CountCopies::copies() == 0);
226 using Array
= CountCopies
[][3][2];
227 CountCopies::reset();
228 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8);
229 assert(CountCopies::copies() == 0);
232 // Passing an initial value
234 using Array
= CountCopies
[];
236 CountCopies
init(&copies
);
237 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8, init
);
241 using Array
= CountCopies
[][3];
243 CountCopies init
[3] = {&copies
, &copies
, &copies
};
244 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8, init
);
245 assert(copies
== 8 * 3);
248 using Array
= CountCopies
[][3][2];
250 CountCopies init
[3][2] = {{&copies
, &copies
}, {&copies
, &copies
}, {&copies
, &copies
}};
251 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8, init
);
252 assert(copies
== 8 * 3 * 2);
256 // Make sure array elements are aligned properly when the array contains an overaligned type.
258 // Here, we don't need to test both the with-initial-value and without-initial-value code paths,
259 // since we're just checking the alignment and both are going to use the same code path unless
260 // the implementation is completely crazy.
262 auto check_alignment
= []<class T
> {
265 std::shared_ptr ptr
= std::make_shared
<Array
>(8);
266 for (int i
= 0; i
< 8; ++i
) {
267 T
* p
= std::addressof(ptr
[i
]);
268 assert(reinterpret_cast<std::uintptr_t>(p
) % alignof(T
) == 0);
272 using Array
= T
[][3];
273 std::shared_ptr ptr
= std::make_shared
<Array
>(8);
274 for (int i
= 0; i
< 8; ++i
) {
275 for (int j
= 0; j
< 3; ++j
) {
276 T
* p
= std::addressof(ptr
[i
][j
]);
277 assert(reinterpret_cast<std::uintptr_t>(p
) % alignof(T
) == 0);
282 using Array
= T
[][3][2];
283 std::shared_ptr ptr
= std::make_shared
<Array
>(8);
284 for (int i
= 0; i
< 8; ++i
) {
285 for (int j
= 0; j
< 3; ++j
) {
286 for (int k
= 0; k
< 2; ++k
) {
287 T
* p
= std::addressof(ptr
[i
][j
][k
]);
288 assert(reinterpret_cast<std::uintptr_t>(p
) % alignof(T
) == 0);
296 check_alignment
.operator()<Empty
>();
297 check_alignment
.operator()<OverAligned
>();
298 check_alignment
.operator()<MaxAligned
>();
300 // test non corner cases as well while we're at it
301 struct Foo
{ int i
; char c
; };
302 check_alignment
.operator()<int>();
303 check_alignment
.operator()<Foo
>();
306 // Make sure that we destroy all the elements constructed so far when an exception
307 // is thrown. Also make sure that we do it in reverse order of construction.
308 #ifndef TEST_HAS_NO_EXCEPTIONS
310 struct Sentinel
: ThrowOnConstruction
, DestroyInReverseOrder
{ };
312 // Without passing an initial value
314 using Array
= Sentinel
[];
315 for (int i
= 0; i
< 8; ++i
) {
316 ThrowOnConstruction::throw_after(i
);
317 DestroyInReverseOrder::reset();
319 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8);
321 } catch (ThrowOnConstruction::exception
const&) {
322 assert(DestroyInReverseOrder::alive() == 0);
327 using Array
= Sentinel
[][3];
328 for (int i
= 0; i
< 8 * 3; ++i
) {
329 ThrowOnConstruction::throw_after(i
);
330 DestroyInReverseOrder::reset();
332 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8);
334 } catch (ThrowOnConstruction::exception
const&) {
335 assert(DestroyInReverseOrder::alive() == 0);
340 using Array
= Sentinel
[][3][2];
341 for (int i
= 0; i
< 8 * 3 * 2; ++i
) {
342 ThrowOnConstruction::throw_after(i
);
343 DestroyInReverseOrder::reset();
345 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8);
347 } catch (ThrowOnConstruction::exception
const&) {
348 assert(DestroyInReverseOrder::alive() == 0);
353 // Passing an initial value
355 using Array
= Sentinel
[];
356 for (int i
= 0; i
< 8; ++i
) {
357 DestroyInReverseOrder::reset();
358 ThrowOnConstruction::reset();
360 ThrowOnConstruction::throw_after(i
);
362 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8, init
);
364 } catch (ThrowOnConstruction::exception
const&) {
365 assert(DestroyInReverseOrder::alive() == 1);
370 using Array
= Sentinel
[][3];
371 for (int i
= 0; i
< 8 * 3; ++i
) {
372 DestroyInReverseOrder::reset();
373 ThrowOnConstruction::reset();
374 Sentinel init
[3] = {};
375 ThrowOnConstruction::throw_after(i
);
377 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8, init
);
379 } catch (ThrowOnConstruction::exception
const&) {
380 assert(DestroyInReverseOrder::alive() == 3);
385 using Array
= Sentinel
[][3][2];
386 for (int i
= 0; i
< 8 * 3 * 2; ++i
) {
387 DestroyInReverseOrder::reset();
388 ThrowOnConstruction::reset();
389 Sentinel init
[3][2] = {};
390 ThrowOnConstruction::throw_after(i
);
392 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8, init
);
394 } catch (ThrowOnConstruction::exception
const&) {
395 assert(DestroyInReverseOrder::alive() == 3 * 2);
400 #endif // TEST_HAS_NO_EXCEPTIONS
402 // Make sure the version without an initialization argument works even for non-movable types
404 using Array
= NonMovable
[][3];
405 std::shared_ptr
<Array
> ptr
= std::make_shared
<Array
>(8);
409 // Make sure std::make_shared handles badly-behaved types properly
411 using Array
= operator_hijacker
[];
412 std::shared_ptr
<Array
> p1
= std::make_shared
<Array
>(3);
413 std::shared_ptr
<Array
> p2
= std::make_shared
<Array
>(3, operator_hijacker());
414 assert(p1
!= nullptr);
415 assert(p2
!= nullptr);
418 // Check that we SFINAE-away for invalid arguments
421 static_assert( CanMakeShared
<T
[], std::size_t>);
422 static_assert( CanMakeShared
<T
[], std::size_t, T
>);
423 static_assert(!CanMakeShared
<T
[], std::size_t, T
, int>); // too many arguments