Skip to content

Commit e1f1cbf

Browse files
committed
[libc++] Avoid type-punning between __Value_type and pair
1 parent 6c9e098 commit e1f1cbf

File tree

6 files changed

+98
-139
lines changed

6 files changed

+98
-139
lines changed

libcxx/include/__fwd/pair.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD
2222
template <class, class>
2323
struct _LIBCPP_TEMPLATE_VIS pair;
2424

25+
template <class _Type>
26+
inline const bool __is_pair_v = false;
27+
28+
template <class _Type1, class _Type2>
29+
inline const bool __is_pair_v<pair<_Type1, _Type2> > = true;
30+
2531
template <size_t _Ip, class _T1, class _T2>
2632
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename tuple_element<_Ip, pair<_T1, _T2> >::type&
2733
get(pair<_T1, _T2>&) _NOEXCEPT;

libcxx/include/__memory/uses_allocator_construction.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include <__memory/uses_allocator.h>
1515
#include <__tuple/tuple_like_no_subrange.h>
1616
#include <__type_traits/enable_if.h>
17-
#include <__type_traits/is_same.h>
1817
#include <__type_traits/remove_cv.h>
1918
#include <__utility/declval.h>
2019
#include <__utility/pair.h>
@@ -31,14 +30,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
3130

3231
#if _LIBCPP_STD_VER >= 17
3332

34-
template <class _Type>
35-
inline constexpr bool __is_std_pair = false;
36-
37-
template <class _Type1, class _Type2>
38-
inline constexpr bool __is_std_pair<pair<_Type1, _Type2>> = true;
39-
4033
template <class _Tp>
41-
inline constexpr bool __is_cv_std_pair = __is_std_pair<remove_cv_t<_Tp>>;
34+
inline constexpr bool __is_cv_std_pair = __is_pair_v<remove_cv_t<_Tp>>;
4235

4336
template <class _Tp, class = void>
4437
struct __uses_allocator_construction_args;

libcxx/include/__node_handle

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,15 +175,15 @@ struct __set_node_handle_specifics {
175175

176176
template <class _NodeType, class _Derived>
177177
struct __map_node_handle_specifics {
178-
typedef typename _NodeType::__node_value_type::key_type key_type;
179-
typedef typename _NodeType::__node_value_type::mapped_type mapped_type;
178+
typedef __remove_const_t<typename _NodeType::__node_value_type::first_type> key_type;
179+
typedef typename _NodeType::__node_value_type::second_type mapped_type;
180180

181181
_LIBCPP_HIDE_FROM_ABI key_type& key() const {
182-
return static_cast<_Derived const*>(this)->__ptr_->__get_value().__ref().first;
182+
return const_cast<key_type&>(static_cast<_Derived const*>(this)->__ptr_->__get_value().first);
183183
}
184184

185185
_LIBCPP_HIDE_FROM_ABI mapped_type& mapped() const {
186-
return static_cast<_Derived const*>(this)->__ptr_->__get_value().__ref().second;
186+
return static_cast<_Derived const*>(this)->__ptr_->__get_value().second;
187187
}
188188
};
189189

libcxx/include/__tree

Lines changed: 61 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -505,48 +505,24 @@ struct __is_tree_value_type<_One> : __is_tree_value_type_imp<__remove_cvref_t<_O
505505
template <class _Tp>
506506
struct __tree_key_value_types {
507507
typedef _Tp key_type;
508-
typedef _Tp __node_value_type;
509508
typedef _Tp __container_value_type;
510509
static const bool __is_map = false;
511510

512511
_LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(_Tp const& __v) { return __v; }
513-
_LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(__node_value_type const& __v) { return __v; }
514-
_LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) { return std::addressof(__n); }
515-
_LIBCPP_HIDE_FROM_ABI static __container_value_type&& __move(__node_value_type& __v) { return std::move(__v); }
516512
};
517513

518514
template <class _Key, class _Tp>
519515
struct __tree_key_value_types<__value_type<_Key, _Tp> > {
520516
typedef _Key key_type;
521517
typedef _Tp mapped_type;
522-
typedef __value_type<_Key, _Tp> __node_value_type;
523518
typedef pair<const _Key, _Tp> __container_value_type;
524519
typedef __container_value_type __map_value_type;
525520
static const bool __is_map = true;
526521

527-
_LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(__node_value_type const& __t) {
528-
return __t.__get_value().first;
529-
}
530-
531522
template <class _Up, __enable_if_t<__is_same_uncvref<_Up, __container_value_type>::value, int> = 0>
532523
_LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(_Up& __t) {
533524
return __t.first;
534525
}
535-
536-
_LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(__node_value_type const& __t) {
537-
return __t.__get_value();
538-
}
539-
540-
template <class _Up, __enable_if_t<__is_same_uncvref<_Up, __container_value_type>::value, int> = 0>
541-
_LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) {
542-
return __t;
543-
}
544-
545-
_LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) {
546-
return std::addressof(__n.__get_value());
547-
}
548-
549-
_LIBCPP_HIDE_FROM_ABI static pair<key_type&&, mapped_type&&> __move(__node_value_type& __v) { return __v.__move(); }
550526
};
551527

552528
template <class _VoidPtr>
@@ -587,6 +563,19 @@ struct __tree_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> {
587563
typedef __rebind_pointer_t<_AllocPtr, const _Mv> __const_map_value_type_pointer;
588564
};
589565

566+
template <class _Tp>
567+
struct __get_node_value_type {
568+
using type _LIBCPP_NODEBUG = _Tp;
569+
};
570+
571+
template <class _Key, class _ValueT>
572+
struct __get_node_value_type<__value_type<_Key, _ValueT> > {
573+
using type _LIBCPP_NODEBUG = pair<const _Key, _ValueT>;
574+
};
575+
576+
template <class _Tp>
577+
using __get_node_value_type_t = typename __get_node_value_type<_Tp>::type;
578+
590579
template <class _NodePtr, class _NodeT = typename pointer_traits<_NodePtr>::element_type>
591580
struct __tree_node_types;
592581

@@ -601,7 +590,7 @@ public:
601590
typedef typename pointer_traits<_NodePtr>::element_type __node_type;
602591
typedef _NodePtr __node_pointer;
603592

604-
typedef _Tp __node_value_type;
593+
using __node_value_type = __get_node_value_type_t<_Tp>;
605594
typedef __rebind_pointer_t<_VoidPtr, __node_value_type> __node_value_type_pointer;
606595
typedef __rebind_pointer_t<_VoidPtr, const __node_value_type> __const_node_value_type_pointer;
607596
typedef typename __base::__end_node_pointer __iter_pointer;
@@ -653,11 +642,11 @@ public:
653642
template <class _Tp, class _VoidPtr>
654643
class _LIBCPP_STANDALONE_DEBUG __tree_node : public __tree_node_base<_VoidPtr> {
655644
public:
656-
typedef _Tp __node_value_type;
645+
using __node_value_type = __get_node_value_type_t<_Tp>;
657646

658647
__node_value_type __value_;
659648

660-
_LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return __value_; }
649+
_LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return __value_; }
661650

662651
~__tree_node() = delete;
663652
__tree_node(__tree_node const&) = delete;
@@ -688,7 +677,7 @@ public:
688677

689678
_LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT {
690679
if (__value_constructed)
691-
__alloc_traits::destroy(__na_, _NodeTypes::__get_ptr(__p->__value_));
680+
__alloc_traits::destroy(__na_, std::addressof(__p->__value_));
692681
if (__p)
693682
__alloc_traits::deallocate(__na_, __p, 1);
694683
}
@@ -719,7 +708,7 @@ class _LIBCPP_TEMPLATE_VIS __tree_iterator {
719708

720709
public:
721710
typedef bidirectional_iterator_tag iterator_category;
722-
typedef _Tp value_type;
711+
using value_type = __get_node_value_type_t<_Tp>;
723712
typedef _DiffType difference_type;
724713
typedef value_type& reference;
725714
typedef typename _NodeTypes::__node_value_type_pointer pointer;
@@ -796,7 +785,7 @@ class _LIBCPP_TEMPLATE_VIS __tree_const_iterator {
796785

797786
public:
798787
typedef bidirectional_iterator_tag iterator_category;
799-
typedef _Tp value_type;
788+
using value_type = __get_node_value_type_t<_Tp>;
800789
typedef _DiffType difference_type;
801790
typedef const value_type& reference;
802791
typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
@@ -809,7 +798,7 @@ public:
809798
}
810799

811800
private:
812-
typedef __tree_iterator<value_type, __node_pointer, difference_type> __non_const_iterator;
801+
typedef __tree_iterator<_Tp, __node_pointer, difference_type> __non_const_iterator;
813802

814803
public:
815804
_LIBCPP_HIDE_FROM_ABI __tree_const_iterator(__non_const_iterator __p) _NOEXCEPT : __ptr_(__p.__ptr_) {}
@@ -1276,6 +1265,32 @@ private:
12761265
}
12771266
_LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__tree&, false_type) _NOEXCEPT {}
12781267

1268+
template <class _From, __enable_if_t<__is_pair_v<__remove_cvref_t<_From> >, int> = 0>
1269+
_LIBCPP_HIDE_FROM_ABI static void __assign_value(__get_node_value_type_t<value_type>& __lhs, _From&& __rhs) {
1270+
using __punned_type = pair<typename _NodeTypes::key_type, typename _NodeTypes::mapped_type>;
1271+
1272+
reinterpret_cast<__punned_type&>(__lhs) = reinterpret_cast<__copy_cvref_t<_From, __punned_type>&&>(__rhs);
1273+
}
1274+
1275+
template <class _To,
1276+
class _From,
1277+
class _ValueT = _Tp,
1278+
__enable_if_t<__is_tree_value_type<_ValueT>::value && !__is_pair_v<__remove_cvref_t<_From> >, int> = 0>
1279+
_LIBCPP_HIDE_FROM_ABI static void __assign_value(_To& __lhs, _From&& __rhs) {
1280+
static_assert(__is_pair_v<__remove_cvref_t<_From> >);
1281+
using __punned_type = pair<typename _NodeTypes::key_type, typename _NodeTypes::mapped_type>;
1282+
1283+
reinterpret_cast<__punned_type&>(__lhs) = __rhs;
1284+
}
1285+
1286+
template <class _To,
1287+
class _From,
1288+
class _ValueT = _Tp,
1289+
__enable_if_t<!__is_tree_value_type<_ValueT>::value && !__is_pair_v<__remove_cvref_t<_From> >, int> = 0>
1290+
_LIBCPP_HIDE_FROM_ABI static void __assign_value(_To& __lhs, _From&& __rhs) {
1291+
__lhs = std::forward<_From>(__rhs);
1292+
}
1293+
12791294
struct _DetachedTreeCache {
12801295
_LIBCPP_HIDE_FROM_ABI explicit _DetachedTreeCache(__tree* __t) _NOEXCEPT
12811296
: __t_(__t),
@@ -1416,13 +1431,13 @@ void __tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _
14161431
if (size() != 0) {
14171432
_DetachedTreeCache __cache(this);
14181433
for (; __cache.__get() && __first != __last; ++__first) {
1419-
__cache.__get()->__value_ = *__first;
1434+
__assign_value(__cache.__get()->__value_, *__first);
14201435
__node_insert_multi(__cache.__get());
14211436
__cache.__advance();
14221437
}
14231438
}
14241439
for (; __first != __last; ++__first)
1425-
__insert_multi(_NodeTypes::__get_value(*__first));
1440+
__insert_multi(*__first);
14261441
}
14271442

14281443
template <class _Tp, class _Compare, class _Allocator>
@@ -1501,13 +1516,19 @@ void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type) {
15011516
if (size() != 0) {
15021517
_DetachedTreeCache __cache(this);
15031518
while (__cache.__get() != nullptr && __t.size() != 0) {
1504-
__cache.__get()->__value_ = std::move(__t.remove(__t.begin())->__value_);
1519+
__assign_value(__cache.__get()->__value_, std::move(__t.remove(__t.begin())->__value_));
15051520
__node_insert_multi(__cache.__get());
15061521
__cache.__advance();
15071522
}
15081523
}
1509-
while (__t.size() != 0)
1510-
__insert_multi(__e, _NodeTypes::__move(__t.remove(__t.begin())->__value_));
1524+
while (__t.size() != 0) {
1525+
if constexpr (__is_tree_value_type<_Tp>::value) {
1526+
using __punned_type = pair<typename _NodeTypes::key_type, typename _NodeTypes::mapped_type>;
1527+
__insert_multi(__e, reinterpret_cast<__punned_type&&>(__t.remove(__t.begin())->__value_));
1528+
} else {
1529+
__insert_multi(__e, std::move(__t.remove(__t.begin())->__value_));
1530+
}
1531+
}
15111532
}
15121533
}
15131534

@@ -1533,7 +1554,7 @@ void __tree<_Tp, _Compare, _Allocator>::destroy(__node_pointer __nd) _NOEXCEPT {
15331554
destroy(static_cast<__node_pointer>(__nd->__left_));
15341555
destroy(static_cast<__node_pointer>(__nd->__right_));
15351556
__node_allocator& __na = __node_alloc();
1536-
__node_traits::destroy(__na, _NodeTypes::__get_ptr(__nd->__value_));
1557+
__node_traits::destroy(__na, std::addressof(__nd->__value_));
15371558
__node_traits::deallocate(__na, __nd, 1);
15381559
}
15391560
}
@@ -1803,10 +1824,9 @@ template <class _Tp, class _Compare, class _Allocator>
18031824
template <class... _Args>
18041825
typename __tree<_Tp, _Compare, _Allocator>::__node_holder
18051826
__tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&&... __args) {
1806-
static_assert(!__is_tree_value_type<_Args...>::value, "Cannot construct from __value_type");
18071827
__node_allocator& __na = __node_alloc();
18081828
__node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
1809-
__node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), std::forward<_Args>(__args)...);
1829+
__node_traits::construct(__na, std::addressof(__h->__value_), std::forward<_Args>(__args)...);
18101830
__h.get_deleter().__value_constructed = true;
18111831
return __h;
18121832
}
@@ -1874,7 +1894,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const __container_value_
18741894
__node_pointer __r = static_cast<__node_pointer>(__child);
18751895
bool __inserted = false;
18761896
if (__child == nullptr) {
1877-
__nd->__value_ = __v;
1897+
__assign_value(__nd->__value_, __v);
18781898
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
18791899
__r = __nd;
18801900
__inserted = true;
@@ -2036,7 +2056,7 @@ typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allo
20362056
__node_pointer __np = __p.__get_np();
20372057
iterator __r = __remove_node_pointer(__np);
20382058
__node_allocator& __na = __node_alloc();
2039-
__node_traits::destroy(__na, _NodeTypes::__get_ptr(const_cast<__node_value_type&>(*__p)));
2059+
__node_traits::destroy(__na, std::addressof(const_cast<__node_value_type&>(*__p)));
20402060
__node_traits::deallocate(__na, __np, 1);
20412061
return __r;
20422062
}

0 commit comments

Comments
 (0)