162 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// <memory>10 11// unique_ptr12 13// T& unique_ptr::operator[](size_t) const14 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 23static int next = 0;24struct EnumeratedDefaultCtor {25 EnumeratedDefaultCtor() : value(0) { value = ++next; }26 int value;27};28 29template <std::size_t Size>30struct 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 37template <std::size_t Size>38struct 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 46template <class T>47struct CustomDeleter : std::default_delete<T> {};48 49struct NoopDeleter {50 template <class T>51 TEST_CONSTEXPR_CXX23 void operator()(T*) const {}52};53 54TEST_CONSTEXPR_CXX23 bool test() {55 // Basic test56 {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 but77 // before actually modifying any of its elements. The implementation would have to78 // 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-qualified92 {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 different99 // sizes. This is relevant because some implementations may want to use properties of the100 // ABI like array cookies and these properties often depend on e.g. the triviality of T's101 // destructor, T's size and so on.102#if TEST_STD_VER >= 20 // this test is too painful to write before C++20103 {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 deleter121 {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 deleter129 {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 deleter137 //138 // This test aims to ensure that the implementation doesn't try to use an array cookie139 // 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++20150 151 return true;152}153 154int main(int, char**) {155 test();156#if TEST_STD_VER >= 23157 static_assert(test());158#endif159 160 return 0;161}162