[libc++] Value-initialize unique_ptr's deleter_type

According to the C++ standard, the stored pointer and the stored deleter
should be value-initialized.

Differential Revision: https://reviews.llvm.org/D113612
This commit is contained in:
Johan Berg 2021-11-24 17:30:50 -05:00 committed by Louis Dionne
parent 95875d246a
commit 68e2231f87
5 changed files with 45 additions and 7 deletions

View File

@ -174,17 +174,17 @@ public:
template <bool _Dummy = true,
class = _EnableIfDeleterDefaultConstructible<_Dummy> >
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(pointer(), __default_init_tag()) {}
_LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(__value_init_tag(), __value_init_tag()) {}
template <bool _Dummy = true,
class = _EnableIfDeleterDefaultConstructible<_Dummy> >
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(pointer(), __default_init_tag()) {}
_LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(__value_init_tag(), __value_init_tag()) {}
template <bool _Dummy = true,
class = _EnableIfDeleterDefaultConstructible<_Dummy> >
_LIBCPP_INLINE_VISIBILITY
explicit unique_ptr(pointer __p) _NOEXCEPT : __ptr_(__p, __default_init_tag()) {}
explicit unique_ptr(pointer __p) _NOEXCEPT : __ptr_(__p, __value_init_tag()) {}
template <bool _Dummy = true,
class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > >
@ -226,7 +226,7 @@ public:
typename enable_if<is_convertible<_Up*, _Tp*>::value &&
is_same<_Dp, default_delete<_Tp> >::value,
__nat>::type = __nat()) _NOEXCEPT
: __ptr_(__p.release(), __default_init_tag()) {}
: __ptr_(__p.release(), __value_init_tag()) {}
#endif
_LIBCPP_INLINE_VISIBILITY
@ -397,19 +397,19 @@ public:
template <bool _Dummy = true,
class = _EnableIfDeleterDefaultConstructible<_Dummy> >
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(pointer(), __default_init_tag()) {}
_LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(__value_init_tag(), __value_init_tag()) {}
template <bool _Dummy = true,
class = _EnableIfDeleterDefaultConstructible<_Dummy> >
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(pointer(), __default_init_tag()) {}
_LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(__value_init_tag(), __value_init_tag()) {}
template <class _Pp, bool _Dummy = true,
class = _EnableIfDeleterDefaultConstructible<_Dummy>,
class = _EnableIfPointerConvertible<_Pp> >
_LIBCPP_INLINE_VISIBILITY
explicit unique_ptr(_Pp __p) _NOEXCEPT
: __ptr_(__p, __default_init_tag()) {}
: __ptr_(__p, __value_init_tag()) {}
template <class _Pp, bool _Dummy = true,
class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> >,

View File

@ -84,6 +84,11 @@ void test_basic() {
p.get_deleter().set_state(5);
assert(p.get_deleter().state() == 5);
}
{
std::unique_ptr<ElemType, DefaultCtorDeleter<ElemType> > p;
assert(p.get() == 0);
assert(p.get_deleter().state() == 0);
}
}
DEFINE_AND_RUN_IS_INCOMPLETE_TEST({

View File

@ -53,6 +53,11 @@ void test_basic() {
assert(p.get() == 0);
assert(p.get_deleter().state() == 0);
}
{
std::unique_ptr<VT, DefaultCtorDeleter<VT> > p(nullptr);
assert(p.get() == 0);
assert(p.get_deleter().state() == 0);
}
}
template <class VT>

View File

@ -69,6 +69,14 @@ void test_pointer() {
assert(s.get_deleter().state() == 0);
}
assert(A::count == 0);
{
A* p = newValue<ValueT>(expect_alive);
assert(A::count == expect_alive);
std::unique_ptr<ValueT, DefaultCtorDeleter<ValueT> > s(p);
assert(s.get() == p);
assert(s.get_deleter().state() == 0);
}
assert(A::count == 0);
}
void test_derived() {

View File

@ -442,4 +442,24 @@ private:
#endif // TEST_STD_VER >= 11
template <class T>
class DefaultCtorDeleter
{
int state_;
public:
int state() const {return state_;}
void operator()(T* p) {delete p;}
};
template <class T>
class DefaultCtorDeleter<T[]>
{
int state_;
public:
int state() const {return state_;}
void operator()(T* p) {delete [] p;}
};
#endif // SUPPORT_DELETER_TYPES_H