Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx20Issues.csv
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
"`LWG3180 <https://wg21.link/LWG3180>`__","Inconsistently named return type for ``ranges::minmax_element``\ ","2019-02 (Kona)","|Complete|","15","`#103844 <https://github.com/llvm/llvm-project/issues/103844>`__",""
"`LWG3182 <https://wg21.link/LWG3182>`__","Specification of ``Same``\ could be clearer","2019-02 (Kona)","|Complete|","15","`#103845 <https://github.com/llvm/llvm-project/issues/103845>`__",""
"","","","","","",""
"`LWG2899 <https://wg21.link/LWG2899>`__","``is_(nothrow_)move_constructible``\ and ``tuple``\ , ``optional``\ and ``unique_ptr``\ ","2019-07 (Cologne)","","","`#100255 <https://github.com/llvm/llvm-project/issues/100255>`__",""
"`LWG2899 <https://wg21.link/LWG2899>`__","``is_(nothrow_)move_constructible``\ and ``tuple``\ , ``optional``\ and ``unique_ptr``\ ","2019-07 (Cologne)","|Complete|","22","`#100255 <https://github.com/llvm/llvm-project/issues/100255>`__",""
"`LWG3055 <https://wg21.link/LWG3055>`__","``path::operator+=(*single-character*)``\ misspecified","2019-07 (Cologne)","|Complete|","7","`#103846 <https://github.com/llvm/llvm-project/issues/103846>`__",""
"`LWG3158 <https://wg21.link/LWG3158>`__","``tuple(allocator_arg_t, const Alloc&)``\ should be conditionally explicit","2019-07 (Cologne)","|Complete|","10","`#103847 <https://github.com/llvm/llvm-project/issues/103847>`__",""
"`LWG3169 <https://wg21.link/LWG3169>`__","``ranges``\ permutation generators discard useful information","2019-07 (Cologne)","|Complete|","15","`#103848 <https://github.com/llvm/llvm-project/issues/103848>`__",""
Expand Down
17 changes: 9 additions & 8 deletions libcxx/include/__memory/unique_ptr.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include <__type_traits/is_trivially_relocatable.h>
#include <__type_traits/is_unbounded_array.h>
#include <__type_traits/is_void.h>
#include <__type_traits/nat.h>
#include <__type_traits/remove_extent.h>
#include <__type_traits/type_identity.h>
#include <__utility/declval.h>
Expand Down Expand Up @@ -208,7 +209,8 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI unique_ptr {
template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> > >
_LIBCPP_HIDE_FROM_ABI unique_ptr(pointer __p, _BadRValRefType<_Dummy> __d) = delete;

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr&& __u) _NOEXCEPT
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23
unique_ptr(_If<is_move_constructible<_Dp>::value, unique_ptr&&, __nat> __u) _NOEXCEPT
: __ptr_(__u.release()),
__deleter_(std::forward<deleter_type>(__u.get_deleter())) {}

Expand All @@ -226,7 +228,8 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI unique_ptr {
_LIBCPP_HIDE_FROM_ABI unique_ptr(auto_ptr<_Up>&& __p) _NOEXCEPT : __ptr_(__p.release()), __deleter_() {}
#endif

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT {
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr&
operator=(_If<is_move_assignable<_Dp>::value, unique_ptr&&, __nat> __u) _NOEXCEPT {
reset(__u.release());
__deleter_ = std::forward<deleter_type>(__u.get_deleter());
return *this;
Expand All @@ -251,10 +254,8 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI unique_ptr {
}
#endif

#ifdef _LIBCPP_CXX03_LANG
unique_ptr(unique_ptr const&) = delete;
unique_ptr& operator=(unique_ptr const&) = delete;
#endif

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 ~unique_ptr() { reset(); }

Expand Down Expand Up @@ -532,12 +533,14 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI unique_ptr<_Tp[], _Dp> {
class = _EnableIfPointerConvertible<_Pp> >
_LIBCPP_HIDE_FROM_ABI unique_ptr(_Pp __ptr, _BadRValRefType<_Dummy> __deleter) = delete;

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr&& __u) _NOEXCEPT
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23
unique_ptr(_If<is_move_constructible<_Dp>::value, unique_ptr&&, __nat> __u) _NOEXCEPT
: __ptr_(__u.release()),
__deleter_(std::forward<deleter_type>(__u.get_deleter())),
__checker_(std::move(__u.__checker_)) {}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT {
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr&
operator=(_If<is_move_assignable<_Dp>::value, unique_ptr&&, __nat> __u) _NOEXCEPT {
reset(__u.release());
__deleter_ = std::forward<deleter_type>(__u.get_deleter());
__checker_ = std::move(__u.__checker_);
Expand All @@ -564,10 +567,8 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI unique_ptr<_Tp[], _Dp> {
return *this;
}

#ifdef _LIBCPP_CXX03_LANG
unique_ptr(unique_ptr const&) = delete;
unique_ptr& operator=(unique_ptr const&) = delete;
#endif

public:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 ~unique_ptr() { reset(); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,19 +112,26 @@ TEST_CONSTEXPR_CXX23 void test_sfinae() {
static_assert(!std::is_assignable<U, const U&&>::value, "");
static_assert(std::is_nothrow_assignable<U, U&&>::value, "");
}
{
typedef std::unique_ptr<VT, NCDeleter<VT> > U;
static_assert(!std::is_assignable<U, U&>::value, "");
static_assert(!std::is_assignable<U, const U&>::value, "");
static_assert(!std::is_assignable<U, const U&&>::value, "");
static_assert(!std::is_assignable<U, U&&>::value, "");
}
{
typedef std::unique_ptr<VT, NCDeleter<VT>&> U;
static_assert(!std::is_assignable<U, U&>::value, "");
static_assert(!std::is_assignable<U, const U&>::value, "");
static_assert(!std::is_assignable<U, const U&&>::value, "");
static_assert(std::is_nothrow_assignable<U, U&&>::value, "");
static_assert(!std::is_assignable<U, U&&>::value, "");
}
{
typedef std::unique_ptr<VT, const NCDeleter<VT>&> U;
static_assert(!std::is_assignable<U, U&>::value, "");
static_assert(!std::is_assignable<U, const U&>::value, "");
static_assert(!std::is_assignable<U, const U&&>::value, "");
static_assert(std::is_nothrow_assignable<U, U&&>::value, "");
static_assert(!std::is_assignable<U, U&&>::value, "");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ TEST_CONSTEXPR_CXX23 void test_sfinae() {
static_assert(!std::is_assignable<U1, U5&&>::value, "");

using U1C = std::unique_ptr<const VT, GenericConvertingDeleter<0> const&>;
static_assert(std::is_nothrow_assignable<U1C, U1&&>::value, "");
static_assert(!std::is_assignable<U1C, U1&&>::value, "");
}
{ // Test that if the deleter assignment is not valid the assignment operator
// SFINAEs.
Expand Down Expand Up @@ -296,12 +296,12 @@ TEST_CONSTEXPR_CXX23 void test_noexcept() {
{
typedef std::unique_ptr<const VT, NCDeleter<const VT>&> APtr;
typedef std::unique_ptr<VT, NCDeleter<const VT>&> BPtr;
static_assert(std::is_nothrow_assignable<APtr, BPtr>::value, "");
static_assert(!std::is_assignable<APtr, BPtr>::value, "");
}
{
typedef std::unique_ptr<const VT, const NCConstDeleter<const VT>&> APtr;
typedef std::unique_ptr<VT, const NCConstDeleter<const VT>&> BPtr;
static_assert(std::is_nothrow_assignable<APtr, BPtr>::value, "");
static_assert(!std::is_assignable<APtr, BPtr>::value, "");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ void test_sfinae() {
static_assert(!std::is_assignable<UAC, const UA&>::value, "");
}
{ // cannot move if the deleter-types cannot convert
static_assert(std::is_assignable<UACD, UAD&&>::value, "");
static_assert(!std::is_assignable<UACD, UAD&&>::value, "");
static_assert(!std::is_assignable<UACD, UAC&&>::value, "");
static_assert(!std::is_assignable<UAC, UACD&&>::value, "");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ TEST_CONSTEXPR_CXX23 void test_sfinae() {
static_assert(!std::is_assignable<UA, const UB&>::value, "");
}
{ // cannot move if the deleter-types cannot convert
static_assert(std::is_assignable<UAD, UBD&&>::value, "");
static_assert(!std::is_assignable<UAD, UBD&&>::value, "");
static_assert(!std::is_assignable<UAD, UB&&>::value, "");
static_assert(!std::is_assignable<UA, UBD&&>::value, "");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

// Test unique_ptr move ctor

// XFAIL: FROZEN-CXX03-HEADERS-FIXME

#include <memory>
#include <utility>
#include <cassert>
Expand All @@ -24,10 +26,8 @@
//
// Concerns
// 1 The moved from pointer is empty and the new pointer stores the old value.
// 2 The only requirement on the deleter is that it is MoveConstructible
// or a reference.
// 3 The constructor works for explicitly moved values (i.e. std::move(x))
// 4 The constructor works for true temporaries (e.g. a return value)
// 2 The constructor works for explicitly moved values (i.e. std::move(x))
// 3 The constructor works for true temporaries (e.g. a return value)
//
// Plan
// 1 Explicitly construct unique_ptr<T, D> for various deleter types 'D'.
Expand Down Expand Up @@ -73,10 +73,22 @@ void sink3(std::unique_ptr<VT, NCDeleter<VT>&> p) {

template <class ValueT>
TEST_CONSTEXPR_CXX23 void test_sfinae() {
typedef std::unique_ptr<ValueT> U;
{ // Ensure unique_ptr is non-copyable
// Ensure that
// - unique_ptr is non-copyable, and
// - unique_ptr's move-constructibility is correctly propagated from its deleter's.
{
typedef std::unique_ptr<ValueT> U;
static_assert((!std::is_constructible<U, U const&>::value), "");
static_assert((!std::is_constructible<U, U&>::value), "");
static_assert(std::is_move_constructible<U>::value, "");
static_assert(!std::is_constructible<U, const U>::value, "");
}
{
typedef std::unique_ptr<ValueT, NCDeleter<ValueT> > U;
static_assert(!std::is_constructible<U, U const&>::value, "");
static_assert(!std::is_constructible<U, U&>::value, "");
static_assert(!std::is_move_constructible<U>::value, "");
static_assert(!std::is_constructible<U, const U>::value, "");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,19 @@ struct move_only_large final {
int value;
};

// a non-movable type
struct nonmovable {
nonmovable(const nonmovable&) = default;
nonmovable(nonmovable&&) = delete;
};

// a non-movable type with a usable copy constructor
// verifying that tuple's move constructor is not confused to select that copy constructor
struct nonmovable_with_copy_ctor {
nonmovable_with_copy_ctor(const nonmovable_with_copy_ctor&) = default;
nonmovable_with_copy_ctor(nonmovable_with_copy_ctor&&) = delete;
};

template <class Elem>
void test_sfinae() {
using Tup = std::tuple<Elem>;
Expand Down Expand Up @@ -123,6 +136,18 @@ int main(int, char**)
test_sfinae<move_only_ebo>();
test_sfinae<move_only_large>();
}
// non-movable types
{
using Alloc = std::allocator<int>;
using Tag = std::allocator_arg_t;

static_assert(!std::is_move_constructible<nonmovable>::value, "");
static_assert(!std::is_constructible<nonmovable, Tag, Alloc, nonmovable>::value, "");

static_assert(!std::is_move_constructible<nonmovable_with_copy_ctor>::value, "");
static_assert(
!std::is_constructible<nonmovable_with_copy_ctor, Tag, Alloc, nonmovable_with_copy_ctor>::value, "");
}

return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ void test_bad_index() {
void test_bad_return_type() {
typedef std::unique_ptr<int> upint;
std::tuple<upint> t;
upint p = std::get<upint>(t); // expected-error{{deleted copy constructor}}
upint p = std::get<upint>(t); // expected-error{{deleted constructor}}
}

void f() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@
void f() {
typedef std::unique_ptr<int> Ptr;
std::pair<Ptr, int> t(Ptr(new int(4)), 23);
Ptr p = std::get<Ptr>(t); // expected-error {{call to implicitly-deleted copy constructor of 'Ptr'}}
Ptr p = std::get<Ptr>(t); // expected-error {{call to deleted constructor of 'Ptr'}}
}
Loading