<div dir="ltr">Hi Eric,<div><br></div><div>Renaming _<span style="font-size:12.800000190734863px">_compressed_pair_elem's member from __first_ to __value_ has broken a lot of LLDB's data formatters. Would it be possible to rename it back for consistency? If it's just a rename it would be preferable to the alternative, which would be to add some clumsy fallback logic in LLDB:</span></div><div><span style="font-size:12.800000190734863px"><br></span></div><div><span style="font-size:12.800000190734863px">if (auto *Entry = find_element("__first_"))</span></div><div><span style="font-size:12.800000190734863px">  // ...</span></div><div><span style="font-size:12.800000190734863px">else if (auto *Entry = find_element("__value_"))</span></div><div><span style="font-size:12.800000190734863px">  // ...</span></div><div><span style="font-size:12.800000190734863px">else</span></div><div><span style="font-size:12.800000190734863px">  // ...</span></div><div><span style="font-size:12.800000190734863px"><br></span></div><div><span style="font-size:12.800000190734863px">Cheers,</span></div><div><span style="font-size:12.800000190734863px">Lang.</span></div><div><span style="font-size:12.800000190734863px"><br></span></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Apr 12, 2017 at 4:45 PM, Eric Fiselier via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: ericwf<br>
Date: Wed Apr 12 18:45:53 2017<br>
New Revision: 300140<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=300140&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=300140&view=rev</a><br>
Log:<br>
[libcxx] Fix __compressed_pair so it doesn't copy the argument multiple times, and add constexpr.<br>
<br>
Summary:<br>
__compressed_pair takes and passes it's constructor arguments by value. This causes arguments to be moved 3 times instead of once. This patch addresses that issue and fixes `constexpr` on the constructors.<br>
<br>
I would rather have this fix than D27564, and I'm fairly confident it's not ABI breaking but I'm not 100% sure.<br>
<br>
I prefer this solution because it removes a lot of code and makes the implementation *much* smaller.<br>
<br>
Reviewers: mclow.lists, K-ballo<br>
<br>
Reviewed By: K-ballo<br>
<br>
Subscribers: K-ballo, cfe-commits<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D27565" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D27565</a><br>
<br>
Modified:<br>
    libcxx/trunk/include/__hash_<wbr>table<br>
    libcxx/trunk/include/memory<br>
    libcxx/trunk/include/string<br>
    libcxx/trunk/test/std/<wbr>utilities/memory/unique.ptr/<wbr>unique.ptr.runtime/unique.ptr.<wbr>runtime.ctor/default01.fail.<wbr>cpp<br>
<br>
Modified: libcxx/trunk/include/__hash_<wbr>table<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__hash_table?rev=300140&r1=300139&r2=300140&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/libcxx/trunk/include/_<wbr>_hash_table?rev=300140&r1=<wbr>300139&r2=300140&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/include/__hash_<wbr>table (original)<br>
+++ libcxx/trunk/include/__hash_<wbr>table Wed Apr 12 18:45:53 2017<br>
@@ -1402,7 +1402,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc><br>
                                                        const key_equal& __eql,<br>
                                                        const allocator_type& __a)<br>
     : __bucket_list_(nullptr, __bucket_list_deleter(__<wbr>pointer_allocator(__a), 0)),<br>
-      __p1_(__node_allocator(__a)),<br>
+      __p1_(__second_tag(), __node_allocator(__a)),<br>
       __p2_(0, __hf),<br>
       __p3_(1.0f, __eql)<br>
 {<br>
@@ -1411,7 +1411,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc><br>
 template <class _Tp, class _Hash, class _Equal, class _Alloc><br>
 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)<br>
     : __bucket_list_(nullptr, __bucket_list_deleter(__<wbr>pointer_allocator(__a), 0)),<br>
-      __p1_(__node_allocator(__a)),<br>
+      __p1_(__second_tag(), __node_allocator(__a)),<br>
       __p2_(0),<br>
       __p3_(1.0f)<br>
 {<br>
@@ -1423,7 +1423,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc><br>
           __bucket_list_deleter(<wbr>allocator_traits<__pointer_<wbr>allocator>::<br>
               select_on_container_copy_<wbr>construction(<br>
                   __u.__bucket_list_.get_<wbr>deleter().__alloc()), 0)),<br>
-      __p1_(allocator_traits<__node_<wbr>allocator>::<br>
+      __p1_(__second_tag(), allocator_traits<__node_<wbr>allocator>::<br>
           select_on_container_copy_<wbr>construction(__u.__node_alloc(<wbr>))),<br>
       __p2_(0, __u.hash_function()),<br>
       __p3_(__u.__p3_)<br>
@@ -1434,7 +1434,7 @@ template <class _Tp, class _Hash, class<br>
 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u,<br>
                                                        const allocator_type& __a)<br>
     : __bucket_list_(nullptr, __bucket_list_deleter(__<wbr>pointer_allocator(__a), 0)),<br>
-      __p1_(__node_allocator(__a)),<br>
+      __p1_(__second_tag(), __node_allocator(__a)),<br>
       __p2_(0, __u.hash_function()),<br>
       __p3_(__u.__p3_)<br>
 {<br>
@@ -1468,7 +1468,7 @@ template <class _Tp, class _Hash, class<br>
 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_<wbr>table&& __u,<br>
                                                        const allocator_type& __a)<br>
     : __bucket_list_(nullptr, __bucket_list_deleter(__<wbr>pointer_allocator(__a), 0)),<br>
-      __p1_(__node_allocator(__a)),<br>
+      __p1_(__second_tag(), __node_allocator(__a)),<br>
       __p2_(0, _VSTD::move(__u.hash_function(<wbr>))),<br>
       __p3_(_VSTD::move(__u.__p3_))<br>
 {<br>
<br>
Modified: libcxx/trunk/include/memory<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=300140&r1=300139&r2=300140&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/libcxx/trunk/include/<wbr>memory?rev=300140&r1=300139&<wbr>r2=300140&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/include/memory (original)<br>
+++ libcxx/trunk/include/memory Wed Apr 12 18:45:53 2017<br>
@@ -653,7 +653,7 @@ void* align(size_t alignment, size_t siz<br>
 #include <tuple><br>
 #include <stdexcept><br>
 #include <cstring><br>
-<br>
+#include <cassert><br>
 #if !defined(_LIBCPP_HAS_NO_<wbr>ATOMIC_HEADER)<br>
 #  include <atomic><br>
 #endif<br>
@@ -2070,307 +2070,174 @@ public:<br>
 };<br>
 #endif<br>
<br>
-template <class _T1, class _T2, bool = is_same<typename remove_cv<_T1>::type,<br>
-                                                     typename remove_cv<_T2>::type>::value,<br>
-                                bool = is_empty<_T1>::value<br>
-                                       && !__libcpp_is_final<_T1>::<wbr>value,<br>
-                                bool = is_empty<_T2>::value<br>
-                                       && !__libcpp_is_final<_T2>::value<br>
-         ><br>
-struct __libcpp_compressed_pair_<wbr>switch;<br>
-<br>
-template <class _T1, class _T2, bool IsSame><br>
-struct __libcpp_compressed_pair_<wbr>switch<_T1, _T2, IsSame, false, false> {enum {value = 0};};<br>
+template <class _Tp, int _Idx,<br>
+          bool _CanBeEmptyBase =<br>
+              is_empty<_Tp>::value && !__libcpp_is_final<_Tp>::<wbr>value><br>
+struct __compressed_pair_elem {<br>
+  typedef _Tp _ParamT;<br>
+  typedef _Tp& reference;<br>
+  typedef const _Tp& const_reference;<br>
<br>
-template <class _T1, class _T2, bool IsSame><br>
-struct __libcpp_compressed_pair_<wbr>switch<_T1, _T2, IsSame, true, false>  {enum {value = 1};};<br>
-<br>
-template <class _T1, class _T2, bool IsSame><br>
-struct __libcpp_compressed_pair_<wbr>switch<_T1, _T2, IsSame, false, true>  {enum {value = 2};};<br>
-<br>
-template <class _T1, class _T2><br>
-struct __libcpp_compressed_pair_<wbr>switch<_T1, _T2, false, true, true>    {enum {value = 3};};<br>
+#ifndef _LIBCPP_CXX03_LANG<br>
+  __compressed_pair_elem() = default;<br>
<br>
-template <class _T1, class _T2><br>
-struct __libcpp_compressed_pair_<wbr>switch<_T1, _T2, true, true, true>     {enum {value = 1};};<br>
+  template <class _Up, class = typename enable_if<<br>
+                           !is_same<__compressed_pair_<wbr>elem, _Up>::value>::type><br>
+  _LIBCPP_CONSTEXPR explicit<br>
+  __compressed_pair_elem(_Up&& __u)<br>
+      : __value_(_VSTD::forward<_Up>(_<wbr>_u)){};<br>
+<br>
+  template <class... _Args, size_t... _Indexes><br>
+  _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14<br>
+  __compressed_pair_elem(<wbr>piecewise_construct_t, tuple<_Args...> __args,<br>
+                         __tuple_indices<_Indexes...>)<br>
+      : __value_(_VSTD::forward<_Args><wbr>(_VSTD::get<_Indexes>(__args))<wbr>...) {}<br>
+#else<br>
+  __compressed_pair_elem() : __value_() {}<br>
+  __compressed_pair_elem(_ParamT __p) : __value_(std::forward<_ParamT><wbr>(__p)) {}<br>
+#endif<br>
<br>
-template <class _T1, class _T2, unsigned = __libcpp_compressed_pair_<wbr>switch<_T1, _T2>::value><br>
-class __libcpp_compressed_pair_imp;<br>
+  reference __get() _NOEXCEPT { return __value_; }<br>
+  const_reference __get() const _NOEXCEPT { return __value_; }<br>
<br>
-template <class _T1, class _T2><br>
-class __libcpp_compressed_pair_imp<_<wbr>T1, _T2, 0><br>
-{<br>
 private:<br>
-    _T1 __first_;<br>
-    _T2 __second_;<br>
-public:<br>
-    typedef _T1 _T1_param;<br>
-    typedef _T2 _T2_param;<br>
-<br>
-    typedef typename remove_reference<_T1>::type& _T1_reference;<br>
-    typedef typename remove_reference<_T2>::type& _T2_reference;<br>
-<br>
-    typedef typename remove_reference<typename add_const<_T1>::type>::type& _T1_const_reference;<br>
-    typedef typename remove_reference<typename add_const<_T2>::type>::type& _T2_const_reference;<br>
-<br>
-    _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp() : __first_(), __second_() {}<br>
-    _LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_<wbr>T1_param __t1)<br>
-        : __first_(_VSTD::forward<_T1_<wbr>param>(__t1)), __second_() {}<br>
-    _LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_<wbr>T2_param __t2)<br>
-        : __first_(), __second_(_VSTD::forward<_T2_<wbr>param>(__t2)) {}<br>
-    _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(_<wbr>T1_param __t1, _T2_param __t2)<br>
-        : __first_(_VSTD::forward<_T1_<wbr>param>(__t1)), __second_(_VSTD::forward<_T2_<wbr>param>(__t2)) {}<br>
-<br>
-#ifndef _LIBCPP_HAS_NO_VARIADICS<br>
-<br>
-    template <class... _Args1, class... _Args2, size_t... _I1, size_t... _I2><br>
-        _LIBCPP_INLINE_VISIBILITY<br>
-        __libcpp_compressed_pair_imp(<wbr>piecewise_construct_t,<br>
-                                     tuple<_Args1...> __first_args,<br>
-                                     tuple<_Args2...> __second_args,<br>
-                                     __tuple_indices<_I1...>,<br>
-                                     __tuple_indices<_I2...>)<br>
-            : __first_(_VSTD::forward<_<wbr>Args1>(_VSTD::get<_I1>(__<wbr>first_args))...),<br>
-              __second_(_VSTD::forward<_<wbr>Args2>(_VSTD::get<_I2>(__<wbr>second_args))...)<br>
-            {}<br>
-<br>
-#endif  // _LIBCPP_HAS_NO_VARIADICS<br>
-<br>
-    _LIBCPP_INLINE_VISIBILITY _T1_reference       first() _NOEXCEPT       {return __first_;}<br>
-    _LIBCPP_INLINE_VISIBILITY _T1_const_reference first() const _NOEXCEPT {return __first_;}<br>
-<br>
-    _LIBCPP_INLINE_VISIBILITY _T2_reference       second() _NOEXCEPT       {return __second_;}<br>
-    _LIBCPP_INLINE_VISIBILITY _T2_const_reference second() const _NOEXCEPT {return __second_;}<br>
-<br>
-    _LIBCPP_INLINE_VISIBILITY void swap(__libcpp_compressed_pair_<wbr>imp& __x)<br>
-        _NOEXCEPT_(__is_nothrow_<wbr>swappable<_T1>::value &&<br>
-                   __is_nothrow_swappable<_T2>::<wbr>value)<br>
-    {<br>
-        using _VSTD::swap;<br>
-        swap(__first_, __x.__first_);<br>
-        swap(__second_, __x.__second_);<br>
-    }<br>
+  _Tp __value_;<br>
 };<br>
<br>
-template <class _T1, class _T2><br>
-class __libcpp_compressed_pair_imp<_<wbr>T1, _T2, 1><br>
-    : private _T1<br>
-{<br>
-private:<br>
-    _T2 __second_;<br>
-public:<br>
-    typedef _T1 _T1_param;<br>
-    typedef _T2 _T2_param;<br>
-<br>
-    typedef _T1&                                        _T1_reference;<br>
-    typedef typename remove_reference<_T2>::type& _T2_reference;<br>
+template <class _Tp, int _Idx><br>
+struct __compressed_pair_elem<_Tp, _Idx, true> : private _Tp {<br>
+  typedef _Tp _ParamT;<br>
+  typedef _Tp& reference;<br>
+  typedef const _Tp& const_reference;<br>
+  typedef _Tp __value_type;<br>
<br>
-    typedef const _T1&                                        _T1_const_reference;<br>
-    typedef typename remove_reference<typename add_const<_T2>::type>::type&<br>
-        _T2_const_reference;<br>
-<br>
-    _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp() : __second_() {}<br>
-    _LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_<wbr>T1_param __t1)<br>
-        : _T1(_VSTD::forward<_T1_param>(<wbr>__t1)), __second_() {}<br>
-    _LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_<wbr>T2_param __t2)<br>
-        : __second_(_VSTD::forward<_T2_<wbr>param>(__t2)) {}<br>
-    _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(_<wbr>T1_param __t1, _T2_param __t2)<br>
-        : _T1(_VSTD::forward<_T1_param>(<wbr>__t1)), __second_(_VSTD::forward<_T2_<wbr>param>(__t2)) {}<br>
-<br>
-#ifndef _LIBCPP_HAS_NO_VARIADICS<br>
-<br>
-    template <class... _Args1, class... _Args2, size_t... _I1, size_t... _I2><br>
-        _LIBCPP_INLINE_VISIBILITY<br>
-        __libcpp_compressed_pair_imp(<wbr>piecewise_construct_t,<br>
-                                     tuple<_Args1...> __first_args,<br>
-                                     tuple<_Args2...> __second_args,<br>
-                                     __tuple_indices<_I1...>,<br>
-                                     __tuple_indices<_I2...>)<br>
-            : _T1(_VSTD::forward<_Args1>(_<wbr>VSTD::get<_I1>(__first_args)).<wbr>..),<br>
-              __second_(_VSTD::forward<_<wbr>Args2>(_VSTD::get<_I2>(__<wbr>second_args))...)<br>
-            {}<br>
-<br>
-#endif  // _LIBCPP_HAS_NO_VARIADICS<br>
-<br>
-    _LIBCPP_INLINE_VISIBILITY _T1_reference       first() _NOEXCEPT       {return *this;}<br>
-    _LIBCPP_INLINE_VISIBILITY _T1_const_reference first() const _NOEXCEPT {return *this;}<br>
+#ifndef _LIBCPP_CXX03_LANG<br>
+  __compressed_pair_elem() = default;<br>
<br>
-    _LIBCPP_INLINE_VISIBILITY _T2_reference       second() _NOEXCEPT       {return __second_;}<br>
-    _LIBCPP_INLINE_VISIBILITY _T2_const_reference second() const _NOEXCEPT {return __second_;}<br>
+  template <class _Up, class = typename enable_if<<br>
+                           !is_same<__compressed_pair_<wbr>elem, _Up>::value>::type><br>
+  _LIBCPP_CONSTEXPR explicit<br>
+  __compressed_pair_elem(_Up&& __u)<br>
+      : __value_type(_VSTD::forward<_<wbr>Up>(__u)){};<br>
+<br>
+  template <class... _Args, size_t... _Indexes><br>
+  _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14<br>
+  __compressed_pair_elem(<wbr>piecewise_construct_t, tuple<_Args...> __args,<br>
+                         __tuple_indices<_Indexes...>)<br>
+      : __value_type(_VSTD::forward<_<wbr>Args>(_VSTD::get<_Indexes>(__<wbr>args))...) {}<br>
+#else<br>
+  __compressed_pair_elem() : __value_type() {}<br>
+  __compressed_pair_elem(_ParamT __p)<br>
+      : __value_type(std::forward<_<wbr>ParamT>(__p)) {}<br>
+#endif<br>
<br>
-    _LIBCPP_INLINE_VISIBILITY void swap(__libcpp_compressed_pair_<wbr>imp& __x)<br>
-        _NOEXCEPT_(__is_nothrow_<wbr>swappable<_T1>::value &&<br>
-                   __is_nothrow_swappable<_T2>::<wbr>value)<br>
-    {<br>
-        using _VSTD::swap;<br>
-        swap(__second_, __x.__second_);<br>
-    }<br>
+  reference __get() _NOEXCEPT { return *this; }<br>
+  const_reference __get() const _NOEXCEPT { return *this; }<br>
 };<br>
<br>
-template <class _T1, class _T2><br>
-class __libcpp_compressed_pair_imp<_<wbr>T1, _T2, 2><br>
-    : private _T2<br>
-{<br>
-private:<br>
-    _T1 __first_;<br>
-public:<br>
-    typedef _T1 _T1_param;<br>
-    typedef _T2 _T2_param;<br>
-<br>
-    typedef typename remove_reference<_T1>::type& _T1_reference;<br>
-    typedef _T2&                                        _T2_reference;<br>
-<br>
-    typedef typename remove_reference<typename add_const<_T1>::type>::type&<br>
-        _T1_const_reference;<br>
-    typedef const _T2&                                        _T2_const_reference;<br>
-<br>
-    _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp() : __first_() {}<br>
-    _LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_<wbr>T1_param __t1)<br>
-        : __first_(_VSTD::forward<_T1_<wbr>param>(__t1)) {}<br>
-    _LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_<wbr>T2_param __t2)<br>
-        : _T2(_VSTD::forward<_T2_param>(<wbr>__t2)), __first_() {}<br>
-    _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(_<wbr>T1_param __t1, _T2_param __t2)<br>
-        _NOEXCEPT_(is_nothrow_move_<wbr>constructible<_T1>::value &&<br>
-                   is_nothrow_move_constructible<<wbr>_T2>::value)<br>
-        : _T2(_VSTD::forward<_T2_param>(<wbr>__t2)), __first_(_VSTD::forward<_T1_<wbr>param>(__t1)) {}<br>
-<br>
-#ifndef _LIBCPP_HAS_NO_VARIADICS<br>
-<br>
-    template <class... _Args1, class... _Args2, size_t... _I1, size_t... _I2><br>
-        _LIBCPP_INLINE_VISIBILITY<br>
-        __libcpp_compressed_pair_imp(<wbr>piecewise_construct_t,<br>
-                                     tuple<_Args1...> __first_args,<br>
-                                     tuple<_Args2...> __second_args,<br>
-                                     __tuple_indices<_I1...>,<br>
-                                     __tuple_indices<_I2...>)<br>
-            : _T2(_VSTD::forward<_Args2>(_<wbr>VSTD::get<_I2>(__second_args))<wbr>...),<br>
-              __first_(_VSTD::forward<_<wbr>Args1>(_VSTD::get<_I1>(__<wbr>first_args))...)<br>
-<br>
-            {}<br>
-<br>
-#endif  // _LIBCPP_HAS_NO_VARIADICS<br>
-<br>
-    _LIBCPP_INLINE_VISIBILITY _T1_reference       first() _NOEXCEPT       {return __first_;}<br>
-    _LIBCPP_INLINE_VISIBILITY _T1_const_reference first() const _NOEXCEPT {return __first_;}<br>
-<br>
-    _LIBCPP_INLINE_VISIBILITY _T2_reference       second() _NOEXCEPT       {return *this;}<br>
-    _LIBCPP_INLINE_VISIBILITY _T2_const_reference second() const _NOEXCEPT {return *this;}<br>
-<br>
-    _LIBCPP_INLINE_VISIBILITY void swap(__libcpp_compressed_pair_<wbr>imp& __x)<br>
-        _NOEXCEPT_(__is_nothrow_<wbr>swappable<_T1>::value &&<br>
-                   __is_nothrow_swappable<_T2>::<wbr>value)<br>
-    {<br>
-        using _VSTD::swap;<br>
-        swap(__first_, __x.__first_);<br>
-    }<br>
-};<br>
+// Tag used to construct the second element of the compressed pair.<br>
+struct __second_tag {};<br>
<br>
 template <class _T1, class _T2><br>
-class __libcpp_compressed_pair_imp<_<wbr>T1, _T2, 3><br>
-    : private _T1,<br>
-      private _T2<br>
-{<br>
-public:<br>
-    typedef _T1 _T1_param;<br>
-    typedef _T2 _T2_param;<br>
-<br>
-    typedef _T1& _T1_reference;<br>
-    typedef _T2& _T2_reference;<br>
-<br>
-    typedef const _T1& _T1_const_reference;<br>
-    typedef const _T2& _T2_const_reference;<br>
-<br>
-    _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp() {}<br>
-    _LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_<wbr>T1_param __t1)<br>
-        : _T1(_VSTD::forward<_T1_param>(<wbr>__t1)) {}<br>
-    _LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_<wbr>T2_param __t2)<br>
-        : _T2(_VSTD::forward<_T2_param>(<wbr>__t2)) {}<br>
-    _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(_<wbr>T1_param __t1, _T2_param __t2)<br>
-        : _T1(_VSTD::forward<_T1_param>(<wbr>__t1)), _T2(_VSTD::forward<_T2_param>(<wbr>__t2)) {}<br>
-<br>
-#ifndef _LIBCPP_HAS_NO_VARIADICS<br>
-<br>
-    template <class... _Args1, class... _Args2, size_t... _I1, size_t... _I2><br>
-        _LIBCPP_INLINE_VISIBILITY<br>
-        __libcpp_compressed_pair_imp(<wbr>piecewise_construct_t,<br>
-                                     tuple<_Args1...> __first_args,<br>
-                                     tuple<_Args2...> __second_args,<br>
-                                     __tuple_indices<_I1...>,<br>
-                                     __tuple_indices<_I2...>)<br>
-            : _T1(_VSTD::forward<_Args1>(_<wbr>VSTD::get<_I1>(__first_args)).<wbr>..),<br>
-              _T2(_VSTD::forward<_Args2>(_<wbr>VSTD::get<_I2>(__second_args))<wbr>...)<br>
-            {}<br>
+class __compressed_pair : private __compressed_pair_elem<_T1, 0>,<br>
+                          private __compressed_pair_elem<_T2, 1> {<br>
+  typedef __compressed_pair_elem<_T1, 0> _Base1;<br>
+  typedef __compressed_pair_elem<_T2, 1> _Base2;<br>
+<br>
+  // NOTE: This static assert should never fire because __compressed_pair<br>
+  // is *almost never* used in a scenario where it's possible for T1 == T2.<br>
+  // (The exception is std::function where it is possible that the function<br>
+  //  object and the allocator have the same type).<br>
+  static_assert(!is_same<_T1, _T2>::value,<br>
+    "__compressed_pair cannot be instantated when T1 and T2 are the same type; "<br>
+    "The current implementation is NOT ABI-compatible with the previous "<br>
+    "implementation for this configuration");<br>
<br>
-#endif  // _LIBCPP_HAS_NO_VARIADICS<br>
-<br>
-    _LIBCPP_INLINE_VISIBILITY _T1_reference       first() _NOEXCEPT       {return *this;}<br>
-    _LIBCPP_INLINE_VISIBILITY _T1_const_reference first() const _NOEXCEPT {return *this;}<br>
-<br>
-    _LIBCPP_INLINE_VISIBILITY _T2_reference       second() _NOEXCEPT       {return *this;}<br>
-    _LIBCPP_INLINE_VISIBILITY _T2_const_reference second() const _NOEXCEPT {return *this;}<br>
-<br>
-    _LIBCPP_INLINE_VISIBILITY void swap(__libcpp_compressed_pair_<wbr>imp&)<br>
-        _NOEXCEPT_(__is_nothrow_<wbr>swappable<_T1>::value &&<br>
-                   __is_nothrow_swappable<_T2>::<wbr>value)<br>
-    {<br>
-    }<br>
-};<br>
-<br>
-template <class _T1, class _T2><br>
-class __compressed_pair<br>
-    : private __libcpp_compressed_pair_imp<_<wbr>T1, _T2><br>
-{<br>
-    typedef __libcpp_compressed_pair_imp<_<wbr>T1, _T2> base;<br>
 public:<br>
-    typedef typename base::_T1_param _T1_param;<br>
-    typedef typename base::_T2_param _T2_param;<br>
-<br>
-    typedef typename base::_T1_reference _T1_reference;<br>
-    typedef typename base::_T2_reference _T2_reference;<br>
-<br>
-    typedef typename base::_T1_const_reference _T1_const_reference;<br>
-    typedef typename base::_T2_const_reference _T2_const_reference;<br>
-<br>
-    _LIBCPP_INLINE_VISIBILITY __compressed_pair() {}<br>
-    _LIBCPP_INLINE_VISIBILITY explicit __compressed_pair(_T1_param __t1)<br>
-        : base(_VSTD::forward<_T1_param><wbr>(__t1)) {}<br>
-    _LIBCPP_INLINE_VISIBILITY explicit __compressed_pair(_T2_param __t2)<br>
-        : base(_VSTD::forward<_T2_param><wbr>(__t2)) {}<br>
-    _LIBCPP_INLINE_VISIBILITY __compressed_pair(_T1_param __t1, _T2_param __t2)<br>
-        : base(_VSTD::forward<_T1_param><wbr>(__t1), _VSTD::forward<_T2_param>(__<wbr>t2)) {}<br>
+#ifndef _LIBCPP_CXX03_LANG<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  __compressed_pair() = default;<br>
<br>
-#ifndef _LIBCPP_HAS_NO_VARIADICS<br>
+  template <class _Tp, typename enable_if<!is_same<typename decay<_Tp>::type,<br>
+                                                   __compressed_pair>::value,<br>
+                                          bool>::type = true><br>
+  _LIBCPP_INLINE_VISIBILITY constexpr explicit<br>
+  __compressed_pair(_Tp&& __t)<br>
+      : _Base1(std::forward<_Tp>(__t))<wbr>, _Base2() {}<br>
+<br>
+  template <class _Tp><br>
+  _LIBCPP_INLINE_VISIBILITY constexpr<br>
+  __compressed_pair(__second_<wbr>tag, _Tp&& __t)<br>
+      : _Base1(), _Base2(std::forward<_Tp>(__t)) {}<br>
+<br>
+  template <class _U1, class _U2><br>
+  _LIBCPP_INLINE_VISIBILITY constexpr<br>
+  __compressed_pair(_U1&& __t1, _U2&& __t2)<br>
+      : _Base1(std::forward<_U1>(__t1)<wbr>), _Base2(std::forward<_U2>(__t2)<wbr>) {}<br>
+<br>
+  template <class... _Args1, class... _Args2><br>
+  _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14<br>
+  __compressed_pair(piecewise_<wbr>construct_t __pc, tuple<_Args1...> __first_args,<br>
+                    tuple<_Args2...> __second_args)<br>
+      : _Base1(__pc, _VSTD::move(__first_args),<br>
+               typename __make_tuple_indices<sizeof...<wbr>(_Args1)>::type()),<br>
+        _Base2(__pc, _VSTD::move(__second_args),<br>
+               typename __make_tuple_indices<sizeof...<wbr>(_Args2)>::type()) {}<br>
<br>
-    template <class... _Args1, class... _Args2><br>
-        _LIBCPP_INLINE_VISIBILITY<br>
-        __compressed_pair(piecewise_<wbr>construct_t __pc, tuple<_Args1...> __first_args,<br>
-                                                      tuple<_Args2...> __second_args)<br>
-            : base(__pc, _VSTD::move(__first_args), _VSTD::move(__second_args),<br>
-                   typename __make_tuple_indices<sizeof...<wbr>(_Args1)>::type(),<br>
-                   typename __make_tuple_indices<sizeof...<wbr>(_Args2) >::type())<br>
-            {}<br>
-<br>
-#endif  // _LIBCPP_HAS_NO_VARIADICS<br>
+#else<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  __compressed_pair() {}<br>
<br>
-    _LIBCPP_INLINE_VISIBILITY _T1_reference       first() _NOEXCEPT       {return base::first();}<br>
-    _LIBCPP_INLINE_VISIBILITY _T1_const_reference first() const _NOEXCEPT {return base::first();}<br>
+  _LIBCPP_INLINE_VISIBILITY explicit<br>
+  __compressed_pair(_T1 __t1) : _Base1(_VSTD::forward<_T1>(__<wbr>t1)) {}<br>
<br>
-    _LIBCPP_INLINE_VISIBILITY _T2_reference       second() _NOEXCEPT       {return base::second();}<br>
-    _LIBCPP_INLINE_VISIBILITY _T2_const_reference second() const _NOEXCEPT {return base::second();}<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  __compressed_pair(__second_<wbr>tag, _T2 __t2)<br>
+      : _Base1(), _Base2(_VSTD::forward<_T2>(__<wbr>t2)) {}<br>
+<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  __compressed_pair(_T1 __t1, _T2 __t2)<br>
+      : _Base1(_VSTD::forward<_T1>(__<wbr>t1)), _Base2(_VSTD::forward<_T2>(__<wbr>t2)) {}<br>
+#endif<br>
<br>
-    _LIBCPP_INLINE_VISIBILITY void swap(__compressed_pair& __x)<br>
-        _NOEXCEPT_(__is_nothrow_<wbr>swappable<_T1>::value &&<br>
-                   __is_nothrow_swappable<_T2>::<wbr>value)<br>
-        {base::swap(__x);}<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  typename _Base1::reference first() _NOEXCEPT {<br>
+    return static_cast<_Base1&>(*this).__<wbr>get();<br>
+  }<br>
+<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  typename _Base1::const_reference first() const _NOEXCEPT {<br>
+    return static_cast<_Base1 const&>(*this).__get();<br>
+  }<br>
+<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  typename _Base2::reference second() _NOEXCEPT {<br>
+    return static_cast<_Base2&>(*this).__<wbr>get();<br>
+  }<br>
+<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  typename _Base2::const_reference second() const _NOEXCEPT {<br>
+    return static_cast<_Base2 const&>(*this).__get();<br>
+  }<br>
+<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  void swap(__compressed_pair& __x)<br>
+    _NOEXCEPT_(__is_nothrow_<wbr>swappable<_T1>::value &&<br>
+               __is_nothrow_swappable<_T2>::<wbr>value)<br>
+  {<br>
+    using std::swap;<br>
+    swap(first(), __x.first());<br>
+    swap(second(), __x.second());<br>
+  }<br>
 };<br>
<br>
 template <class _T1, class _T2><br>
 inline _LIBCPP_INLINE_VISIBILITY<br>
-void<br>
-swap(__compressed_pair<_T1, _T2>& __x, __compressed_pair<_T1, _T2>& __y)<br>
-        _NOEXCEPT_(__is_nothrow_<wbr>swappable<_T1>::value &&<br>
-                   __is_nothrow_swappable<_T2>::<wbr>value)<br>
-    {__x.swap(__y);}<br>
+void swap(__compressed_pair<_T1, _T2>& __x, __compressed_pair<_T1, _T2>& __y)<br>
+    _NOEXCEPT_(__is_nothrow_<wbr>swappable<_T1>::value &&<br>
+               __is_nothrow_swappable<_T2>::<wbr>value) {<br>
+  __x.swap(__y);<br>
+}<br>
<br>
 // __same_or_less_cv_qualified<br>
<br>
@@ -2401,7 +2268,7 @@ struct __same_or_less_cv_qualified<_<wbr>Ptr1<br>
 template <class _Tp><br>
 struct _LIBCPP_TEMPLATE_VIS default_delete<br>
 {<br>
-#ifndef _LIBCPP_CXX03_LANG<br>
+#ifndef _LIBCPP_HAS_NO_DEFAULTED_<wbr>FUNCTIONS<br>
     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR default_delete() _NOEXCEPT = default;<br>
 #else<br>
     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR default_delete() _NOEXCEPT {}<br>
@@ -2421,7 +2288,7 @@ template <class _Tp><br>
 struct _LIBCPP_TEMPLATE_VIS default_delete<_Tp[]><br>
 {<br>
 public:<br>
-#ifndef _LIBCPP_CXX03_LANG<br>
+#ifndef _LIBCPP_HAS_NO_DEFAULTED_<wbr>FUNCTIONS<br>
     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR default_delete() _NOEXCEPT = default;<br>
 #else<br>
     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR default_delete() _NOEXCEPT {}<br>
<br>
Modified: libcxx/trunk/include/string<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/string?rev=300140&r1=300139&r2=300140&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/libcxx/trunk/include/<wbr>string?rev=300140&r1=300139&<wbr>r2=300140&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/include/string (original)<br>
+++ libcxx/trunk/include/string Wed Apr 12 18:45:53 2017<br>
@@ -1511,7 +1511,7 @@ basic_string<_CharT, _Traits, _Allocator<br>
 #else<br>
         _NOEXCEPT<br>
 #endif<br>
-: __r_(__a)<br>
+: __r_(__second_tag(), __a)<br>
 {<br>
 #if _LIBCPP_DEBUG_LEVEL >= 2<br>
     __get_db()->__insert_c(this);<br>
@@ -1582,7 +1582,7 @@ basic_string<_CharT, _Traits, _Allocator<br>
 template <class _CharT, class _Traits, class _Allocator><br>
 inline _LIBCPP_INLINE_VISIBILITY<br>
 basic_string<_CharT, _Traits, _Allocator>::basic_string(<wbr>const _CharT* __s, const _Allocator& __a)<br>
-    : __r_(__a)<br>
+    : __r_(__second_tag(), __a)<br>
 {<br>
     _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*, allocator) detected nullptr");<br>
     __init(__s, traits_type::length(__s));<br>
@@ -1605,7 +1605,7 @@ basic_string<_CharT, _Traits, _Allocator<br>
 template <class _CharT, class _Traits, class _Allocator><br>
 inline _LIBCPP_INLINE_VISIBILITY<br>
 basic_string<_CharT, _Traits, _Allocator>::basic_string(<wbr>const _CharT* __s, size_type __n, const _Allocator& __a)<br>
-    : __r_(__a)<br>
+    : __r_(__second_tag(), __a)<br>
 {<br>
     _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "basic_string(const char*, n, allocator) detected nullptr");<br>
     __init(__s, __n);<br>
@@ -1616,7 +1616,7 @@ basic_string<_CharT, _Traits, _Allocator<br>
<br>
 template <class _CharT, class _Traits, class _Allocator><br>
 basic_string<_CharT, _Traits, _Allocator>::basic_string(<wbr>const basic_string& __str)<br>
-    : __r_(__alloc_traits::select_<wbr>on_container_copy_<wbr>construction(__str.__alloc()))<br>
+    : __r_(__second_tag(), __alloc_traits::select_on_<wbr>container_copy_construction(__<wbr>str.__alloc()))<br>
 {<br>
     if (!__str.__is_long())<br>
         __r_.first().__r = __str.__r_.first().__r;<br>
@@ -1630,7 +1630,7 @@ basic_string<_CharT, _Traits, _Allocator<br>
 template <class _CharT, class _Traits, class _Allocator><br>
 basic_string<_CharT, _Traits, _Allocator>::basic_string(<br>
     const basic_string& __str, const allocator_type& __a)<br>
-    : __r_(__a)<br>
+    : __r_(__second_tag(), __a)<br>
 {<br>
     if (!__str.__is_long())<br>
         __r_.first().__r = __str.__r_.first().__r;<br>
@@ -1664,7 +1664,7 @@ basic_string<_CharT, _Traits, _Allocator<br>
 template <class _CharT, class _Traits, class _Allocator><br>
 inline _LIBCPP_INLINE_VISIBILITY<br>
 basic_string<_CharT, _Traits, _Allocator>::basic_string(<wbr>basic_string&& __str, const allocator_type& __a)<br>
-    : __r_(__a)<br>
+    : __r_(__second_tag(), __a)<br>
 {<br>
     if (__str.__is_long() && __a != __str.__alloc()) // copy, not move<br>
         __init(_VSTD::__to_raw_<wbr>pointer(__str.__get_long_<wbr>pointer()), __str.__get_long_size());<br>
@@ -1719,7 +1719,7 @@ basic_string<_CharT, _Traits, _Allocator<br>
 template <class _CharT, class _Traits, class _Allocator><br>
 inline _LIBCPP_INLINE_VISIBILITY<br>
 basic_string<_CharT, _Traits, _Allocator>::basic_string(<wbr>size_type __n, _CharT __c, const _Allocator& __a)<br>
-    : __r_(__a)<br>
+    : __r_(__second_tag(), __a)<br>
 {<br>
     __init(__n, __c);<br>
 #if _LIBCPP_DEBUG_LEVEL >= 2<br>
@@ -1731,7 +1731,7 @@ template <class _CharT, class _Traits, c<br>
 basic_string<_CharT, _Traits, _Allocator>::basic_string(<wbr>const basic_string& __str,<br>
                                                         size_type __pos, size_type __n,<br>
                                                         const _Allocator& __a)<br>
-    : __r_(__a)<br>
+    : __r_(__second_tag(), __a)<br>
 {<br>
     size_type __str_sz = __str.size();<br>
     if (__pos > __str_sz)<br>
@@ -1746,7 +1746,7 @@ template <class _CharT, class _Traits, c<br>
 inline _LIBCPP_INLINE_VISIBILITY<br>
 basic_string<_CharT, _Traits, _Allocator>::basic_string(<wbr>const basic_string& __str, size_type __pos,<br>
                                                         const _Allocator& __a)<br>
-    : __r_(__a)<br>
+    : __r_(__second_tag(), __a)<br>
 {<br>
     size_type __str_sz = __str.size();<br>
     if (__pos > __str_sz)<br>
@@ -1762,7 +1762,7 @@ template <class _Tp><br>
 basic_string<_CharT, _Traits, _Allocator>::basic_string(<br>
              const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a,<br>
                         typename enable_if<__can_be_converted_<wbr>to_string_view<_CharT, _Traits, _Tp>::value, void>::type *)<br>
-    : __r_(__a)<br>
+    : __r_(__second_tag(), __a)<br>
 {<br>
        __self_view __sv = __self_view(__t).substr(__pos, __n);<br>
     __init(__sv.data(), __sv.size());<br>
@@ -1784,7 +1784,7 @@ basic_string<_CharT, _Traits, _Allocator<br>
 template <class _CharT, class _Traits, class _Allocator><br>
 inline _LIBCPP_INLINE_VISIBILITY<br>
 basic_string<_CharT, _Traits, _Allocator>::basic_string(__<wbr>self_view __sv, const _Allocator& __a)<br>
-    : __r_(__a)<br>
+    : __r_(__second_tag(), __a)<br>
 {<br>
     __init(__sv.data(), __sv.size());<br>
 #if _LIBCPP_DEBUG_LEVEL >= 2<br>
@@ -1866,7 +1866,7 @@ template<class _InputIterator><br>
 inline _LIBCPP_INLINE_VISIBILITY<br>
 basic_string<_CharT, _Traits, _Allocator>::basic_string(_<wbr>InputIterator __first, _InputIterator __last,<br>
                                                         const allocator_type& __a)<br>
-    : __r_(__a)<br>
+    : __r_(__second_tag(), __a)<br>
 {<br>
     __init(__first, __last);<br>
 #if _LIBCPP_DEBUG_LEVEL >= 2<br>
@@ -1889,10 +1889,10 @@ basic_string<_CharT, _Traits, _Allocator<br>
<br>
 template <class _CharT, class _Traits, class _Allocator><br>
 inline _LIBCPP_INLINE_VISIBILITY<br>
+<br>
 basic_string<_CharT, _Traits, _Allocator>::basic_string(<br>
     initializer_list<_CharT> __il, const _Allocator& __a)<br>
-<br>
-    : __r_(__a)<br>
+    : __r_(__second_tag(), __a)<br>
 {<br>
     __init(__il.begin(), __il.end());<br>
 #if _LIBCPP_DEBUG_LEVEL >= 2<br>
<br>
Modified: libcxx/trunk/test/std/<wbr>utilities/memory/unique.ptr/<wbr>unique.ptr.runtime/unique.ptr.<wbr>runtime.ctor/default01.fail.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/unique.ptr/unique.ptr.runtime/unique.ptr.runtime.ctor/default01.fail.cpp?rev=300140&r1=300139&r2=300140&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/libcxx/trunk/test/std/<wbr>utilities/memory/unique.ptr/<wbr>unique.ptr.runtime/unique.ptr.<wbr>runtime.ctor/default01.fail.<wbr>cpp?rev=300140&r1=300139&r2=<wbr>300140&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/test/std/<wbr>utilities/memory/unique.ptr/<wbr>unique.ptr.runtime/unique.ptr.<wbr>runtime.ctor/default01.fail.<wbr>cpp (original)<br>
+++ libcxx/trunk/test/std/<wbr>utilities/memory/unique.ptr/<wbr>unique.ptr.runtime/unique.ptr.<wbr>runtime.ctor/default01.fail.<wbr>cpp Wed Apr 12 18:45:53 2017<br>
@@ -15,24 +15,25 @@<br>
<br>
 // default unique_ptr ctor should require default Deleter ctor<br>
<br>
-<br>
 #include <memory><br>
+#include "test_macros.h"<br>
<br>
-class Deleter<br>
-{<br>
-    // expected-error@memory:* {{base class 'Deleter' has private default constructor}}<br>
-    // expected-note@memory:* + {{in instantiation of member function}}<br>
-    Deleter() {} // expected-note {{implicitly declared private here}}<br>
+class Deleter {<br>
+  Deleter() {}<br>
<br>
 public:<br>
+  Deleter(Deleter&) {}<br>
+  Deleter& operator=(Deleter&) { return *this; }<br>
<br>
-    Deleter(Deleter&) {}<br>
-    Deleter& operator=(Deleter&) { return *this; }<br>
-<br>
-    void operator()(void*) const {}<br>
+  void operator()(void*) const {}<br>
 };<br>
<br>
-int main()<br>
-{<br>
-    std::unique_ptr<int[], Deleter> p;<br>
+int main() {<br>
+#if TEST_STD_VER >= 11<br>
+  // expected-error@memory:* {{call to implicitly-deleted default constructor}}<br>
+  // expected-note@memory:* {{implicitly deleted because base class 'Deleter' has an inaccessible default constructor}}<br>
+#else<br>
+  // expected-error@memory:* {{base class 'Deleter' has private default constructor}}<br>
+#endif<br>
+  std::unique_ptr<int[], Deleter> p; // expected-note {{requested here}}<br>
 }<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>