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 // <memory> 10 11 // unique_ptr 12 13 // T& unique_ptr::operator[](size_t) const 14 15 #include <memory> 16 #include <cassert> 17 #include <type_traits> 18 #include <array> 19 20 #include "test_macros.h" 21 #include "type_algorithms.h" 22 23 static int next = 0; 24 struct EnumeratedDefaultCtor { 25 EnumeratedDefaultCtor() : value(0) { value = ++next; } 26 int value; 27 }; 28 29 template <std::size_t Size> 30 struct WithTrivialDtor { 31 std::array<char, Size> padding = {'x'}; 32 TEST_CONSTEXPR_CXX23 friend bool operator==(WithTrivialDtor const& x, WithTrivialDtor const& y) { 33 return x.padding == y.padding; 34 } 35 }; 36 37 template <std::size_t Size> 38 struct WithNonTrivialDtor { 39 std::array<char, Size> padding = {'x'}; 40 TEST_CONSTEXPR_CXX23 friend bool operator==(WithNonTrivialDtor const& x, WithNonTrivialDtor const& y) { 41 return x.padding == y.padding; 42 } 43 TEST_CONSTEXPR_CXX23 ~WithNonTrivialDtor() {} 44 }; 45 46 template <class T> 47 struct CustomDeleter : std::default_delete<T> {}; 48 49 struct NoopDeleter { 50 template <class T> 51 TEST_CONSTEXPR_CXX23 void operator()(T*) const {} 52 }; 53 54 TEST_CONSTEXPR_CXX23 bool test() { 55 // Basic test 56 { 57 std::unique_ptr<int[]> p(new int[3]); 58 { 59 int& result = p[0]; 60 result = 0; 61 } 62 { 63 int& result = p[1]; 64 result = 1; 65 } 66 { 67 int& result = p[2]; 68 result = 2; 69 } 70 71 assert(p[0] == 0); 72 assert(p[1] == 1); 73 assert(p[2] == 2); 74 } 75 76 // Ensure that the order of access is correct after initializing a unique_ptr but 77 // before actually modifying any of its elements. The implementation would have to 78 // really try for this not to be the case, but we still check it. 79 // 80 // This requires assigning known values to the elements when they are first constructed, 81 // which requires global state. 82 { 83 if (!TEST_IS_CONSTANT_EVALUATED) { 84 std::unique_ptr<EnumeratedDefaultCtor[]> p(new EnumeratedDefaultCtor[3]); 85 assert(p[0].value == 1); 86 assert(p[1].value == 2); 87 assert(p[2].value == 3); 88 } 89 } 90 91 // Make sure operator[] is const-qualified 92 { 93 std::unique_ptr<int[]> const p(new int[3]); 94 p[0] = 42; 95 assert(p[0] == 42); 96 } 97 98 // Make sure we properly handle types with trivial and non-trivial destructors of different 99 // sizes. This is relevant because some implementations may want to use properties of the 100 // ABI like array cookies and these properties often depend on e.g. the triviality of T's 101 // destructor, T's size and so on. 102 #if TEST_STD_VER >= 20 // this test is too painful to write before C++20 103 { 104 using TrickyCookieTypes = types::type_list< 105 WithTrivialDtor<1>, 106 WithTrivialDtor<2>, 107 WithTrivialDtor<3>, 108 WithTrivialDtor<4>, 109 WithTrivialDtor<8>, 110 WithTrivialDtor<16>, 111 WithTrivialDtor<256>, 112 WithNonTrivialDtor<1>, 113 WithNonTrivialDtor<2>, 114 WithNonTrivialDtor<3>, 115 WithNonTrivialDtor<4>, 116 WithNonTrivialDtor<8>, 117 WithNonTrivialDtor<16>, 118 WithNonTrivialDtor<256>>; 119 types::for_each(TrickyCookieTypes(), []<class T> { 120 // Array allocated with `new T[n]`, default deleter 121 { 122 std::unique_ptr<T[], std::default_delete<T[]>> p(new T[3]); 123 assert(p[0] == T()); 124 assert(p[1] == T()); 125 assert(p[2] == T()); 126 } 127 128 // Array allocated with `new T[n]`, custom deleter 129 { 130 std::unique_ptr<T[], CustomDeleter<T[]>> p(new T[3]); 131 assert(p[0] == T()); 132 assert(p[1] == T()); 133 assert(p[2] == T()); 134 } 135 136 // Array not allocated with `new T[n]`, custom deleter 137 // 138 // This test aims to ensure that the implementation doesn't try to use an array cookie 139 // when there is none. 140 { 141 T array[50] = {}; 142 std::unique_ptr<T[], NoopDeleter> p(&array[0]); 143 assert(p[0] == T()); 144 assert(p[1] == T()); 145 assert(p[2] == T()); 146 } 147 }); 148 } 149 #endif // C++20 150 151 return true; 152 } 153 154 int main(int, char**) { 155 test(); 156 #if TEST_STD_VER >= 23 157 static_assert(test()); 158 #endif 159 160 return 0; 161 } 162