[libcxx] r300406 - Overhaul unique_ptr - Implement LWG 2801, 2905, 2520.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Sat Apr 15 18:51:04 PDT 2017


Author: ericwf
Date: Sat Apr 15 20:51:04 2017
New Revision: 300406

URL: http://llvm.org/viewvc/llvm-project?rev=300406&view=rev
Log:
Overhaul unique_ptr - Implement LWG 2801, 2905, 2520.

This patch overhauls both specializations of unique_ptr while implementing
the following LWG issues:

* LWG 2801 - This issue constrains unique_ptr's constructors when the deleter type
  is not default constructible. Additionally it adds SFINAE conditions
  to unique_ptr<T[]>::unique_ptr(Up).

* LWG 2905 - This issue reworks the unique_ptr(pointer, /* see below */ deleter)
  constructors so that they correctly SFINAE when the deleter argument cannot
  be used to construct the stored deleter.

* LWG 2520 - This issue fixes initializing unique_ptr<T[]> from nullptr.
  Libc++ had previously implemented this issue, but the suggested resolution
  still broke initialization from NULL. This patch re-works the
  unique_ptr<T[]>(Up, deleter) overloads so that they accept NULL as well
  as nullptr.

Added:
    libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.pass.cpp
    libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.pass.cpp
Modified:
    libcxx/trunk/include/memory
    libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move.pass.cpp
    libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/default.pass.cpp
    libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move.pass.cpp
    libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.runtime.pass.cpp
    libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.single.pass.cpp
    libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/nullptr.pass.cpp
    libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer.pass.cpp
    libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer_deleter.fail.cpp
    libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer_deleter.pass.cpp
    libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.dtor/null.pass.cpp
    libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.modifiers/release.pass.cpp
    libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.modifiers/reset.pass.cpp
    libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.modifiers/swap.pass.cpp
    libcxx/trunk/test/support/deleter_types.h
    libcxx/trunk/test/support/test_workarounds.h
    libcxx/trunk/www/cxx1z_status.html

Modified: libcxx/trunk/include/memory
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=300406&r1=300405&r2=300406&view=diff
==============================================================================
--- libcxx/trunk/include/memory (original)
+++ libcxx/trunk/include/memory Sat Apr 15 20:51:04 2017
@@ -2313,412 +2313,587 @@ public:
         }
 };
 
+
+#ifndef _LIBCPP_CXX03_LANG
+template <class _Deleter>
+struct __unique_ptr_deleter_sfinae {
+  static_assert(!is_reference<_Deleter>::value, "incorrect specialization");
+  typedef const _Deleter& __lval_ref_type;
+  typedef _Deleter&& __good_rval_ref_type;
+  typedef true_type __enable_rval_overload;
+};
+
+template <class _Deleter>
+struct __unique_ptr_deleter_sfinae<_Deleter const&> {
+  typedef const _Deleter& __lval_ref_type;
+  typedef const _Deleter&& __bad_rval_ref_type;
+  typedef false_type __enable_rval_overload;
+};
+
+template <class _Deleter>
+struct __unique_ptr_deleter_sfinae<_Deleter&> {
+  typedef _Deleter& __lval_ref_type;
+  typedef _Deleter&& __bad_rval_ref_type;
+  typedef false_type __enable_rval_overload;
+};
+#endif // !defined(_LIBCPP_CXX03_LANG)
+
 template <class _Tp, class _Dp = default_delete<_Tp> >
-class _LIBCPP_TEMPLATE_VIS unique_ptr
-{
+class _LIBCPP_TEMPLATE_VIS unique_ptr {
 public:
-    typedef _Tp element_type;
-    typedef _Dp deleter_type;
-    typedef typename __pointer_type<_Tp, deleter_type>::type pointer;
+  typedef _Tp element_type;
+  typedef _Dp deleter_type;
+  typedef typename __pointer_type<_Tp, deleter_type>::type pointer;
+
+  static_assert(!is_rvalue_reference<deleter_type>::value,
+                "the specified deleter type cannot be an rvalue reference");
+
 private:
-    __compressed_pair<pointer, deleter_type> __ptr_;
+  __compressed_pair<pointer, deleter_type> __ptr_;
 
-#ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    unique_ptr(unique_ptr&);
-    template <class _Up, class _Ep>
-        unique_ptr(unique_ptr<_Up, _Ep>&);
-    unique_ptr& operator=(unique_ptr&);
-    template <class _Up, class _Ep>
-        unique_ptr& operator=(unique_ptr<_Up, _Ep>&);
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
-
-    struct __nat {int __for_bool_;};
-
-    typedef typename remove_reference<deleter_type>::type& _Dp_reference;
-    typedef typename remove_reference<typename add_const<deleter_type>::type>::type&
-        _Dp_const_reference;
-public:
-    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT
-        : __ptr_(pointer())
-        {
-            static_assert(!is_pointer<deleter_type>::value,
-                "unique_ptr constructed with null function pointer deleter");
-        }
-    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT
-        : __ptr_(pointer())
-        {
-            static_assert(!is_pointer<deleter_type>::value,
-                "unique_ptr constructed with null function pointer deleter");
-        }
-    _LIBCPP_INLINE_VISIBILITY explicit unique_ptr(pointer __p) _NOEXCEPT
-        : __ptr_(_VSTD::move(__p))
-        {
-            static_assert(!is_pointer<deleter_type>::value,
-                "unique_ptr constructed with null function pointer deleter");
-        }
+  struct __nat { int __for_bool_; };
 
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    _LIBCPP_INLINE_VISIBILITY unique_ptr(pointer __p, typename conditional<
-                                        is_reference<deleter_type>::value,
-                                        deleter_type,
-                                        typename add_lvalue_reference<const deleter_type>::type>::type __d)
-             _NOEXCEPT
-        : __ptr_(__p, __d) {}
-
-    _LIBCPP_INLINE_VISIBILITY unique_ptr(pointer __p, typename remove_reference<deleter_type>::type&& __d)
-             _NOEXCEPT
-        : __ptr_(__p, _VSTD::move(__d))
-        {
-            static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference");
-        }
-    _LIBCPP_INLINE_VISIBILITY unique_ptr(unique_ptr&& __u) _NOEXCEPT
-        : __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) {}
-    template <class _Up, class _Ep>
-        _LIBCPP_INLINE_VISIBILITY
-        unique_ptr(unique_ptr<_Up, _Ep>&& __u,
-                   typename enable_if
-                      <
-                        !is_array<_Up>::value &&
-                         is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>::value &&
-                         is_convertible<_Ep, deleter_type>::value &&
-                         (
-                            !is_reference<deleter_type>::value ||
-                            is_same<deleter_type, _Ep>::value
-                         ),
-                         __nat
-                      >::type = __nat()) _NOEXCEPT
-            : __ptr_(__u.release(), _VSTD::forward<_Ep>(__u.get_deleter())) {}
+#ifndef _LIBCPP_CXX03_LANG
+  typedef __unique_ptr_deleter_sfinae<_Dp> _SFINAE;
+
+  template <bool _Dummy>
+  using _LValRefType =
+      typename __dependent_type<_SFINAE, _Dummy>::__lval_ref_type;
+
+  template <bool _Dummy>
+  using _GoodRValRefType =
+      typename __dependent_type<_SFINAE, _Dummy>::__good_rval_ref_type;
+
+  template <bool _Dummy>
+  using _BadRValRefType =
+      typename __dependent_type<_SFINAE, _Dummy>::__bad_rval_ref_type;
+
+  template <bool _Dummy, class _Deleter = typename __dependent_type<
+                             __identity<deleter_type>, _Dummy>::type>
+  using _EnableIfDeleterDefaultConstructible =
+      typename enable_if<is_default_constructible<_Deleter>::value &&
+                         !is_pointer<_Deleter>::value>::type;
+
+  template <class _ArgType>
+  using _EnableIfDeleterConstructible =
+      typename enable_if<is_constructible<deleter_type, _ArgType>::value>::type;
+
+  template <class _UPtr, class _Up>
+  using _EnableIfMoveConvertible = typename enable_if<
+      is_convertible<typename _UPtr::pointer, pointer>::value &&
+      !is_array<_Up>::value
+  >::type;
+
+  template <class _UDel>
+  using _EnableIfDeleterConvertible = typename enable_if<
+      (is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) ||
+      (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value)
+    >::type;
+
+  template <class _UDel>
+  using _EnableIfDeleterAssignable = typename enable_if<
+      is_assignable<_Dp&, _UDel&&>::value
+    >::type;
+
+public:
+  template <bool _Dummy = true,
+            class = _EnableIfDeleterDefaultConstructible<_Dummy>>
+  _LIBCPP_INLINE_VISIBILITY
+  constexpr unique_ptr() noexcept : __ptr_(pointer()) {}
+
+  template <bool _Dummy = true,
+            class = _EnableIfDeleterDefaultConstructible<_Dummy>>
+  _LIBCPP_INLINE_VISIBILITY
+  constexpr unique_ptr(nullptr_t) noexcept : __ptr_(pointer()) {}
+
+  template <bool _Dummy = true,
+            class = _EnableIfDeleterDefaultConstructible<_Dummy>>
+  _LIBCPP_INLINE_VISIBILITY
+  explicit unique_ptr(pointer __p) noexcept : __ptr_(__p) {}
+
+  template <bool _Dummy = true,
+            class = _EnableIfDeleterConstructible<_LValRefType<_Dummy>>>
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(pointer __p, _LValRefType<_Dummy> __d) noexcept
+      : __ptr_(__p, __d) {}
+
+  template <bool _Dummy = true,
+            class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy>>>
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(pointer __p, _GoodRValRefType<_Dummy> __d) noexcept
+      : __ptr_(__p, _VSTD::move(__d)) {
+    static_assert(!is_reference<deleter_type>::value,
+                  "rvalue deleter bound to reference");
+  }
+
+  template <bool _Dummy = true,
+            class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy>>>
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(pointer __p, _BadRValRefType<_Dummy> __d) = delete;
+
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(unique_ptr&& __u) noexcept
+      : __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) {
+  }
+
+  template <class _Up, class _Ep,
+      class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>,
+      class = _EnableIfDeleterConvertible<_Ep>
+  >
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT
+      : __ptr_(__u.release(), _VSTD::forward<_Ep>(__u.get_deleter())) {}
 
 #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
-    template <class _Up>
-        _LIBCPP_INLINE_VISIBILITY unique_ptr(auto_ptr<_Up>&& __p,
-                typename enable_if<
-                                      is_convertible<_Up*, _Tp*>::value &&
-                                      is_same<_Dp, default_delete<_Tp> >::value,
-                                      __nat
-                                  >::type = __nat()) _NOEXCEPT
-            : __ptr_(__p.release())
-            {
-            }
+  template <class _Up>
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(auto_ptr<_Up>&& __p,
+             typename enable_if<is_convertible<_Up*, _Tp*>::value &&
+                                    is_same<_Dp, default_delete<_Tp>>::value,
+                                __nat>::type = __nat()) _NOEXCEPT
+      : __ptr_(__p.release()) {}
 #endif
 
-        _LIBCPP_INLINE_VISIBILITY unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT
-            {
-                reset(__u.release());
-                __ptr_.second() = _VSTD::forward<deleter_type>(__u.get_deleter());
-                return *this;
-            }
-
-        template <class _Up, class _Ep>
-            _LIBCPP_INLINE_VISIBILITY
-            typename enable_if
-            <
-                !is_array<_Up>::value &&
-                is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>::value &&
-                is_assignable<deleter_type&, _Ep&&>::value,
-                unique_ptr&
-            >::type
-            operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT
-            {
-                reset(__u.release());
-                __ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter());
-                return *this;
-            }
-#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
-
-    _LIBCPP_INLINE_VISIBILITY operator __rv<unique_ptr>()
-    {
-        return __rv<unique_ptr>(*this);
-    }
-
-    _LIBCPP_INLINE_VISIBILITY unique_ptr(__rv<unique_ptr> __u)
-        : __ptr_(__u->release(), _VSTD::forward<deleter_type>(__u->get_deleter())) {}
-
-    template <class _Up, class _Ep>
-    _LIBCPP_INLINE_VISIBILITY
-    typename enable_if<
-        !is_array<_Up>::value &&
-        is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>::value &&
-        is_assignable<deleter_type&, _Ep&>::value,
-        unique_ptr&
-    >::type
-    operator=(unique_ptr<_Up, _Ep> __u)
-    {
-        reset(__u.release());
-        __ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter());
-        return *this;
-    }
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT {
+    reset(__u.release());
+    __ptr_.second() = _VSTD::forward<deleter_type>(__u.get_deleter());
+    return *this;
+  }
+
+  template <class _Up, class _Ep,
+      class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>,
+      class = _EnableIfDeleterAssignable<_Ep>
+  >
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT {
+    reset(__u.release());
+    __ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter());
+    return *this;
+  }
+
+#else  // _LIBCPP_CXX03_LANG
+private:
+  unique_ptr(unique_ptr&);
+  template <class _Up, class _Ep> unique_ptr(unique_ptr<_Up, _Ep>&);
 
-    _LIBCPP_INLINE_VISIBILITY unique_ptr(pointer __p, deleter_type __d)
-        : __ptr_(_VSTD::move(__p), _VSTD::move(__d)) {}
+  unique_ptr& operator=(unique_ptr&);
+  template <class _Up, class _Ep> unique_ptr& operator=(unique_ptr<_Up, _Ep>&);
+
+public:
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr() : __ptr_(pointer())
+  {
+    static_assert(!is_pointer<deleter_type>::value,
+                  "unique_ptr constructed with null function pointer deleter");
+    static_assert(is_default_constructible<deleter_type>::value,
+                  "unique_ptr::deleter_type is not default constructible");
+  }
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(nullptr_t) : __ptr_(pointer())
+  {
+    static_assert(!is_pointer<deleter_type>::value,
+                  "unique_ptr constructed with null function pointer deleter");
+  }
+  _LIBCPP_INLINE_VISIBILITY
+  explicit unique_ptr(pointer __p)
+      : __ptr_(_VSTD::move(__p)) {
+    static_assert(!is_pointer<deleter_type>::value,
+                  "unique_ptr constructed with null function pointer deleter");
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  operator __rv<unique_ptr>() {
+    return __rv<unique_ptr>(*this);
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(__rv<unique_ptr> __u)
+      : __ptr_(__u->release(),
+               _VSTD::forward<deleter_type>(__u->get_deleter())) {}
+
+  template <class _Up, class _Ep>
+  _LIBCPP_INLINE_VISIBILITY
+  typename enable_if<
+      !is_array<_Up>::value &&
+          is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
+                         pointer>::value &&
+          is_assignable<deleter_type&, _Ep&>::value,
+      unique_ptr&>::type
+  operator=(unique_ptr<_Up, _Ep> __u) {
+    reset(__u.release());
+    __ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter());
+    return *this;
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(pointer __p, deleter_type __d)
+      : __ptr_(_VSTD::move(__p), _VSTD::move(__d)) {}
+#endif // _LIBCPP_CXX03_LANG
 
 #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
-    template <class _Up>
-        _LIBCPP_INLINE_VISIBILITY
-                typename enable_if<
-                                      is_convertible<_Up*, _Tp*>::value &&
-                                      is_same<_Dp, default_delete<_Tp> >::value,
-                                      unique_ptr&
-                                  >::type
-        operator=(auto_ptr<_Up> __p)
-            {reset(__p.release()); return *this;}
+  template <class _Up>
+  _LIBCPP_INLINE_VISIBILITY
+      typename enable_if<is_convertible<_Up*, _Tp*>::value &&
+                             is_same<_Dp, default_delete<_Tp> >::value,
+                         unique_ptr&>::type
+      operator=(auto_ptr<_Up> __p) {
+    reset(__p.release());
+    return *this;
+  }
 #endif
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    _LIBCPP_INLINE_VISIBILITY ~unique_ptr() {reset();}
 
-    _LIBCPP_INLINE_VISIBILITY unique_ptr& operator=(nullptr_t) _NOEXCEPT
-    {
-        reset();
-        return *this;
-    }
-
-    _LIBCPP_INLINE_VISIBILITY typename add_lvalue_reference<_Tp>::type operator*() const
-        {return *__ptr_.first();}
-    _LIBCPP_INLINE_VISIBILITY pointer operator->() const _NOEXCEPT {return __ptr_.first();}
-    _LIBCPP_INLINE_VISIBILITY pointer get() const _NOEXCEPT {return __ptr_.first();}
-    _LIBCPP_INLINE_VISIBILITY       _Dp_reference get_deleter() _NOEXCEPT
-        {return __ptr_.second();}
-    _LIBCPP_INLINE_VISIBILITY _Dp_const_reference get_deleter() const _NOEXCEPT
-        {return __ptr_.second();}
-    _LIBCPP_INLINE_VISIBILITY
-        _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT
-        {return __ptr_.first() != nullptr;}
-
-    _LIBCPP_INLINE_VISIBILITY pointer release() _NOEXCEPT
-    {
-        pointer __t = __ptr_.first();
-        __ptr_.first() = pointer();
-        return __t;
-    }
-
-    _LIBCPP_INLINE_VISIBILITY void reset(pointer __p = pointer()) _NOEXCEPT
-    {
-        pointer __tmp = __ptr_.first();
-        __ptr_.first() = __p;
-        if (__tmp)
-            __ptr_.second()(__tmp);
-    }
+  _LIBCPP_INLINE_VISIBILITY
+  ~unique_ptr() { reset(); }
 
-    _LIBCPP_INLINE_VISIBILITY void swap(unique_ptr& __u) _NOEXCEPT
-        {__ptr_.swap(__u.__ptr_);}
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr& operator=(nullptr_t) _NOEXCEPT {
+    reset();
+    return *this;
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  typename add_lvalue_reference<_Tp>::type
+  operator*() const {
+    return *__ptr_.first();
+  }
+  _LIBCPP_INLINE_VISIBILITY
+  pointer operator->() const _NOEXCEPT {
+    return __ptr_.first();
+  }
+  _LIBCPP_INLINE_VISIBILITY
+  pointer get() const _NOEXCEPT {
+    return __ptr_.first();
+  }
+  _LIBCPP_INLINE_VISIBILITY
+  deleter_type& get_deleter() _NOEXCEPT {
+    return __ptr_.second();
+  }
+  _LIBCPP_INLINE_VISIBILITY
+  const deleter_type& get_deleter() const _NOEXCEPT {
+    return __ptr_.second();
+  }
+  _LIBCPP_INLINE_VISIBILITY
+  _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {
+    return __ptr_.first() != nullptr;
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  pointer release() _NOEXCEPT {
+    pointer __t = __ptr_.first();
+    __ptr_.first() = pointer();
+    return __t;
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  void reset(pointer __p = pointer()) _NOEXCEPT {
+    pointer __tmp = __ptr_.first();
+    __ptr_.first() = __p;
+    if (__tmp)
+      __ptr_.second()(__tmp);
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  void swap(unique_ptr& __u) _NOEXCEPT {
+    __ptr_.swap(__u.__ptr_);
+  }
 };
 
+template <class _From, class _ToUnique>
+struct __check_array_pointer_conversion : is_same<_From, typename _ToUnique::pointer> {};
+
+template <class _FromElem, class _ToUnique>
+struct __check_array_pointer_conversion<_FromElem*, _ToUnique>
+    : integral_constant<bool,
+        is_same<_FromElem*, typename _ToUnique::pointer>::value ||
+          (is_same<typename _ToUnique::pointer, typename _ToUnique::element_type*>::value &&
+           is_convertible<_FromElem(*)[], typename _ToUnique::element_type(*)[]>::value)
+    >
+{};
+
 template <class _Tp, class _Dp>
-class _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
-{
+class _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp> {
 public:
-    typedef _Tp element_type;
-    typedef _Dp deleter_type;
-    typedef typename __pointer_type<_Tp, deleter_type>::type pointer;
+  typedef _Tp element_type;
+  typedef _Dp deleter_type;
+  typedef typename __pointer_type<_Tp, deleter_type>::type pointer;
+
 private:
-    __compressed_pair<pointer, deleter_type> __ptr_;
+  __compressed_pair<pointer, deleter_type> __ptr_;
 
-#ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    unique_ptr(unique_ptr&);
-    template <class _Up>
-        unique_ptr(unique_ptr<_Up>&);
-    unique_ptr& operator=(unique_ptr&);
-    template <class _Up>
-        unique_ptr& operator=(unique_ptr<_Up>&);
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
-
-    struct __nat {int __for_bool_;};
-
-    typedef typename remove_reference<deleter_type>::type& _Dp_reference;
-    typedef typename remove_reference<typename add_const<deleter_type>::type>::type&
-        _Dp_const_reference;
-public:
-    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT
-        : __ptr_(pointer())
-        {
-            static_assert(!is_pointer<deleter_type>::value,
-                "unique_ptr constructed with null function pointer deleter");
-        }
-    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT
-        : __ptr_(pointer())
-        {
-            static_assert(!is_pointer<deleter_type>::value,
-                "unique_ptr constructed with null function pointer deleter");
-        }
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    template <class _Pp>
-    _LIBCPP_INLINE_VISIBILITY explicit unique_ptr(_Pp __p,
-            typename enable_if<__same_or_less_cv_qualified<_Pp, pointer>::value, __nat>::type = __nat()) _NOEXCEPT
-        : __ptr_(__p)
-        {
-            static_assert(!is_pointer<deleter_type>::value,
-                "unique_ptr constructed with null function pointer deleter");
-        }
+  struct __nat { int __for_bool_; };
 
-    template <class _Pp>
-    _LIBCPP_INLINE_VISIBILITY unique_ptr(_Pp __p, typename conditional<
-                                       is_reference<deleter_type>::value,
-                                       deleter_type,
-                                       typename add_lvalue_reference<const deleter_type>::type>::type __d,
-                                       typename enable_if<__same_or_less_cv_qualified<_Pp, pointer>::value, __nat>::type = __nat())
-             _NOEXCEPT
-        : __ptr_(__p, __d) {}
-
-    _LIBCPP_INLINE_VISIBILITY unique_ptr(nullptr_t, typename conditional<
-                                       is_reference<deleter_type>::value,
-                                       deleter_type,
-                                       typename add_lvalue_reference<const deleter_type>::type>::type __d)
-             _NOEXCEPT
-        : __ptr_(pointer(), __d) {}
-
-    template <class _Pp>
-    _LIBCPP_INLINE_VISIBILITY unique_ptr(_Pp __p,
-                                         typename remove_reference<deleter_type>::type&& __d,
-                                         typename enable_if<__same_or_less_cv_qualified<_Pp, pointer>::value, __nat>::type = __nat())
-             _NOEXCEPT
-        : __ptr_(__p, _VSTD::move(__d))
-        {
-            static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference");
-        }
+  typedef deleter_type& _Dp_reference;
+  typedef typename remove_reference<typename add_const<deleter_type>::type>::type&
+      _Dp_const_reference;
+
+#ifndef _LIBCPP_CXX03_LANG
+  typedef __unique_ptr_deleter_sfinae<_Dp> _SFINAE;
+
+  template <bool _Dummy>
+  using _LValRefType =
+      typename __dependent_type<_SFINAE, _Dummy>::__lval_ref_type;
+
+  template <bool _Dummy>
+  using _GoodRValRefType =
+      typename __dependent_type<_SFINAE, _Dummy>::__good_rval_ref_type;
+
+  template <bool _Dummy>
+  using _BadRValRefType =
+      typename __dependent_type<_SFINAE, _Dummy>::__bad_rval_ref_type;
+
+  template <bool _Dummy, class _Deleter = typename __dependent_type<
+                             __identity<deleter_type>, _Dummy>::type>
+  using _EnableIfDeleterDefaultConstructible =
+      typename enable_if<is_default_constructible<_Deleter>::value &&
+                         !is_pointer<_Deleter>::value>::type;
+
+  template <class _ArgType>
+  using _EnableIfDeleterConstructible =
+      typename enable_if<is_constructible<deleter_type, _ArgType>::value>::type;
+
+  template <class _Pp>
+  using _EnableIfPointerConvertible = typename enable_if<
+      __check_array_pointer_conversion<_Pp, unique_ptr>::value
+  >::type;
+
+  template <class _UPtr, class _Up,
+        class _ElemT = typename _UPtr::element_type>
+  using _EnableIfMoveConvertible = typename enable_if<
+      is_array<_Up>::value &&
+      is_same<pointer, element_type*>::value &&
+      is_same<typename _UPtr::pointer, _ElemT*>::value &&
+      is_convertible<_ElemT(*)[], element_type(*)[]>::value
+    >::type;
+
+  template <class _UDel>
+  using _EnableIfDeleterConvertible = typename enable_if<
+      (is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) ||
+      (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value)
+    >::type;
+
+  template <class _UDel>
+  using _EnableIfDeleterAssignable = typename enable_if<
+      is_assignable<_Dp&, _UDel&&>::value
+    >::type;
 
-    _LIBCPP_INLINE_VISIBILITY unique_ptr(nullptr_t, typename remove_reference<deleter_type>::type&& __d)
-             _NOEXCEPT
-        : __ptr_(pointer(), _VSTD::move(__d))
-        {
-            static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference");
-        }
+public:
+  template <bool _Dummy = true,
+            class = _EnableIfDeleterDefaultConstructible<_Dummy>>
+  _LIBCPP_INLINE_VISIBILITY
+  constexpr unique_ptr() noexcept : __ptr_(pointer()) {}
+
+  template <bool _Dummy = true,
+            class = _EnableIfDeleterDefaultConstructible<_Dummy>>
+  _LIBCPP_INLINE_VISIBILITY
+  constexpr unique_ptr(nullptr_t) noexcept : __ptr_(pointer()) {}
+
+  template <class _Pp, bool _Dummy = true,
+            class = _EnableIfDeleterDefaultConstructible<_Dummy>,
+            class = _EnableIfPointerConvertible<_Pp>>
+  _LIBCPP_INLINE_VISIBILITY
+  explicit unique_ptr(_Pp __p) noexcept
+      : __ptr_(__p) {}
+
+  template <class _Pp, bool _Dummy = true,
+            class = _EnableIfDeleterConstructible<_LValRefType<_Dummy>>,
+            class = _EnableIfPointerConvertible<_Pp>>
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(_Pp __p, _LValRefType<_Dummy> __d) noexcept
+      : __ptr_(__p, __d) {}
+
+  template <bool _Dummy = true,
+            class = _EnableIfDeleterConstructible<_LValRefType<_Dummy>>>
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(nullptr_t, _LValRefType<_Dummy> __d) noexcept
+      : __ptr_(nullptr, __d) {}
+
+  template <class _Pp, bool _Dummy = true,
+            class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy>>,
+            class = _EnableIfPointerConvertible<_Pp>>
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(_Pp __p, _GoodRValRefType<_Dummy> __d) noexcept
+      : __ptr_(__p, _VSTD::move(__d)) {
+    static_assert(!is_reference<deleter_type>::value,
+                  "rvalue deleter bound to reference");
+  }
+
+  template <bool _Dummy = true,
+            class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy>>>
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(nullptr_t, _GoodRValRefType<_Dummy> __d) noexcept
+      : __ptr_(nullptr, _VSTD::move(__d)) {
+    static_assert(!is_reference<deleter_type>::value,
+                  "rvalue deleter bound to reference");
+  }
+
+  template <class _Pp, bool _Dummy = true,
+            class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy>>,
+            class = _EnableIfPointerConvertible<_Pp>>
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(_Pp __p, _BadRValRefType<_Dummy> __d) = delete;
+
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(unique_ptr&& __u) noexcept
+      : __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) {
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr& operator=(unique_ptr&& __u) noexcept {
+    reset(__u.release());
+    __ptr_.second() = _VSTD::forward<deleter_type>(__u.get_deleter());
+    return *this;
+  }
+
+  template <class _Up, class _Ep,
+      class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>,
+      class = _EnableIfDeleterConvertible<_Ep>
+  >
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
+      : __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) {
+  }
+
+  template <class _Up, class _Ep,
+      class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>,
+      class = _EnableIfDeleterAssignable<_Ep>
+  >
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr&
+  operator=(unique_ptr<_Up, _Ep>&& __u) noexcept {
+    reset(__u.release());
+    __ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter());
+    return *this;
+  }
 
-    _LIBCPP_INLINE_VISIBILITY unique_ptr(unique_ptr&& __u) _NOEXCEPT
-        : __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) {}
+#else // _LIBCPP_CXX03_LANG
+private:
+  template <class _Up> explicit unique_ptr(_Up);
 
-    _LIBCPP_INLINE_VISIBILITY unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT
-        {
-            reset(__u.release());
-            __ptr_.second() = _VSTD::forward<deleter_type>(__u.get_deleter());
-            return *this;
-        }
+  unique_ptr(unique_ptr&);
+  template <class _Up> unique_ptr(unique_ptr<_Up>&);
 
-    template <class _Up, class _Ep>
-        _LIBCPP_INLINE_VISIBILITY
-        unique_ptr(unique_ptr<_Up, _Ep>&& __u,
-                   typename enable_if
-                            <
-                                is_array<_Up>::value &&
-                                __same_or_less_cv_qualified<typename unique_ptr<_Up, _Ep>::pointer, pointer>::value
-                                && is_convertible<_Ep, deleter_type>::value &&
-                                (
-                                    !is_reference<deleter_type>::value ||
-                                    is_same<deleter_type, _Ep>::value
-                                ),
-                                __nat
-                            >::type = __nat()
-                  ) _NOEXCEPT
-        : __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) {}
-
-
-        template <class _Up, class _Ep>
-            _LIBCPP_INLINE_VISIBILITY
-            typename enable_if
-            <
-                is_array<_Up>::value &&
-                __same_or_less_cv_qualified<typename unique_ptr<_Up, _Ep>::pointer, pointer>::value &&
-                is_assignable<deleter_type&, _Ep&&>::value,
-                unique_ptr&
-            >::type
-            operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT
-            {
-                reset(__u.release());
-                __ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter());
-                return *this;
-            }
-#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
-
-    _LIBCPP_INLINE_VISIBILITY explicit unique_ptr(pointer __p)
-        : __ptr_(__p)
-        {
-            static_assert(!is_pointer<deleter_type>::value,
-                "unique_ptr constructed with null function pointer deleter");
-        }
+  unique_ptr& operator=(unique_ptr&);
+  template <class _Up> unique_ptr& operator=(unique_ptr<_Up>&);
 
-    _LIBCPP_INLINE_VISIBILITY unique_ptr(pointer __p, deleter_type __d)
-        : __ptr_(__p, _VSTD::forward<deleter_type>(__d)) {}
+  template <class _Up>
+  unique_ptr(_Up __u,
+             typename conditional<
+                 is_reference<deleter_type>::value, deleter_type,
+                 typename add_lvalue_reference<const deleter_type>::type>::type,
+             typename enable_if<is_convertible<_Up, pointer>::value,
+                                __nat>::type = __nat());
+public:
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr() : __ptr_(pointer()) {
+    static_assert(!is_pointer<deleter_type>::value,
+                  "unique_ptr constructed with null function pointer deleter");
+  }
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(nullptr_t) : __ptr_(pointer()) {
+    static_assert(!is_pointer<deleter_type>::value,
+                  "unique_ptr constructed with null function pointer deleter");
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  explicit unique_ptr(pointer __p) : __ptr_(__p) {
+    static_assert(!is_pointer<deleter_type>::value,
+                  "unique_ptr constructed with null function pointer deleter");
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(pointer __p, deleter_type __d)
+      : __ptr_(__p, _VSTD::forward<deleter_type>(__d)) {}
+
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(nullptr_t, deleter_type __d)
+      : __ptr_(pointer(), _VSTD::forward<deleter_type>(__d)) {}
+
+  _LIBCPP_INLINE_VISIBILITY
+  operator __rv<unique_ptr>() {
+    return __rv<unique_ptr>(*this);
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr(__rv<unique_ptr> __u)
+      : __ptr_(__u->release(),
+               _VSTD::forward<deleter_type>(__u->get_deleter())) {}
+
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr& operator=(__rv<unique_ptr> __u) {
+    reset(__u->release());
+    __ptr_.second() = _VSTD::forward<deleter_type>(__u->get_deleter());
+    return *this;
+  }
 
-    _LIBCPP_INLINE_VISIBILITY unique_ptr(nullptr_t, deleter_type __d)
-        : __ptr_(pointer(), _VSTD::forward<deleter_type>(__d)) {}
+#endif // _LIBCPP_CXX03_LANG
 
-    _LIBCPP_INLINE_VISIBILITY operator __rv<unique_ptr>()
-    {
-        return __rv<unique_ptr>(*this);
-    }
-
-    _LIBCPP_INLINE_VISIBILITY unique_ptr(__rv<unique_ptr> __u)
-        : __ptr_(__u->release(), _VSTD::forward<deleter_type>(__u->get_deleter())) {}
-
-    _LIBCPP_INLINE_VISIBILITY unique_ptr& operator=(__rv<unique_ptr> __u)
-    {
-        reset(__u->release());
-        __ptr_.second() = _VSTD::forward<deleter_type>(__u->get_deleter());
-        return *this;
-    }
-
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    _LIBCPP_INLINE_VISIBILITY ~unique_ptr() {reset();}
-
-    _LIBCPP_INLINE_VISIBILITY unique_ptr& operator=(nullptr_t) _NOEXCEPT
-    {
-        reset();
-        return *this;
-    }
-
-    _LIBCPP_INLINE_VISIBILITY typename add_lvalue_reference<_Tp>::type operator[](size_t __i) const
-        {return __ptr_.first()[__i];}
-    _LIBCPP_INLINE_VISIBILITY pointer get() const _NOEXCEPT {return __ptr_.first();}
-    _LIBCPP_INLINE_VISIBILITY       _Dp_reference get_deleter() _NOEXCEPT
-        {return __ptr_.second();}
-    _LIBCPP_INLINE_VISIBILITY _Dp_const_reference get_deleter() const _NOEXCEPT
-        {return __ptr_.second();}
-    _LIBCPP_INLINE_VISIBILITY
-        _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT
-        {return __ptr_.first() != nullptr;}
-
-    _LIBCPP_INLINE_VISIBILITY pointer release() _NOEXCEPT
-    {
-        pointer __t = __ptr_.first();
-        __ptr_.first() = pointer();
-        return __t;
-    }
-
-    template <class _Pp>
-    _LIBCPP_INLINE_VISIBILITY
-    typename enable_if<__same_or_less_cv_qualified<_Pp, pointer>::value, void>::type
-    reset(_Pp __p) _NOEXCEPT
-    {
-        pointer __tmp = __ptr_.first();
-        __ptr_.first() = __p;
-        if (__tmp)
-            __ptr_.second()(__tmp);
-    }
-    _LIBCPP_INLINE_VISIBILITY void reset(nullptr_t = nullptr) _NOEXCEPT
-    {
-        pointer __tmp = __ptr_.first();
-        __ptr_.first() = nullptr;
-        if (__tmp)
-            __ptr_.second()(__tmp);
-    }
+public:
+  _LIBCPP_INLINE_VISIBILITY
+  ~unique_ptr() { reset(); }
 
-    _LIBCPP_INLINE_VISIBILITY void swap(unique_ptr& __u) {__ptr_.swap(__u.__ptr_);}
-private:
+  _LIBCPP_INLINE_VISIBILITY
+  unique_ptr& operator=(nullptr_t) _NOEXCEPT {
+    reset();
+    return *this;
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  typename add_lvalue_reference<_Tp>::type
+  operator[](size_t __i) const {
+    return __ptr_.first()[__i];
+  }
+  _LIBCPP_INLINE_VISIBILITY
+  pointer get() const _NOEXCEPT {
+    return __ptr_.first();
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  deleter_type& get_deleter() _NOEXCEPT {
+    return __ptr_.second();
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  const deleter_type& get_deleter() const _NOEXCEPT {
+    return __ptr_.second();
+  }
+  _LIBCPP_INLINE_VISIBILITY
+  _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {
+    return __ptr_.first() != nullptr;
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  pointer release() _NOEXCEPT {
+    pointer __t = __ptr_.first();
+    __ptr_.first() = pointer();
+    return __t;
+  }
+
+  template <class _Pp>
+  _LIBCPP_INLINE_VISIBILITY
+  typename enable_if<
+      __check_array_pointer_conversion<_Pp, unique_ptr>::value
+  >::type
+  reset(_Pp __p) _NOEXCEPT {
+    pointer __tmp = __ptr_.first();
+    __ptr_.first() = __p;
+    if (__tmp)
+      __ptr_.second()(__tmp);
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  void reset(nullptr_t = nullptr) _NOEXCEPT {
+    pointer __tmp = __ptr_.first();
+    __ptr_.first() = nullptr;
+    if (__tmp)
+      __ptr_.second()(__tmp);
+  }
+
+  _LIBCPP_INLINE_VISIBILITY
+  void swap(unique_ptr& __u) _NOEXCEPT {
+    __ptr_.swap(__u.__ptr_);
+  }
 
-#ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    template <class _Up>
-        explicit unique_ptr(_Up);
-    template <class _Up>
-        unique_ptr(_Up __u,
-                   typename conditional<
-                                       is_reference<deleter_type>::value,
-                                       deleter_type,
-                                       typename add_lvalue_reference<const deleter_type>::type>::type,
-                   typename enable_if
-                      <
-                         is_convertible<_Up, pointer>::value,
-                         __nat
-                      >::type = __nat());
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
 };
 
 template <class _Tp, class _Dp>

Modified: libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move.pass.cpp?rev=300406&r1=300405&r2=300406&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move.pass.cpp Sat Apr 15 20:51:04 2017
@@ -82,31 +82,32 @@ void test_sfinae() {
     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, "");
+    static_assert(std::is_nothrow_assignable<U, U&&>::value, "");
   }
   {
     typedef std::unique_ptr<VT, GenericDeleter> 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, "");
+    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, "");
+    static_assert(std::is_nothrow_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_assignable<U, U&&>::value, "");
+    static_assert(std::is_nothrow_assignable<U, U&&>::value, "");
   }
 }
 
+
 int main() {
   {
     test_basic</*IsArray*/ false>();

Added: libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.pass.cpp?rev=300406&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.pass.cpp Sat Apr 15 20:51:04 2017
@@ -0,0 +1,414 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory>
+
+// unique_ptr
+
+// Test unique_ptr converting move ctor
+
+#include <memory>
+#include <cassert>
+
+#include "test_macros.h"
+#include "unique_ptr_test_helper.h"
+#include "type_id.h"
+
+template <int ID = 0>
+struct GenericDeleter {
+  void operator()(void*) const {}
+};
+
+template <int ID = 0>
+struct GenericConvertingDeleter {
+
+  template <int OID>
+  GenericConvertingDeleter(GenericConvertingDeleter<OID>) {}
+
+  template <int OID>
+  GenericConvertingDeleter& operator=(GenericConvertingDeleter<OID> const&) {
+    return *this;
+  }
+
+  void operator()(void*) const {}
+};
+
+template <class T, class U>
+using EnableIfNotSame = typename std::enable_if<
+    !std::is_same<typename std::decay<T>::type, typename std::decay<U>::type>::value
+>::type;
+
+template <template <int> class Templ, class Other>
+struct is_specialization : std::false_type {};
+
+template <template <int> class Templ, int ID>
+struct is_specialization<Templ, Templ<ID> > : std::true_type {};
+
+template <template <int> class Templ, class Other>
+using EnableIfSpecialization = typename std::enable_if<
+    is_specialization<Templ, typename std::decay<Other>::type >::value
+  >::type;
+
+template <int ID>
+struct TrackingDeleter {
+  TrackingDeleter() : arg_type(&makeArgumentID<>()) {}
+
+  TrackingDeleter(TrackingDeleter const&)
+      : arg_type(&makeArgumentID<TrackingDeleter const&>()) {}
+
+  TrackingDeleter(TrackingDeleter&&)
+      : arg_type(&makeArgumentID<TrackingDeleter &&>()) {}
+
+  template <class T, class = EnableIfSpecialization<TrackingDeleter, T> >
+  TrackingDeleter(T&&) : arg_type(&makeArgumentID<T&&>()) {}
+
+  TrackingDeleter& operator=(TrackingDeleter const&) {
+    arg_type = &makeArgumentID<TrackingDeleter const&>();
+    return *this;
+  }
+
+  TrackingDeleter& operator=(TrackingDeleter &&) {
+    arg_type = &makeArgumentID<TrackingDeleter &&>();
+    return *this;
+  }
+
+  template <class T, class = EnableIfSpecialization<TrackingDeleter, T> >
+  TrackingDeleter& operator=(T&&) {
+    arg_type = &makeArgumentID<T&&>();
+    return *this;
+  }
+
+  void operator()(void*) const {}
+
+public:
+  TypeID const* reset() const {
+    TypeID const* tmp = arg_type;
+    arg_type = nullptr;
+    return tmp;
+  }
+
+  mutable TypeID const* arg_type;
+};
+
+template <int ID>
+struct ConstTrackingDeleter {
+  ConstTrackingDeleter() : arg_type(&makeArgumentID<>()) {}
+
+  ConstTrackingDeleter(ConstTrackingDeleter const&)
+      : arg_type(&makeArgumentID<ConstTrackingDeleter const&>()) {}
+
+  ConstTrackingDeleter(ConstTrackingDeleter&&)
+      : arg_type(&makeArgumentID<ConstTrackingDeleter &&>()) {}
+
+  template <class T, class = EnableIfSpecialization<ConstTrackingDeleter, T> >
+  ConstTrackingDeleter(T&&) : arg_type(&makeArgumentID<T&&>()) {}
+
+  const ConstTrackingDeleter& operator=(ConstTrackingDeleter const&) const {
+    arg_type = &makeArgumentID<ConstTrackingDeleter const&>();
+    return *this;
+  }
+
+  const ConstTrackingDeleter& operator=(ConstTrackingDeleter &&) const {
+    arg_type = &makeArgumentID<ConstTrackingDeleter &&>();
+    return *this;
+  }
+
+  template <class T, class = EnableIfSpecialization<ConstTrackingDeleter, T> >
+  const ConstTrackingDeleter& operator=(T&&) const {
+    arg_type = &makeArgumentID<T&&>();
+    return *this;
+  }
+
+  void operator()(void*) const {}
+
+public:
+  TypeID const* reset() const {
+    TypeID const* tmp = arg_type;
+    arg_type = nullptr;
+    return tmp;
+  }
+
+  mutable TypeID const* arg_type;
+};
+
+template <class ExpectT, int ID>
+bool checkArg(TrackingDeleter<ID> const& d) {
+  return d.arg_type && *d.arg_type == makeArgumentID<ExpectT>();
+}
+
+template <class ExpectT, int ID>
+bool checkArg(ConstTrackingDeleter<ID> const& d) {
+  return d.arg_type && *d.arg_type == makeArgumentID<ExpectT>();
+}
+
+template <class From, bool AssignIsConst = false>
+struct AssignDeleter {
+  AssignDeleter() = default;
+  AssignDeleter(AssignDeleter const&) = default;
+  AssignDeleter(AssignDeleter&&) = default;
+
+  AssignDeleter& operator=(AssignDeleter const&) = delete;
+  AssignDeleter& operator=(AssignDeleter &&) = delete;
+
+  template <class T> AssignDeleter& operator=(T&&) && = delete;
+  template <class T> AssignDeleter& operator=(T&&) const && = delete;
+
+  template <class T, class = typename std::enable_if<
+      std::is_same<T&&, From>::value && !AssignIsConst
+    >::type>
+  AssignDeleter& operator=(T&&) & { return *this; }
+
+  template <class T, class = typename std::enable_if<
+      std::is_same<T&&, From>::value && AssignIsConst
+    >::type>
+  const AssignDeleter& operator=(T&&) const & { return *this; }
+
+  template <class T>
+  void operator()(T) const {}
+};
+
+template <class VT, class DDest, class DSource>
+  void doDeleterTest() {
+    using U1 = std::unique_ptr<VT, DDest>;
+    using U2 = std::unique_ptr<VT, DSource>;
+    static_assert(std::is_nothrow_assignable<U1, U2&&>::value, "");
+    typename std::decay<DDest>::type ddest;
+    typename std::decay<DSource>::type dsource;
+    U1 u1(nullptr, ddest);
+    U2 u2(nullptr, dsource);
+    u1 = std::move(u2);
+}
+
+template <bool IsArray>
+void test_sfinae() {
+  typedef typename std::conditional<IsArray, A[], A>::type VT;
+
+  { // Test that different non-reference deleter types are allowed so long
+    // as they convert to each other.
+    using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
+    using U2 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
+    static_assert(std::is_assignable<U1, U2&&>::value, "");
+  }
+  { // Test that different non-reference deleter types are disallowed when
+    // they cannot convert.
+    using U1 = std::unique_ptr<VT, GenericDeleter<0> >;
+    using U2 = std::unique_ptr<VT, GenericDeleter<1> >;
+    static_assert(!std::is_assignable<U1, U2&&>::value, "");
+  }
+  { // Test that if the deleter assignment is not valid the assignment operator
+    // SFINAEs.
+    using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> const& >;
+    using U2 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
+    using U3 = std::unique_ptr<VT, GenericConvertingDeleter<0> &>;
+    using U4 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
+    using U5 = std::unique_ptr<VT, GenericConvertingDeleter<1> const&>;
+    static_assert(!std::is_assignable<U1, U2&&>::value, "");
+    static_assert(!std::is_assignable<U1, U3&&>::value, "");
+    static_assert(!std::is_assignable<U1, U4&&>::value, "");
+    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, "");
+  }
+  { // Test that if the deleter assignment is not valid the assignment operator
+    // SFINAEs.
+    using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> & >;
+    using U2 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
+    using U3 = std::unique_ptr<VT, GenericConvertingDeleter<0> &>;
+    using U4 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
+    using U5 = std::unique_ptr<VT, GenericConvertingDeleter<1> const&>;
+
+    static_assert(std::is_nothrow_assignable<U1, U2&&>::value, "");
+    static_assert(std::is_nothrow_assignable<U1, U3&&>::value, "");
+    static_assert(std::is_nothrow_assignable<U1, U4&&>::value, "");
+    static_assert(std::is_nothrow_assignable<U1, U5&&>::value, "");
+
+    using U1C = std::unique_ptr<const VT, GenericConvertingDeleter<0> &>;
+    static_assert(std::is_nothrow_assignable<U1C, U1&&>::value, "");
+  }
+  { // Test that non-reference destination deleters can be assigned
+    // from any source deleter type with a sutible conversion. Including
+    // reference types.
+    using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
+    using U2 = std::unique_ptr<VT, GenericConvertingDeleter<0> &>;
+    using U3 = std::unique_ptr<VT, GenericConvertingDeleter<0> const &>;
+    using U4 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
+    using U5 = std::unique_ptr<VT, GenericConvertingDeleter<1> &>;
+    using U6 = std::unique_ptr<VT, GenericConvertingDeleter<1> const&>;
+    static_assert(std::is_assignable<U1, U2&&>::value, "");
+    static_assert(std::is_assignable<U1, U3&&>::value, "");
+    static_assert(std::is_assignable<U1, U4&&>::value, "");
+    static_assert(std::is_assignable<U1, U5&&>::value, "");
+    static_assert(std::is_assignable<U1, U6&&>::value, "");
+  }
+  /////////////////////////////////////////////////////////////////////////////
+  {
+    using Del = GenericDeleter<0>;
+    using AD = AssignDeleter<Del&&>;
+    using ADC = AssignDeleter<Del&&, /*AllowConstAssign*/true>;
+    doDeleterTest<VT, AD, Del>();
+    doDeleterTest<VT, AD&, Del>();
+    doDeleterTest<VT, ADC const&, Del>();
+  }
+  {
+    using Del = GenericDeleter<0>;
+    using AD = AssignDeleter<Del&>;
+    using ADC = AssignDeleter<Del&, /*AllowConstAssign*/true>;
+    doDeleterTest<VT, AD, Del&>();
+    doDeleterTest<VT, AD&, Del&>();
+    doDeleterTest<VT, ADC const&, Del&>();
+  }
+  {
+    using Del = GenericDeleter<0>;
+    using AD = AssignDeleter<Del const&>;
+    using ADC = AssignDeleter<Del const&, /*AllowConstAssign*/true>;
+    doDeleterTest<VT, AD, Del const&>();
+    doDeleterTest<VT, AD&, Del const&>();
+    doDeleterTest<VT, ADC const&, Del const&>();
+  }
+}
+
+
+template <bool IsArray>
+void test_noexcept() {
+  typedef typename std::conditional<IsArray, A[], A>::type VT;
+  {
+    typedef std::unique_ptr<const VT> APtr;
+    typedef std::unique_ptr<VT> BPtr;
+    static_assert(std::is_nothrow_assignable<APtr, BPtr>::value, "");
+  }
+  {
+    typedef std::unique_ptr<const VT, CDeleter<const VT> > APtr;
+    typedef std::unique_ptr<VT, CDeleter<VT> > BPtr;
+    static_assert(std::is_nothrow_assignable<APtr, BPtr>::value, "");
+  }
+  {
+    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, "");
+  }
+  {
+    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, "");
+  }
+}
+
+template <bool IsArray>
+void test_deleter_value_category() {
+  typedef typename std::conditional<IsArray, A[], A>::type VT;
+  using TD1 = TrackingDeleter<1>;
+  using TD2 = TrackingDeleter<2>;
+  TD1 d1;
+  TD2 d2;
+  using CD1 = ConstTrackingDeleter<1>;
+  using CD2 = ConstTrackingDeleter<2>;
+  CD1 cd1;
+  CD2 cd2;
+
+  { // Test non-reference deleter conversions
+    using U1 = std::unique_ptr<VT, TD1 >;
+    using U2 = std::unique_ptr<VT, TD2 >;
+    U1 u1;
+    U2 u2;
+    u1.get_deleter().reset();
+    u1 = std::move(u2);
+    assert(checkArg<TD2&&>(u1.get_deleter()));
+  }
+  { // Test assignment to non-const ref
+    using U1 = std::unique_ptr<VT, TD1& >;
+    using U2 = std::unique_ptr<VT, TD2 >;
+    U1 u1(nullptr, d1);
+    U2 u2;
+    u1.get_deleter().reset();
+    u1 = std::move(u2);
+    assert(checkArg<TD2&&>(u1.get_deleter()));
+  }
+  { // Test assignment to const&.
+    using U1 = std::unique_ptr<VT, CD1 const& >;
+    using U2 = std::unique_ptr<VT, CD2 >;
+    U1 u1(nullptr, cd1);
+    U2 u2;
+    u1.get_deleter().reset();
+    u1 = std::move(u2);
+    assert(checkArg<CD2&&>(u1.get_deleter()));
+  }
+
+  { // Test assignment from non-const ref
+    using U1 = std::unique_ptr<VT, TD1 >;
+    using U2 = std::unique_ptr<VT, TD2& >;
+    U1 u1;
+    U2 u2(nullptr, d2);
+    u1.get_deleter().reset();
+    u1 = std::move(u2);
+    assert(checkArg<TD2&>(u1.get_deleter()));
+  }
+  { // Test assignment from const ref
+    using U1 = std::unique_ptr<VT, TD1 >;
+    using U2 = std::unique_ptr<VT, TD2 const& >;
+    U1 u1;
+    U2 u2(nullptr, d2);
+    u1.get_deleter().reset();
+    u1 = std::move(u2);
+    assert(checkArg<TD2 const&>(u1.get_deleter()));
+  }
+
+  { // Test assignment from non-const ref
+    using U1 = std::unique_ptr<VT, TD1& >;
+    using U2 = std::unique_ptr<VT, TD2& >;
+    U1 u1(nullptr, d1);
+    U2 u2(nullptr, d2);
+    u1.get_deleter().reset();
+    u1 = std::move(u2);
+    assert(checkArg<TD2&>(u1.get_deleter()));
+  }
+  { // Test assignment from const ref
+    using U1 = std::unique_ptr<VT, TD1& >;
+    using U2 = std::unique_ptr<VT, TD2 const& >;
+    U1 u1(nullptr, d1);
+    U2 u2(nullptr, d2);
+    u1.get_deleter().reset();
+    u1 = std::move(u2);
+    assert(checkArg<TD2 const&>(u1.get_deleter()));
+  }
+
+  { // Test assignment from non-const ref
+    using U1 = std::unique_ptr<VT, CD1 const& >;
+    using U2 = std::unique_ptr<VT, CD2 & >;
+    U1 u1(nullptr, cd1);
+    U2 u2(nullptr, cd2);
+    u1.get_deleter().reset();
+    u1 = std::move(u2);
+    assert(checkArg<CD2 &>(u1.get_deleter()));
+  }
+  { // Test assignment from const ref
+    using U1 = std::unique_ptr<VT, CD1 const& >;
+    using U2 = std::unique_ptr<VT, CD2 const& >;
+    U1 u1(nullptr, cd1);
+    U2 u2(nullptr, cd2);
+    u1.get_deleter().reset();
+    u1 = std::move(u2);
+    assert(checkArg<CD2 const&>(u1.get_deleter()));
+  }
+}
+
+int main() {
+  {
+    test_sfinae</*IsArray*/false>();
+    test_noexcept<false>();
+    test_deleter_value_category<false>();
+  }
+  {
+    test_sfinae</*IsArray*/true>();
+    test_noexcept<true>();
+    test_deleter_value_category<true>();
+  }
+}

Modified: libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/default.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/default.pass.cpp?rev=300406&r1=300405&r2=300406&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/default.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/default.pass.cpp Sat Apr 15 20:51:04 2017
@@ -31,8 +31,6 @@
 #include "deleter_types.h"
 #include "unique_ptr_test_helper.h"
 
-#include "test_workarounds.h" // For TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES
-
 #if defined(_LIBCPP_VERSION) && TEST_STD_VER >= 11
 _LIBCPP_SAFE_STATIC std::unique_ptr<int> global_static_unique_ptr_single;
 _LIBCPP_SAFE_STATIC std::unique_ptr<int[]> global_static_unique_ptr_runtime;
@@ -47,7 +45,7 @@ struct NonDefaultDeleter {
 
 template <class ElemType>
 void test_sfinae() {
-#if TEST_STD_VER >= 11 && !defined(TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES)
+#if TEST_STD_VER >= 11
   { // the constructor does not participate in overload resultion when
     // the deleter is a pointer type
     using U = std::unique_ptr<ElemType, void (*)(void*)>;

Modified: libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move.pass.cpp?rev=300406&r1=300405&r2=300406&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move.pass.cpp Sat Apr 15 20:51:04 2017
@@ -18,7 +18,6 @@
 #include <cassert>
 
 #include "test_macros.h"
-#include "deleter_types.h"
 #include "unique_ptr_test_helper.h"
 
 //=============================================================================
@@ -139,13 +138,37 @@ void test_basic() {
   assert(A::count == 0);
 }
 
+template <class VT>
+void test_noexcept() {
+#if TEST_STD_VER >= 11
+  {
+    typedef std::unique_ptr<VT> U;
+    static_assert(std::is_nothrow_move_constructible<U>::value, "");
+  }
+  {
+    typedef std::unique_ptr<VT, Deleter<VT> > U;
+    static_assert(std::is_nothrow_move_constructible<U>::value, "");
+  }
+  {
+    typedef std::unique_ptr<VT, NCDeleter<VT> &> U;
+    static_assert(std::is_nothrow_move_constructible<U>::value, "");
+  }
+  {
+    typedef std::unique_ptr<VT, const NCConstDeleter<VT> &> U;
+    static_assert(std::is_nothrow_move_constructible<U>::value, "");
+  }
+#endif
+}
+
 int main() {
   {
     test_basic</*IsArray*/ false>();
     test_sfinae<int>();
+    test_noexcept<int>();
   }
   {
     test_basic</*IsArray*/ true>();
     test_sfinae<int[]>();
+    test_noexcept<int[]>();
   }
 }

Added: libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.pass.cpp?rev=300406&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.pass.cpp Sat Apr 15 20:51:04 2017
@@ -0,0 +1,124 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <memory>
+
+// unique_ptr
+
+// Test unique_ptr converting move ctor
+
+#include <memory>
+#include <cassert>
+
+#include "test_macros.h"
+#include "unique_ptr_test_helper.h"
+
+template <int ID = 0>
+struct GenericDeleter {
+  void operator()(void*) const {}
+};
+
+template <int ID = 0>
+struct GenericConvertingDeleter {
+  template <int OID>
+  GenericConvertingDeleter(GenericConvertingDeleter<OID>) {}
+  void operator()(void*) const {}
+};
+
+template <bool IsArray>
+void test_sfinae() {
+#if TEST_STD_VER >= 11
+  typedef typename std::conditional<IsArray, A[], A>::type VT;
+
+  { // Test that different non-reference deleter types are allowed so long
+    // as they convert to each other.
+    using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
+    using U2 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
+    static_assert(std::is_constructible<U1, U2&&>::value, "");
+  }
+  { // Test that different non-reference deleter types are disallowed when
+    // they cannot convert.
+    using U1 = std::unique_ptr<VT, GenericDeleter<0> >;
+    using U2 = std::unique_ptr<VT, GenericDeleter<1> >;
+    static_assert(!std::is_constructible<U1, U2&&>::value, "");
+  }
+  { // Test that if the destination deleter is a reference type then only
+    // exact matches are allowed.
+    using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> const& >;
+    using U2 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
+    using U3 = std::unique_ptr<VT, GenericConvertingDeleter<0> &>;
+    using U4 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
+    using U5 = std::unique_ptr<VT, GenericConvertingDeleter<1> const&>;
+    static_assert(!std::is_constructible<U1, U2&&>::value, "");
+    static_assert(!std::is_constructible<U1, U3&&>::value, "");
+    static_assert(!std::is_constructible<U1, U4&&>::value, "");
+    static_assert(!std::is_constructible<U1, U5&&>::value, "");
+
+    using U1C = std::unique_ptr<const VT, GenericConvertingDeleter<0> const&>;
+    static_assert(std::is_nothrow_constructible<U1C, U1&&>::value, "");
+  }
+  { // Test that non-reference destination deleters can be constructed
+    // from any source deleter type with a sutible conversion. Including
+    // reference types.
+    using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
+    using U2 = std::unique_ptr<VT, GenericConvertingDeleter<0> &>;
+    using U3 = std::unique_ptr<VT, GenericConvertingDeleter<0> const &>;
+    using U4 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
+    using U5 = std::unique_ptr<VT, GenericConvertingDeleter<1> &>;
+    using U6 = std::unique_ptr<VT, GenericConvertingDeleter<1> const&>;
+    static_assert(std::is_constructible<U1, U2&&>::value, "");
+    static_assert(std::is_constructible<U1, U3&&>::value, "");
+    static_assert(std::is_constructible<U1, U4&&>::value, "");
+    static_assert(std::is_constructible<U1, U5&&>::value, "");
+    static_assert(std::is_constructible<U1, U6&&>::value, "");
+  }
+#endif
+}
+
+
+template <bool IsArray>
+void test_noexcept() {
+#if TEST_STD_VER >= 11
+  typedef typename std::conditional<IsArray, A[], A>::type VT;
+  {
+    typedef std::unique_ptr<const VT> APtr;
+    typedef std::unique_ptr<VT> BPtr;
+    static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
+  }
+  {
+    typedef std::unique_ptr<const VT, CDeleter<const VT> > APtr;
+    typedef std::unique_ptr<VT, CDeleter<VT> > BPtr;
+    static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
+  }
+  {
+    typedef std::unique_ptr<const VT, NCDeleter<const VT>&> APtr;
+    typedef std::unique_ptr<VT, NCDeleter<const VT>&> BPtr;
+    static_assert(std::is_nothrow_constructible<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_constructible<APtr, BPtr>::value, "");
+  }
+#endif
+}
+
+
+int main() {
+  {
+    test_sfinae</*IsArray*/false>();
+    test_noexcept<false>();
+  }
+  {
+    test_sfinae</*IsArray*/true>();
+    test_noexcept<true>();
+  }
+}

Modified: libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.runtime.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.runtime.pass.cpp?rev=300406&r1=300405&r2=300406&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.runtime.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.runtime.pass.cpp Sat Apr 15 20:51:04 2017
@@ -77,4 +77,7 @@ void test_sfinae() {
   }
 }
 
-int main() { test_sfinae(); }
+
+int main() {
+  test_sfinae();
+}

Modified: libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.single.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.single.pass.cpp?rev=300406&r1=300405&r2=300406&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.single.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move_convert.single.pass.cpp Sat Apr 15 20:51:04 2017
@@ -22,7 +22,7 @@
 #include <utility>
 #include <cassert>
 
-#include "deleter_types.h"
+#include "test_macros.h"
 #include "unique_ptr_test_helper.h"
 
 // test converting move ctor.  Should only require a MoveConstructible deleter, or if
@@ -135,8 +135,35 @@ void test_sfinae() {
   }
 }
 
+void test_noexcept() {
+  {
+    typedef std::unique_ptr<A> APtr;
+    typedef std::unique_ptr<B> BPtr;
+    static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
+  }
+  {
+    typedef std::unique_ptr<A, Deleter<A> > APtr;
+    typedef std::unique_ptr<B, Deleter<B> > BPtr;
+    static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
+  }
+  {
+    typedef std::unique_ptr<A, NCDeleter<A>&> APtr;
+    typedef std::unique_ptr<B, NCDeleter<A>&> BPtr;
+    static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
+  }
+  {
+    typedef std::unique_ptr<A, const NCConstDeleter<A>&> APtr;
+    typedef std::unique_ptr<B, const NCConstDeleter<A>&> BPtr;
+    static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
+  }
+}
+
 int main() {
   {
+    test_sfinae();
+    test_noexcept();
+  }
+  {
     typedef std::unique_ptr<A> APtr;
     typedef std::unique_ptr<B> BPtr;
     { // explicit
@@ -218,5 +245,4 @@ int main() {
     }
     checkNoneAlive();
   }
-  test_sfinae();
 }

Modified: libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/nullptr.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/nullptr.pass.cpp?rev=300406&r1=300405&r2=300406&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/nullptr.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/nullptr.pass.cpp Sat Apr 15 20:51:04 2017
@@ -17,25 +17,14 @@
 #include <cassert>
 
 #include "test_macros.h"
-#include "deleter_types.h"
 #include "unique_ptr_test_helper.h"
 
-#include "test_workarounds.h" // For TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES
 
-// default unique_ptr ctor should only require default Deleter ctor
-class DefaultDeleter {
-  int state_;
-
-  DefaultDeleter(DefaultDeleter&);
-  DefaultDeleter& operator=(DefaultDeleter&);
-
-public:
-  DefaultDeleter() : state_(5) {}
-
-  int state() const { return state_; }
+#if defined(_LIBCPP_VERSION) && TEST_STD_VER >= 11
+_LIBCPP_SAFE_STATIC std::unique_ptr<int> global_static_unique_ptr_single(nullptr);
+_LIBCPP_SAFE_STATIC std::unique_ptr<int[]> global_static_unique_ptr_runtime(nullptr);
+#endif
 
-  void operator()(void*) {}
-};
 
 #if TEST_STD_VER >= 11
 struct NonDefaultDeleter {
@@ -46,15 +35,6 @@ struct NonDefaultDeleter {
 
 template <class VT>
 void test_basic() {
-  {
-    std::unique_ptr<VT> p(nullptr);
-    assert(p.get() == 0);
-  }
-  {
-    std::unique_ptr<VT, DefaultDeleter> p(nullptr);
-    assert(p.get() == 0);
-    assert(p.get_deleter().state() == 5);
-  }
 #if TEST_STD_VER >= 11
   {
     using U1 = std::unique_ptr<VT>;
@@ -65,11 +45,20 @@ void test_basic() {
                   "");
   }
 #endif
+  {
+    std::unique_ptr<VT> p(nullptr);
+    assert(p.get() == 0);
+  }
+  {
+    std::unique_ptr<VT, NCDeleter<VT> > p(nullptr);
+    assert(p.get() == 0);
+    assert(p.get_deleter().state() == 0);
+  }
 }
 
 template <class VT>
 void test_sfinae() {
-#if TEST_STD_VER >= 11 && !defined(TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES)
+#if TEST_STD_VER >= 11
   { // the constructor does not participate in overload resultion when
     // the deleter is a pointer type
     using U = std::unique_ptr<VT, void (*)(void*)>;

Modified: libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer.pass.cpp?rev=300406&r1=300405&r2=300406&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer.pass.cpp Sat Apr 15 20:51:04 2017
@@ -35,8 +35,6 @@
 #include "test_macros.h"
 #include "unique_ptr_test_helper.h"
 
-#include "test_workarounds.h" // For TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES
-
 // unique_ptr(pointer) ctor should only require default Deleter ctor
 
 template <bool IsArray>
@@ -47,8 +45,14 @@ void test_pointer() {
   {
     using U1 = std::unique_ptr<ValueT>;
     using U2 = std::unique_ptr<ValueT, Deleter<ValueT> >;
+
+    // Test for noexcept
     static_assert(std::is_nothrow_constructible<U1, A*>::value, "");
     static_assert(std::is_nothrow_constructible<U2, A*>::value, "");
+
+    // Test for explicit
+    static_assert(!std::is_convertible<A*, U1>::value, "");
+    static_assert(!std::is_convertible<A*, U2>::value, "");
   }
 #endif
   {
@@ -103,7 +107,7 @@ struct GenericDeleter {
 
 template <class T>
 void test_sfinae() {
-#if TEST_STD_VER >= 11 && !defined(TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES)
+#if TEST_STD_VER >= 11
   { // the constructor does not participate in overload resultion when
     // the deleter is a pointer type
     using U = std::unique_ptr<T, void (*)(void*)>;

Modified: libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer_deleter.fail.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer_deleter.fail.cpp?rev=300406&r1=300405&r2=300406&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer_deleter.fail.cpp (original)
+++ libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer_deleter.fail.cpp Sat Apr 15 20:51:04 2017
@@ -19,17 +19,11 @@
 
 #include <memory>
 
-#include "test_workarounds.h"
-
 struct Deleter {
   void operator()(int* p) const { delete p; }
 };
 
 int main() {
-#if defined(TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES)
-// expected-error at memory:* {{static_assert failed "rvalue deleter bound to reference"}}
-#else
-// expected-error at +2 {{call to deleted constructor of 'std::unique_ptr<int, const Deleter &>}}
-#endif
+  // expected-error at +1 {{call to deleted constructor of 'std::unique_ptr<int, const Deleter &>}}
   std::unique_ptr<int, const Deleter&> s((int*)nullptr, Deleter());
 }

Modified: libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer_deleter.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer_deleter.pass.cpp?rev=300406&r1=300405&r2=300406&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer_deleter.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer_deleter.pass.cpp Sat Apr 15 20:51:04 2017
@@ -29,8 +29,6 @@
 #include "test_macros.h"
 #include "unique_ptr_test_helper.h"
 
-#include "test_workarounds.h" // For TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES
-
 bool my_free_called = false;
 
 void my_free(void*) { my_free_called = true; }
@@ -56,7 +54,7 @@ struct NoCopyMoveDeleter : DeleterBase {
 
 template <bool IsArray>
 void test_sfinae() {
-#if TEST_STD_VER >= 11 && !defined(TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES)
+#if TEST_STD_VER >= 11
   typedef typename std::conditional<!IsArray, int, int[]>::type VT;
   {
     using D = CopyOnlyDeleter;
@@ -137,13 +135,13 @@ void test_noexcept() {
 }
 
 void test_sfinae_runtime() {
-#if TEST_STD_VER >= 11 && !defined(TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES)
+#if TEST_STD_VER >= 11
   {
     using D = CopyOnlyDeleter;
     using U = std::unique_ptr<A[], D>;
-    static_assert(std::is_constructible<U, A*, D const&>::value, "");
-    static_assert(std::is_constructible<U, A*, D&>::value, "");
-    static_assert(std::is_constructible<U, A*, D&&>::value, "");
+    static_assert(std::is_nothrow_constructible<U, A*, D const&>::value, "");
+    static_assert(std::is_nothrow_constructible<U, A*, D&>::value, "");
+    static_assert(std::is_nothrow_constructible<U, A*, D&&>::value, "");
 
     static_assert(!std::is_constructible<U, B*, D const&>::value, "");
     static_assert(!std::is_constructible<U, B*, D&>::value, "");
@@ -158,7 +156,7 @@ void test_sfinae_runtime() {
     using U = std::unique_ptr<A[], D>;
     static_assert(!std::is_constructible<U, A*, D const&>::value, "");
     static_assert(!std::is_constructible<U, A*, D&>::value, "");
-    static_assert(std::is_constructible<U, A*, D&&>::value, "");
+    static_assert(std::is_nothrow_constructible<U, A*, D&&>::value, "");
 
     static_assert(!std::is_constructible<U, B*, D const&>::value, "");
     static_assert(!std::is_constructible<U, B*, D&>::value, "");
@@ -181,7 +179,7 @@ void test_sfinae_runtime() {
     using D = NoCopyMoveDeleter;
     using U = std::unique_ptr<A[], D&>;
     static_assert(!std::is_constructible<U, A*, D const&>::value, "");
-    static_assert(std::is_constructible<U, A*, D&>::value, "");
+    static_assert(std::is_nothrow_constructible<U, A*, D&>::value, "");
     static_assert(!std::is_constructible<U, A*, D&&>::value, "");
     static_assert(!std::is_constructible<U, A*, const D&&>::value, "");
 
@@ -193,8 +191,8 @@ void test_sfinae_runtime() {
   {
     using D = NoCopyMoveDeleter;
     using U = std::unique_ptr<A[], const D&>;
-    static_assert(std::is_constructible<U, A*, D const&>::value, "");
-    static_assert(std::is_constructible<U, A*, D&>::value, "");
+    static_assert(std::is_nothrow_constructible<U, A*, D const&>::value, "");
+    static_assert(std::is_nothrow_constructible<U, A*, D&>::value, "");
     static_assert(!std::is_constructible<U, A*, D&&>::value, "");
     static_assert(!std::is_constructible<U, A*, const D&&>::value, "");
 
@@ -291,15 +289,38 @@ void test_basic_single() {
   }
 }
 
+template <bool IsArray>
+void test_nullptr() {
+#if TEST_STD_VER >= 11
+  typedef typename std::conditional<!IsArray, A, A[]>::type VT;
+  {
+    std::unique_ptr<VT, Deleter<VT> > u(nullptr, Deleter<VT>{});
+    assert(u.get() == nullptr);
+  }
+  {
+    NCDeleter<VT> d;
+    std::unique_ptr<VT, NCDeleter<VT>& > u(nullptr, d);
+    assert(u.get() == nullptr);
+  }
+  {
+    NCConstDeleter<VT> d;
+    std::unique_ptr<VT, NCConstDeleter<VT> const& > u(nullptr, d);
+    assert(u.get() == nullptr);
+  }
+#endif
+}
+
 int main() {
   {
     test_basic</*IsArray*/ false>();
+    test_nullptr<false>();
     test_basic_single();
     test_sfinae<false>();
     test_noexcept<false>();
   }
   {
     test_basic</*IsArray*/ true>();
+    test_nullptr<true>();
     test_sfinae<true>();
     test_sfinae_runtime();
     test_noexcept<true>();

Modified: libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.dtor/null.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.dtor/null.pass.cpp?rev=300406&r1=300405&r2=300406&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.dtor/null.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.dtor/null.pass.cpp Sat Apr 15 20:51:04 2017
@@ -35,8 +35,8 @@ void test_basic() {
   Deleter d;
   assert(d.state() == 0);
   {
-    std::unique_ptr<T, Deleter&> p(0, d);
-    assert(p.get() == 0);
+    std::unique_ptr<T, Deleter&> p(nullptr, d);
+    assert(p.get() == nullptr);
     assert(&p.get_deleter() == &d);
   }
   assert(d.state() == 0);

Modified: libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.modifiers/release.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.modifiers/release.pass.cpp?rev=300406&r1=300405&r2=300406&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.modifiers/release.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.modifiers/release.pass.cpp Sat Apr 15 20:51:04 2017
@@ -16,12 +16,20 @@
 #include <memory>
 #include <cassert>
 
+#include "test_macros.h"
 #include "unique_ptr_test_helper.h"
 
 template <bool IsArray>
 void test_basic() {
   typedef typename std::conditional<IsArray, A[], A>::type VT;
   const int expect_alive = IsArray ? 3 : 1;
+#if TEST_STD_VER >= 11
+  {
+    using U = std::unique_ptr<VT>;
+    U u; ((void)u);
+    ASSERT_NOEXCEPT(u.release());
+  }
+#endif
   {
     std::unique_ptr<VT> p(newValue<VT>(expect_alive));
     assert(A::count == expect_alive);

Modified: libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.modifiers/reset.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.modifiers/reset.pass.cpp?rev=300406&r1=300405&r2=300406&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.modifiers/reset.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.modifiers/reset.pass.cpp Sat Apr 15 20:51:04 2017
@@ -16,36 +16,102 @@
 #include <memory>
 #include <cassert>
 
+#include "test_macros.h"
 #include "unique_ptr_test_helper.h"
 
 template <bool IsArray>
-void test_basic() {
+void test_reset_pointer() {
   typedef typename std::conditional<IsArray, A[], A>::type VT;
   const int expect_alive = IsArray ? 3 : 1;
+#if TEST_STD_VER >= 11
+  {
+    using U = std::unique_ptr<VT>;
+    U u; ((void)u);
+    ASSERT_NOEXCEPT(u.reset((A*)nullptr));
+  }
+#endif
   {
     std::unique_ptr<VT> p(newValue<VT>(expect_alive));
     assert(A::count == expect_alive);
     A* i = p.get();
     assert(i != nullptr);
-    p.reset();
-    assert(A::count == 0);
-    assert(p.get() == 0);
+    A* new_value = newValue<VT>(expect_alive);
+    assert(A::count == (expect_alive * 2));
+    p.reset(new_value);
+    assert(A::count == expect_alive);
+    assert(p.get() == new_value);
   }
   assert(A::count == 0);
   {
-    std::unique_ptr<VT> p(newValue<VT>(expect_alive));
+    std::unique_ptr<const VT> p(newValue<const VT>(expect_alive));
     assert(A::count == expect_alive);
-    A* i = p.get();
+    const A* i = p.get();
     assert(i != nullptr);
     A* new_value = newValue<VT>(expect_alive);
     assert(A::count == (expect_alive * 2));
     p.reset(new_value);
     assert(A::count == expect_alive);
+    assert(p.get() == new_value);
+  }
+  assert(A::count == 0);
+}
+
+template <bool IsArray>
+void test_reset_nullptr() {
+  typedef typename std::conditional<IsArray, A[], A>::type VT;
+  const int expect_alive = IsArray ? 3 : 1;
+#if TEST_STD_VER >= 11
+  {
+    using U = std::unique_ptr<VT>;
+    U u; ((void)u);
+    ASSERT_NOEXCEPT(u.reset(nullptr));
+  }
+#endif
+  {
+    std::unique_ptr<VT> p(newValue<VT>(expect_alive));
+    assert(A::count == expect_alive);
+    A* i = p.get();
+    assert(i != nullptr);
+    p.reset(nullptr);
+    assert(A::count == 0);
+    assert(p.get() == nullptr);
+  }
+  assert(A::count == 0);
+}
+
+
+template <bool IsArray>
+void test_reset_no_arg() {
+  typedef typename std::conditional<IsArray, A[], A>::type VT;
+  const int expect_alive = IsArray ? 3 : 1;
+#if TEST_STD_VER >= 11
+  {
+    using U = std::unique_ptr<VT>;
+    U u; ((void)u);
+    ASSERT_NOEXCEPT(u.reset());
+  }
+#endif
+  {
+    std::unique_ptr<VT> p(newValue<VT>(expect_alive));
+    assert(A::count == expect_alive);
+    A* i = p.get();
+    assert(i != nullptr);
+    p.reset();
+    assert(A::count == 0);
+    assert(p.get() == nullptr);
   }
   assert(A::count == 0);
 }
 
 int main() {
-  test_basic</*IsArray*/ false>();
-  test_basic<true>();
+  {
+    test_reset_pointer</*IsArray*/ false>();
+    test_reset_nullptr<false>();
+    test_reset_no_arg<false>();
+  }
+  {
+    test_reset_pointer</*IsArray*/true>();
+    test_reset_nullptr<true>();
+    test_reset_no_arg<true>();
+  }
 }

Modified: libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.modifiers/swap.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.modifiers/swap.pass.cpp?rev=300406&r1=300405&r2=300406&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.modifiers/swap.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.modifiers/swap.pass.cpp Sat Apr 15 20:51:04 2017
@@ -16,6 +16,7 @@
 #include <memory>
 #include <cassert>
 
+#include "test_macros.h"
 #include "unique_ptr_test_helper.h"
 
 struct TT {
@@ -51,6 +52,13 @@ template <bool IsArray>
 void test_basic() {
   typedef typename std::conditional<IsArray, TT[], TT>::type VT;
   const int expect_alive = IsArray ? 5 : 1;
+#if TEST_STD_VER >= 11
+  {
+    using U = std::unique_ptr<VT, Deleter<VT> >;
+    U u; ((void)u);
+    ASSERT_NOEXCEPT(u.swap(u));
+  }
+#endif
   {
     TT* p1 = newValueInit<VT>(expect_alive, 1);
     std::unique_ptr<VT, Deleter<VT> > s1(p1, Deleter<VT>(1));

Modified: libcxx/trunk/test/support/deleter_types.h
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/support/deleter_types.h?rev=300406&r1=300405&r2=300406&view=diff
==============================================================================
--- libcxx/trunk/test/support/deleter_types.h (original)
+++ libcxx/trunk/test/support/deleter_types.h Sat Apr 15 20:51:04 2017
@@ -193,6 +193,10 @@ public:
 
     CDeleter() : state_(0) {}
     explicit CDeleter(int s) : state_(s) {}
+    template <class U>
+        CDeleter(const CDeleter<U>& d)
+            : state_(d.state()) {}
+
     ~CDeleter() {assert(state_ >= 0); state_ = -1;}
 
     int state() const {return state_;}

Modified: libcxx/trunk/test/support/test_workarounds.h
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/support/test_workarounds.h?rev=300406&r1=300405&r2=300406&view=diff
==============================================================================
--- libcxx/trunk/test/support/test_workarounds.h (original)
+++ libcxx/trunk/test/support/test_workarounds.h Sat Apr 15 20:51:04 2017
@@ -17,12 +17,4 @@
 # define TEST_WORKAROUND_C1XX_BROKEN_NULLPTR_CONVERSION_OPERATOR
 #endif
 
-// FIXME(EricWF): Remove this. This macro guards tests for upcoming changes
-// and fixes to unique_ptr. Until the changes have been implemented in trunk
-// the tests have to be disabled. However the tests have been left in until
-// then so they can be used by other standard libraries.
-#if defined(_LIBCPP_VERSION)
-# define TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES
-#endif
-
 #endif // SUPPORT_TEST_WORKAROUNDS_H

Modified: libcxx/trunk/www/cxx1z_status.html
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/www/cxx1z_status.html?rev=300406&r1=300405&r2=300406&view=diff
==============================================================================
--- libcxx/trunk/www/cxx1z_status.html (original)
+++ libcxx/trunk/www/cxx1z_status.html Sat Apr 15 20:51:04 2017
@@ -448,7 +448,7 @@
 	<tr><td><a href="http://wg21.link/LWG2794">2794</a></td><td>Missing requirements for allocator pointers</td><td>Kona</td><td></td></tr>
 	<tr><td><a href="http://wg21.link/LWG2795">2795</a></td><td>§[global.functions] provides incorrect example of ADL use</td><td>Kona</td><td>Complete</td></tr>
 	<tr><td><a href="http://wg21.link/LWG2796">2796</a></td><td>tuple should be a literal type</td><td>Kona</td><td></td></tr>
-	<tr><td><a href="http://wg21.link/LWG2801">2801</a></td><td>Default-constructibility of unique_ptr</td><td>Kona</td><td></td></tr>
+	<tr><td><a href="http://wg21.link/LWG2801">2801</a></td><td>Default-constructibility of unique_ptr</td><td>Kona</td><td>Complete</td></tr>
 	<tr><td><a href="http://wg21.link/LWG2802">2802</a></td><td>shared_ptr constructor requirements for a deleter</td><td>Kona</td><td></td></tr>
 	<tr><td><a href="http://wg21.link/LWG2804">2804</a></td><td>Unconditional constexpr default constructor for istream_iterator</td><td>Kona</td><td>Complete</td></tr>
 	<tr><td><a href="http://wg21.link/LWG2806">2806</a></td><td>Base class of bad_optional_access</td><td>Kona</td><td>Complete</td></tr>
@@ -478,7 +478,7 @@
 	<tr><td><a href="http://wg21.link/LWG2900">2900</a></td><td>The copy and move constructors of optional are not constexpr</td><td>Kona</td><td></td></tr>
 	<tr><td><a href="http://wg21.link/LWG2903">2903</a></td><td>The form of initialization for the emplace-constructors is not specified</td><td>Kona</td><td></td></tr>
 	<tr><td><a href="http://wg21.link/LWG2904">2904</a></td><td>Make variant move-assignment more exception safe</td><td>Kona</td><td></td></tr>
-	<tr><td><a href="http://wg21.link/LWG2905">2905</a></td><td>is_constructible_v<unique_ptr<P, D>, P, D const &> should be false when D is not copy constructible</td><td>Kona</td><td></td></tr>
+	<tr><td><a href="http://wg21.link/LWG2905">2905</a></td><td>is_constructible_v<unique_ptr<P, D>, P, D const &> should be false when D is not copy constructible</td><td>Kona</td><td>Complete</td></tr>
 	<tr><td><a href="http://wg21.link/LWG2908">2908</a></td><td>The less-than operator for shared pointers could do more</td><td>Kona</td><td></td></tr>
 	<tr><td><a href="http://wg21.link/LWG2911">2911</a></td><td>An is_aggregate type trait is needed</td><td>Kona</td><td>Complete</td></tr>
 	<tr><td><a href="http://wg21.link/LWG2921">2921</a></td><td>packaged_task and type-erased allocators</td><td>Kona</td><td></td></tr>




More information about the cfe-commits mailing list