<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>