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
22struct Counted {
23 int* counter_;
24 TEST_CONSTEXPR Counted(int* counter) : counter_(counter) { ++*counter_; }
25 TEST_CONSTEXPR_CXX20 ~Counted() { --*counter_; }
26 friend void operator&(Counted) = delete;
27};
28
29struct VirtualCounted {
30 int* counter_;
31 TEST_CONSTEXPR VirtualCounted(int* counter) : counter_(counter) { ++*counter_; }
32 TEST_CONSTEXPR_CXX20 virtual ~VirtualCounted() { --*counter_; }
33 void operator&() const = delete;
34};
35
36struct DerivedCounted : VirtualCounted {
37 TEST_CONSTEXPR DerivedCounted(int* counter) : VirtualCounted(counter) { }
38 TEST_CONSTEXPR_CXX20 ~DerivedCounted() override { }
39};
40
41#if TEST_STD_VER > 17
42constexpr 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
84TEST_CONSTEXPR_CXX20 bool test() {
85 {
86 using Alloc = std::allocator<Counted>;
87 Alloc alloc;
88 Counted* ptr1 = std::allocator_traits<Alloc>::allocate(a&: alloc, n: 1);
89 Counted* ptr2 = std::allocator_traits<Alloc>::allocate(a&: alloc, n: 1);
90
91 int counter = 0;
92 std::allocator_traits<Alloc>::construct(a&: alloc, p: ptr1, args: &counter);
93 std::allocator_traits<Alloc>::construct(a&: alloc, p: ptr2, args: &counter);
94 assert(counter == 2);
95
96 std::destroy_at(location: ptr1);
97 ASSERT_SAME_TYPE(decltype(std::destroy_at(ptr1)), void);
98 assert(counter == 1);
99
100 std::destroy_at(location: ptr2);
101 assert(counter == 0);
102
103 std::allocator_traits<Alloc>::deallocate(a&: alloc, p: ptr1, n: 1);
104 std::allocator_traits<Alloc>::deallocate(a&: alloc, p: ptr2, n: 1);
105 }
106 {
107 using Alloc = std::allocator<DerivedCounted>;
108 Alloc alloc;
109 DerivedCounted* ptr1 = std::allocator_traits<Alloc>::allocate(a&: alloc, n: 1);
110 DerivedCounted* ptr2 = std::allocator_traits<Alloc>::allocate(a&: alloc, n: 1);
111
112 int counter = 0;
113 std::allocator_traits<Alloc>::construct(a&: alloc, p: ptr1, args: &counter);
114 std::allocator_traits<Alloc>::construct(a&: alloc, p: ptr2, args: &counter);
115 assert(counter == 2);
116
117 std::destroy_at(location: ptr1);
118 ASSERT_SAME_TYPE(decltype(std::destroy_at(ptr1)), void);
119 assert(counter == 1);
120
121 std::destroy_at(location: ptr2);
122 assert(counter == 0);
123
124 std::allocator_traits<Alloc>::deallocate(a&: alloc, p: ptr1, n: 1);
125 std::allocator_traits<Alloc>::deallocate(a&: alloc, p: ptr2, n: 1);
126 }
127
128 return true;
129}
130
131int 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

source code of libcxx/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_at.pass.cpp