211 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//=============================================================================14// TESTING std::unique_ptr::unique_ptr(pointer)15//16// Concerns:17// 1 The pointer constructor works for any default constructible deleter types.18// 2 The pointer constructor accepts pointers to derived types.19// 2 The stored type 'T' is allowed to be incomplete.20//21// Plan22// 1 Construct unique_ptr<T, D>'s with a pointer to 'T' and various deleter23// types (C-1)24// 2 Construct unique_ptr<T, D>'s with a pointer to 'D' and various deleter25// types where 'D' is derived from 'T'. (C-1,2)26// 3 Construct a unique_ptr<T, D> with a pointer to 'T' and various deleter27// types where 'T' is an incomplete type (C-1,3)28 29// Test unique_ptr(pointer) ctor30 31#include <memory>32#include <cassert>33 34#include "test_macros.h"35#include "unique_ptr_test_helper.h"36 37// unique_ptr(pointer) ctor should only require default Deleter ctor38 39template <bool IsArray>40TEST_CONSTEXPR_CXX23 void test_pointer() {41 typedef typename std::conditional<!IsArray, A, A[]>::type ValueT;42 const int expect_alive = IsArray ? 5 : 1;43#if TEST_STD_VER >= 1144 {45 using U1 = std::unique_ptr<ValueT>;46 using U2 = std::unique_ptr<ValueT, Deleter<ValueT> >;47 48 // Test for noexcept49 static_assert(std::is_nothrow_constructible<U1, A*>::value, "");50 static_assert(std::is_nothrow_constructible<U2, A*>::value, "");51 52 // Test for explicit53 static_assert(!std::is_convertible<A*, U1>::value, "");54 static_assert(!std::is_convertible<A*, U2>::value, "");55 }56#endif57 {58 A* p = newValue<ValueT>(expect_alive);59 if (!TEST_IS_CONSTANT_EVALUATED)60 assert(A::count == expect_alive);61 62 std::unique_ptr<ValueT> s(p);63 assert(s.get() == p);64 }65 if (!TEST_IS_CONSTANT_EVALUATED)66 assert(A::count == 0);67 {68 A* p = newValue<ValueT>(expect_alive);69 if (!TEST_IS_CONSTANT_EVALUATED)70 assert(A::count == expect_alive);71 72 std::unique_ptr<ValueT, NCDeleter<ValueT> > s(p);73 assert(s.get() == p);74 assert(s.get_deleter().state() == 0);75 }76 if (!TEST_IS_CONSTANT_EVALUATED)77 assert(A::count == 0);78// TODO: Remove this check once https://llvm.org/PR154567 is fixed79#if TEST_STD_VER >= 23 && defined(TEST_COMPILER_CLANG)80 if (!TEST_IS_CONSTANT_EVALUATED)81#endif82 {83 A* p = newValue<ValueT>(expect_alive);84 if (!TEST_IS_CONSTANT_EVALUATED)85 assert(A::count == expect_alive);86 87 std::unique_ptr<ValueT, DefaultCtorDeleter<ValueT> > s(p);88 assert(s.get() == p);89 assert(s.get_deleter().state() == 0);90 }91 if (!TEST_IS_CONSTANT_EVALUATED)92 assert(A::count == 0);93}94 95TEST_CONSTEXPR_CXX23 void test_derived() {96 {97 B* p = new B;98 if (!TEST_IS_CONSTANT_EVALUATED) {99 assert(A::count == 1);100 assert(B::count == 1);101 }102 std::unique_ptr<A> s(p);103 assert(s.get() == p);104 }105 if (!TEST_IS_CONSTANT_EVALUATED) {106 assert(A::count == 0);107 assert(B::count == 0);108 }109 {110 B* p = new B;111 if (!TEST_IS_CONSTANT_EVALUATED) {112 assert(A::count == 1);113 assert(B::count == 1);114 }115 std::unique_ptr<A, NCDeleter<A> > s(p);116 assert(s.get() == p);117 assert(s.get_deleter().state() == 0);118 }119 if (!TEST_IS_CONSTANT_EVALUATED) {120 assert(A::count == 0);121 assert(B::count == 0);122 }123}124 125#if TEST_STD_VER >= 11126struct NonDefaultDeleter {127 NonDefaultDeleter() = delete;128 void operator()(void*) const {}129};130 131struct GenericDeleter {132 void operator()(void*) const;133};134#endif135 136template <class T>137void TEST_CONSTEXPR_CXX23 test_sfinae() {138#if TEST_STD_VER >= 11139 { // the constructor does not participate in overload resolution when140 // the deleter is a pointer type141 using U = std::unique_ptr<T, void (*)(void*)>;142 static_assert(!std::is_constructible<U, T*>::value, "");143 }144 { // the constructor does not participate in overload resolution when145 // the deleter is not default constructible146 using Del = CDeleter<T>;147 using U1 = std::unique_ptr<T, NonDefaultDeleter>;148 using U2 = std::unique_ptr<T, Del&>;149 using U3 = std::unique_ptr<T, Del const&>;150 static_assert(!std::is_constructible<U1, T*>::value, "");151 static_assert(!std::is_constructible<U2, T*>::value, "");152 static_assert(!std::is_constructible<U3, T*>::value, "");153 }154#endif155}156 157static TEST_CONSTEXPR_CXX23 void test_sfinae_runtime() {158#if TEST_STD_VER >= 11159 { // the constructor does not participate in overload resolution when160 // a base <-> derived conversion would occur.161 using UA = std::unique_ptr<A[]>;162 using UAD = std::unique_ptr<A[], GenericDeleter>;163 using UAC = std::unique_ptr<const A[]>;164 using UB = std::unique_ptr<B[]>;165 using UBD = std::unique_ptr<B[], GenericDeleter>;166 using UBC = std::unique_ptr<const B[]>;167 168 static_assert(!std::is_constructible<UA, B*>::value, "");169 static_assert(!std::is_constructible<UB, A*>::value, "");170 static_assert(!std::is_constructible<UAD, B*>::value, "");171 static_assert(!std::is_constructible<UBD, A*>::value, "");172 static_assert(!std::is_constructible<UAC, const B*>::value, "");173 static_assert(!std::is_constructible<UBC, const A*>::value, "");174 }175#endif176}177 178DEFINE_AND_RUN_IS_INCOMPLETE_TEST({179 { doIncompleteTypeTest(1, getNewIncomplete()); }180 checkNumIncompleteTypeAlive(0);181 {182 doIncompleteTypeTest<IncompleteType, NCDeleter<IncompleteType> >(183 1, getNewIncomplete());184 }185 checkNumIncompleteTypeAlive(0);186})187 188TEST_CONSTEXPR_CXX23 bool test() {189 {190 test_pointer</*IsArray*/ false>();191 test_derived();192 test_sfinae<int>();193 }194 {195 test_pointer</*IsArray*/ true>();196 test_sfinae<int[]>();197 test_sfinae_runtime();198 }199 200 return true;201}202 203int main(int, char**) {204 test();205#if TEST_STD_VER >= 23206 static_assert(test());207#endif208 209 return 0;210}211