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: no-exceptions |
10 | |
11 | // ensure that __uninitialized_allocator_copy calls the proper construct and destruct functions |
12 | |
13 | #include <algorithm> |
14 | #include <iterator> |
15 | #include <memory> |
16 | |
17 | #include "test_allocator.h" |
18 | |
19 | template <class T> |
20 | class construct_counting_allocator { |
21 | public: |
22 | using value_type = T; |
23 | |
24 | int* constructed_count_; |
25 | int* max_constructed_count_; |
26 | |
27 | construct_counting_allocator(int* constructed_count, int* max_constructed_count) |
28 | : constructed_count_(constructed_count), max_constructed_count_(max_constructed_count) {} |
29 | |
30 | template <class... Args> |
31 | void construct(T* ptr, Args&&... args) { |
32 | ::new (static_cast<void*>(ptr)) T(args...); |
33 | ++*constructed_count_; |
34 | *max_constructed_count_ = std::max(*max_constructed_count_, *constructed_count_); |
35 | } |
36 | |
37 | void destroy(T* ptr) { |
38 | --*constructed_count_; |
39 | ptr->~T(); |
40 | } |
41 | }; |
42 | |
43 | int throw_if_zero = 15; |
44 | |
45 | struct ThrowSometimes { |
46 | ThrowSometimes() = default; |
47 | ThrowSometimes(const ThrowSometimes&) { |
48 | if (--throw_if_zero == 0) |
49 | throw 1; |
50 | } |
51 | }; |
52 | |
53 | int main(int, char**) { |
54 | int constructed_count = 0; |
55 | int max_constructed_count = 0; |
56 | construct_counting_allocator<ThrowSometimes> alloc(&constructed_count, &max_constructed_count); |
57 | ThrowSometimes in[20]; |
58 | TEST_ALIGNAS_TYPE(ThrowSometimes) char out[sizeof(ThrowSometimes) * 20]; |
59 | try { |
60 | std::__uninitialized_allocator_copy( |
61 | alloc, std::begin(arr&: in), std::end(arr&: in), reinterpret_cast<ThrowSometimes*>(std::begin(out))); |
62 | } catch (...) { |
63 | } |
64 | |
65 | assert(constructed_count == 0); |
66 | assert(max_constructed_count == 14); |
67 | } |
68 | |