Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9621c25

Browse filesBrowse files
committed
[libc++] Avoid type-punning between __Value_type and pair
1 parent 6c9e098 commit 9621c25
Copy full SHA for 9621c25

File tree

Expand file treeCollapse file tree

6 files changed

+124
-139
lines changed
Filter options
Expand file treeCollapse file tree

6 files changed

+124
-139
lines changed

‎libcxx/include/__fwd/pair.h

Copy file name to clipboardExpand all lines: libcxx/include/__fwd/pair.h
+6Lines 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

Copy file name to clipboardExpand all lines: libcxx/include/__memory/uses_allocator_construction.h
+1-8Lines 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

Copy file name to clipboardExpand all lines: libcxx/include/__node_handle
+28-4Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public:
6262
#include <__config>
6363
#include <__memory/allocator_traits.h>
6464
#include <__memory/pointer_traits.h>
65+
#include <__type_traits/is_specialization.h>
6566
#include <optional>
6667

6768
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -173,17 +174,40 @@ struct __set_node_handle_specifics {
173174
_LIBCPP_HIDE_FROM_ABI value_type& value() const { return static_cast<_Derived const*>(this)->__ptr_->__get_value(); }
174175
};
175176

177+
template <class, class>
178+
struct __hash_value_type;
179+
176180
template <class _NodeType, class _Derived>
177181
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;
182+
template <class _Tp>
183+
struct __get_type {
184+
using key_type = __remove_const_t<typename _Tp::first_type>;
185+
using mapped_type = typename _Tp::second_type;
186+
};
187+
188+
template <class _Key, class _Mapped>
189+
struct __get_type<__hash_value_type<_Key, _Mapped> > {
190+
using key_type = _Key;
191+
using mapped_type = _Mapped;
192+
};
193+
194+
using key_type = typename __get_type<typename _NodeType::__node_value_type>::key_type;
195+
using mapped_type = typename __get_type<typename _NodeType::__node_value_type>::mapped_type;
180196

181197
_LIBCPP_HIDE_FROM_ABI key_type& key() const {
182-
return static_cast<_Derived const*>(this)->__ptr_->__get_value().__ref().first;
198+
if constexpr (__is_specialization_v<typename _NodeType::__node_value_type, __hash_value_type>) {
199+
return static_cast<_Derived const*>(this)->__ptr_->__get_value().__ref().first;
200+
} else {
201+
return const_cast<key_type&>(static_cast<_Derived const*>(this)->__ptr_->__get_value().first);
202+
}
183203
}
184204

185205
_LIBCPP_HIDE_FROM_ABI mapped_type& mapped() const {
186-
return static_cast<_Derived const*>(this)->__ptr_->__get_value().__ref().second;
206+
if constexpr (__is_specialization_v<typename _NodeType::__node_value_type, __hash_value_type>) {
207+
return static_cast<_Derived const*>(this)->__ptr_->__get_value().__ref().second;
208+
} else {
209+
return static_cast<_Derived const*>(this)->__ptr_->__get_value().second;
210+
}
187211
}
188212
};
189213

‎libcxx/include/__tree

Copy file name to clipboardExpand all lines: libcxx/include/__tree
+63-41Lines changed: 63 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <__assert>
1515
#include <__config>
1616
#include <__fwd/map.h>
17+
#include <__fwd/pair.h>
1718
#include <__fwd/set.h>
1819
#include <__iterator/distance.h>
1920
#include <__iterator/iterator_traits.h>
@@ -25,6 +26,7 @@
2526
#include <__memory/swap_allocator.h>
2627
#include <__memory/unique_ptr.h>
2728
#include <__type_traits/can_extract_key.h>
29+
#include <__type_traits/copy_cvref.h>
2830
#include <__type_traits/enable_if.h>
2931
#include <__type_traits/invoke.h>
3032
#include <__type_traits/is_const.h>
@@ -505,48 +507,24 @@ struct __is_tree_value_type<_One> : __is_tree_value_type_imp<__remove_cvref_t<_O
505507
template <class _Tp>
506508
struct __tree_key_value_types {
507509
typedef _Tp key_type;
508-
typedef _Tp __node_value_type;
509510
typedef _Tp __container_value_type;
510511
static const bool __is_map = false;
511512

512513
_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); }
516514
};
517515

518516
template <class _Key, class _Tp>
519517
struct __tree_key_value_types<__value_type<_Key, _Tp> > {
520518
typedef _Key key_type;
521519
typedef _Tp mapped_type;
522-
typedef __value_type<_Key, _Tp> __node_value_type;
523520
typedef pair<const _Key, _Tp> __container_value_type;
524521
typedef __container_value_type __map_value_type;
525522
static const bool __is_map = true;
526523

527-
_LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(__node_value_type const& __t) {
528-
return __t.__get_value().first;
529-
}
530-
531524
template <class _Up, __enable_if_t<__is_same_uncvref<_Up, __container_value_type>::value, int> = 0>
532525
_LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(_Up& __t) {
533526
return __t.first;
534527
}
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(); }
550528
};
551529

552530
template <class _VoidPtr>
@@ -587,6 +565,19 @@ struct __tree_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> {
587565
typedef __rebind_pointer_t<_AllocPtr, const _Mv> __const_map_value_type_pointer;
588566
};
589567

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

@@ -601,7 +592,7 @@ public:
601592
typedef typename pointer_traits<_NodePtr>::element_type __node_type;
602593
typedef _NodePtr __node_pointer;
603594

604-
typedef _Tp __node_value_type;
595+
using __node_value_type = __get_node_value_type_t<_Tp>;
605596
typedef __rebind_pointer_t<_VoidPtr, __node_value_type> __node_value_type_pointer;
606597
typedef __rebind_pointer_t<_VoidPtr, const __node_value_type> __const_node_value_type_pointer;
607598
typedef typename __base::__end_node_pointer __iter_pointer;
@@ -653,11 +644,11 @@ public:
653644
template <class _Tp, class _VoidPtr>
654645
class _LIBCPP_STANDALONE_DEBUG __tree_node : public __tree_node_base<_VoidPtr> {
655646
public:
656-
typedef _Tp __node_value_type;
647+
using __node_value_type = __get_node_value_type_t<_Tp>;
657648

658649
__node_value_type __value_;
659650

660-
_LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return __value_; }
651+
_LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return __value_; }
661652

662653
~__tree_node() = delete;
663654
__tree_node(__tree_node const&) = delete;
@@ -688,7 +679,7 @@ public:
688679

689680
_LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT {
690681
if (__value_constructed)
691-
__alloc_traits::destroy(__na_, _NodeTypes::__get_ptr(__p->__value_));
682+
__alloc_traits::destroy(__na_, std::addressof(__p->__value_));
692683
if (__p)
693684
__alloc_traits::deallocate(__na_, __p, 1);
694685
}
@@ -719,7 +710,7 @@ class _LIBCPP_TEMPLATE_VIS __tree_iterator {
719710

720711
public:
721712
typedef bidirectional_iterator_tag iterator_category;
722-
typedef _Tp value_type;
713+
using value_type = __get_node_value_type_t<_Tp>;
723714
typedef _DiffType difference_type;
724715
typedef value_type& reference;
725716
typedef typename _NodeTypes::__node_value_type_pointer pointer;
@@ -796,7 +787,7 @@ class _LIBCPP_TEMPLATE_VIS __tree_const_iterator {
796787

797788
public:
798789
typedef bidirectional_iterator_tag iterator_category;
799-
typedef _Tp value_type;
790+
using value_type = __get_node_value_type_t<_Tp>;
800791
typedef _DiffType difference_type;
801792
typedef const value_type& reference;
802793
typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
@@ -809,7 +800,7 @@ public:
809800
}
810801

811802
private:
812-
typedef __tree_iterator<value_type, __node_pointer, difference_type> __non_const_iterator;
803+
typedef __tree_iterator<_Tp, __node_pointer, difference_type> __non_const_iterator;
813804

814805
public:
815806
_LIBCPP_HIDE_FROM_ABI __tree_const_iterator(__non_const_iterator __p) _NOEXCEPT : __ptr_(__p.__ptr_) {}
@@ -1276,6 +1267,32 @@ private:
12761267
}
12771268
_LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__tree&, false_type) _NOEXCEPT {}
12781269

1270+
template <class _From, __enable_if_t<__is_pair_v<__remove_cvref_t<_From> >, int> = 0>
1271+
_LIBCPP_HIDE_FROM_ABI static void __assign_value(__get_node_value_type_t<value_type>& __lhs, _From&& __rhs) {
1272+
using __punned_type = pair<typename _NodeTypes::key_type, typename _NodeTypes::mapped_type>;
1273+
1274+
reinterpret_cast<__punned_type&>(__lhs) = reinterpret_cast<__copy_cvref_t<_From, __punned_type>&&>(__rhs);
1275+
}
1276+
1277+
template <class _To,
1278+
class _From,
1279+
class _ValueT = _Tp,
1280+
__enable_if_t<__is_tree_value_type<_ValueT>::value && !__is_pair_v<__remove_cvref_t<_From> >, int> = 0>
1281+
_LIBCPP_HIDE_FROM_ABI static void __assign_value(_To& __lhs, _From&& __rhs) {
1282+
static_assert(__is_pair_v<__remove_cvref_t<_From> >);
1283+
using __punned_type = pair<typename _NodeTypes::key_type, typename _NodeTypes::mapped_type>;
1284+
1285+
reinterpret_cast<__punned_type&>(__lhs) = __rhs;
1286+
}
1287+
1288+
template <class _To,
1289+
class _From,
1290+
class _ValueT = _Tp,
1291+
__enable_if_t<!__is_tree_value_type<_ValueT>::value && !__is_pair_v<__remove_cvref_t<_From> >, int> = 0>
1292+
_LIBCPP_HIDE_FROM_ABI static void __assign_value(_To& __lhs, _From&& __rhs) {
1293+
__lhs = std::forward<_From>(__rhs);
1294+
}
1295+
12791296
struct _DetachedTreeCache {
12801297
_LIBCPP_HIDE_FROM_ABI explicit _DetachedTreeCache(__tree* __t) _NOEXCEPT
12811298
: __t_(__t),
@@ -1416,13 +1433,13 @@ void __tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _
14161433
if (size() != 0) {
14171434
_DetachedTreeCache __cache(this);
14181435
for (; __cache.__get() && __first != __last; ++__first) {
1419-
__cache.__get()->__value_ = *__first;
1436+
__assign_value(__cache.__get()->__value_, *__first);
14201437
__node_insert_multi(__cache.__get());
14211438
__cache.__advance();
14221439
}
14231440
}
14241441
for (; __first != __last; ++__first)
1425-
__insert_multi(_NodeTypes::__get_value(*__first));
1442+
__insert_multi(*__first);
14261443
}
14271444

14281445
template <class _Tp, class _Compare, class _Allocator>
@@ -1501,13 +1518,19 @@ void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type) {
15011518
if (size() != 0) {
15021519
_DetachedTreeCache __cache(this);
15031520
while (__cache.__get() != nullptr && __t.size() != 0) {
1504-
__cache.__get()->__value_ = std::move(__t.remove(__t.begin())->__value_);
1521+
__assign_value(__cache.__get()->__value_, std::move(__t.remove(__t.begin())->__value_));
15051522
__node_insert_multi(__cache.__get());
15061523
__cache.__advance();
15071524
}
15081525
}
1509-
while (__t.size() != 0)
1510-
__insert_multi(__e, _NodeTypes::__move(__t.remove(__t.begin())->__value_));
1526+
while (__t.size() != 0) {
1527+
if constexpr (__is_tree_value_type<_Tp>::value) {
1528+
using __punned_type = pair<typename _NodeTypes::key_type, typename _NodeTypes::mapped_type>;
1529+
__insert_multi(__e, reinterpret_cast<__punned_type&&>(__t.remove(__t.begin())->__value_));
1530+
} else {
1531+
__insert_multi(__e, std::move(__t.remove(__t.begin())->__value_));
1532+
}
1533+
}
15111534
}
15121535
}
15131536

@@ -1533,7 +1556,7 @@ void __tree<_Tp, _Compare, _Allocator>::destroy(__node_pointer __nd) _NOEXCEPT {
15331556
destroy(static_cast<__node_pointer>(__nd->__left_));
15341557
destroy(static_cast<__node_pointer>(__nd->__right_));
15351558
__node_allocator& __na = __node_alloc();
1536-
__node_traits::destroy(__na, _NodeTypes::__get_ptr(__nd->__value_));
1559+
__node_traits::destroy(__na, std::addressof(__nd->__value_));
15371560
__node_traits::deallocate(__na, __nd, 1);
15381561
}
15391562
}
@@ -1803,10 +1826,9 @@ template <class _Tp, class _Compare, class _Allocator>
18031826
template <class... _Args>
18041827
typename __tree<_Tp, _Compare, _Allocator>::__node_holder
18051828
__tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&&... __args) {
1806-
static_assert(!__is_tree_value_type<_Args...>::value, "Cannot construct from __value_type");
18071829
__node_allocator& __na = __node_alloc();
18081830
__node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
1809-
__node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), std::forward<_Args>(__args)...);
1831+
__node_traits::construct(__na, std::addressof(__h->__value_), std::forward<_Args>(__args)...);
18101832
__h.get_deleter().__value_constructed = true;
18111833
return __h;
18121834
}
@@ -1874,7 +1896,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const __container_value_
18741896
__node_pointer __r = static_cast<__node_pointer>(__child);
18751897
bool __inserted = false;
18761898
if (__child == nullptr) {
1877-
__nd->__value_ = __v;
1899+
__assign_value(__nd->__value_, __v);
18781900
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
18791901
__r = __nd;
18801902
__inserted = true;
@@ -2036,7 +2058,7 @@ typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allo
20362058
__node_pointer __np = __p.__get_np();
20372059
iterator __r = __remove_node_pointer(__np);
20382060
__node_allocator& __na = __node_alloc();
2039-
__node_traits::destroy(__na, _NodeTypes::__get_ptr(const_cast<__node_value_type&>(*__p)));
2061+
__node_traits::destroy(__na, std::addressof(const_cast<__node_value_type&>(*__p)));
20402062
__node_traits::deallocate(__na, __np, 1);
20412063
return __r;
20422064
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.