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
10
11 // <memory>
12
13 // template <class T>
14 // constexpr void destroy_at(T*);
15
16 #include <memory>
17 #include <cassert>
18 #include <type_traits>
19
20 #include "test_macros.h"
21
22 struct Counted {
23 int* counter_;
CountedCounted24 TEST_CONSTEXPR Counted(int* counter) : counter_(counter) { ++*counter_; }
~CountedCounted25 TEST_CONSTEXPR_CXX20 ~Counted() { --*counter_; }
26 friend void operator&(Counted) = delete;
27 };
28
29 struct VirtualCounted {
30 int* counter_;
VirtualCountedVirtualCounted31 TEST_CONSTEXPR VirtualCounted(int* counter) : counter_(counter) { ++*counter_; }
~VirtualCountedVirtualCounted32 TEST_CONSTEXPR_CXX20 virtual ~VirtualCounted() { --*counter_; }
33 void operator&() const = delete;
34 };
35
36 struct DerivedCounted : VirtualCounted {
DerivedCountedDerivedCounted37 TEST_CONSTEXPR DerivedCounted(int* counter) : VirtualCounted(counter) { }
~DerivedCountedDerivedCounted38 TEST_CONSTEXPR_CXX20 ~DerivedCounted() override { }
39 };
40
41 #if TEST_STD_VER > 17
test_arrays()42 constexpr bool test_arrays() {
43 {
44 using Array = Counted[3];
45 using Alloc = std::allocator<Array>;
46 Alloc alloc;
47 Array* ptr = std::allocator_traits<Alloc>::allocate(alloc, 1);
48 Array& arr = *ptr;
49
50 int counter = 0;
51 for (int i = 0; i != 3; ++i)
52 std::allocator_traits<Alloc>::construct(alloc, std::addressof(arr[i]), &counter);
53 assert(counter == 3);
54
55 std::destroy_at(ptr);
56 ASSERT_SAME_TYPE(decltype(std::destroy_at(ptr)), void);
57 assert(counter == 0);
58
59 std::allocator_traits<Alloc>::deallocate(alloc, ptr, 1);
60 }
61 {
62 using Array = Counted[3][2];
63 using Alloc = std::allocator<Array>;
64 Alloc alloc;
65 Array* ptr = std::allocator_traits<Alloc>::allocate(alloc, 1);
66 Array& arr = *ptr;
67
68 int counter = 0;
69 for (int i = 0; i != 3; ++i)
70 for (int j = 0; j != 2; ++j)
71 std::allocator_traits<Alloc>::construct(alloc, std::addressof(arr[i][j]), &counter);
72 assert(counter == 3 * 2);
73
74 std::destroy_at(ptr);
75 ASSERT_SAME_TYPE(decltype(std::destroy_at(ptr)), void);
76 assert(counter == 0);
77
78 std::allocator_traits<Alloc>::deallocate(alloc, ptr, 1);
79 }
80 return true;
81 }
82 #endif
83
test()84 TEST_CONSTEXPR_CXX20 bool test() {
85 {
86 using Alloc = std::allocator<Counted>;
87 Alloc alloc;
88 Counted* ptr1 = std::allocator_traits<Alloc>::allocate(alloc, 1);
89 Counted* ptr2 = std::allocator_traits<Alloc>::allocate(alloc, 1);
90
91 int counter = 0;
92 std::allocator_traits<Alloc>::construct(alloc, ptr1, &counter);
93 std::allocator_traits<Alloc>::construct(alloc, ptr2, &counter);
94 assert(counter == 2);
95
96 std::destroy_at(ptr1);
97 ASSERT_SAME_TYPE(decltype(std::destroy_at(ptr1)), void);
98 assert(counter == 1);
99
100 std::destroy_at(ptr2);
101 assert(counter == 0);
102
103 std::allocator_traits<Alloc>::deallocate(alloc, ptr1, 1);
104 std::allocator_traits<Alloc>::deallocate(alloc, ptr2, 1);
105 }
106 {
107 using Alloc = std::allocator<DerivedCounted>;
108 Alloc alloc;
109 DerivedCounted* ptr1 = std::allocator_traits<Alloc>::allocate(alloc, 1);
110 DerivedCounted* ptr2 = std::allocator_traits<Alloc>::allocate(alloc, 1);
111
112 int counter = 0;
113 std::allocator_traits<Alloc>::construct(alloc, ptr1, &counter);
114 std::allocator_traits<Alloc>::construct(alloc, ptr2, &counter);
115 assert(counter == 2);
116
117 std::destroy_at(ptr1);
118 ASSERT_SAME_TYPE(decltype(std::destroy_at(ptr1)), void);
119 assert(counter == 1);
120
121 std::destroy_at(ptr2);
122 assert(counter == 0);
123
124 std::allocator_traits<Alloc>::deallocate(alloc, ptr1, 1);
125 std::allocator_traits<Alloc>::deallocate(alloc, ptr2, 1);
126 }
127
128 return true;
129 }
130
main(int,char **)131 int main(int, char**) {
132 test();
133 #if TEST_STD_VER > 17
134 test_arrays();
135 static_assert(test());
136 // TODO: Until std::construct_at has support for arrays, it's impossible to test this
137 // in a constexpr context (see https://reviews.llvm.org/D114903).
138 // static_assert(test_arrays());
139 #endif
140 return 0;
141 }
142