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

Browse filesBrowse files
committed
[libc++] Avoid type-punning between __Value_type and pair
1 parent 4cde945 commit 2c455e4
Copy full SHA for 2c455e4

File tree

Expand file treeCollapse file tree

6 files changed

+122
-145
lines changed
Filter options
Expand file treeCollapse file tree

6 files changed

+122
-145
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 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
+56-41Lines changed: 56 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 _LIBCPP_NODEBUG = 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 _LIBCPP_NODEBUG = __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 _LIBCPP_NODEBUG = __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 __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 __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_) {}
@@ -1135,6 +1126,17 @@ public:
11351126
return __emplace_hint_multi(__p, std::forward<_Vp>(__v));
11361127
}
11371128

1129+
template <class _ValueT = _Tp, __enable_if_t<__is_tree_value_type<_ValueT>::value, int> = 0>
1130+
_LIBCPP_HIDE_FROM_ABI void __insert_from_orphaned_node(const_iterator __p, __get_node_value_type_t<_Tp>&& __value) {
1131+
using __key_type = typename _NodeTypes::key_type;
1132+
__emplace_hint_multi(__p, const_cast<__key_type&&>(__value.first), std::move(__value.second));
1133+
}
1134+
1135+
template <class _ValueT = _Tp, __enable_if_t<!__is_tree_value_type<_ValueT>::value, int> = 0>
1136+
_LIBCPP_HIDE_FROM_ABI void __insert_from_orphaned_node(const_iterator __p, _Tp&& __value) {
1137+
__emplace_hint_multi(__p, std::move(__value));
1138+
}
1139+
11381140
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool>
11391141
__node_assign_unique(const __container_value_type& __v, __node_pointer __dest);
11401142

@@ -1276,6 +1278,19 @@ private:
12761278
}
12771279
_LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__tree&, false_type) _NOEXCEPT {}
12781280

1281+
template <class _From, __enable_if_t<__is_pair_v<__remove_cvref_t<_From> >, int> = 0>
1282+
_LIBCPP_HIDE_FROM_ABI static void __assign_value(__get_node_value_type_t<value_type>& __lhs, _From&& __rhs) {
1283+
using __key_type = typename _NodeTypes::key_type;
1284+
1285+
const_cast<__key_type&>(__lhs.first) = const_cast<__copy_cvref_t<_From, __key_type>&&>(__rhs.first);
1286+
__lhs.second = std::forward<_From>(__rhs).second;
1287+
}
1288+
1289+
template <class _To, class _From, class _ValueT = _Tp, __enable_if_t<!__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,14 @@ 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+
__insert_from_orphaned_node(__e, std::move(__t.remove(__t.begin())->__value_));
1526+
}
15111527
}
15121528
}
15131529

@@ -1533,7 +1549,7 @@ void __tree<_Tp, _Compare, _Allocator>::destroy(__node_pointer __nd) _NOEXCEPT {
15331549
destroy(static_cast<__node_pointer>(__nd->__left_));
15341550
destroy(static_cast<__node_pointer>(__nd->__right_));
15351551
__node_allocator& __na = __node_alloc();
1536-
__node_traits::destroy(__na, _NodeTypes::__get_ptr(__nd->__value_));
1552+
__node_traits::destroy(__na, std::addressof(__nd->__value_));
15371553
__node_traits::deallocate(__na, __nd, 1);
15381554
}
15391555
}
@@ -1803,10 +1819,9 @@ template <class _Tp, class _Compare, class _Allocator>
18031819
template <class... _Args>
18041820
typename __tree<_Tp, _Compare, _Allocator>::__node_holder
18051821
__tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&&... __args) {
1806-
static_assert(!__is_tree_value_type<_Args...>::value, "Cannot construct from __value_type");
18071822
__node_allocator& __na = __node_alloc();
18081823
__node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
1809-
__node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), std::forward<_Args>(__args)...);
1824+
__node_traits::construct(__na, std::addressof(__h->__value_), std::forward<_Args>(__args)...);
18101825
__h.get_deleter().__value_constructed = true;
18111826
return __h;
18121827
}
@@ -1874,7 +1889,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const __container_value_
18741889
__node_pointer __r = static_cast<__node_pointer>(__child);
18751890
bool __inserted = false;
18761891
if (__child == nullptr) {
1877-
__nd->__value_ = __v;
1892+
__assign_value(__nd->__value_, __v);
18781893
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
18791894
__r = __nd;
18801895
__inserted = true;
@@ -2036,7 +2051,7 @@ typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allo
20362051
__node_pointer __np = __p.__get_np();
20372052
iterator __r = __remove_node_pointer(__np);
20382053
__node_allocator& __na = __node_alloc();
2039-
__node_traits::destroy(__na, _NodeTypes::__get_ptr(const_cast<__node_value_type&>(*__p)));
2054+
__node_traits::destroy(__na, std::addressof(const_cast<__node_value_type&>(*__p)));
20402055
__node_traits::deallocate(__na, __np, 1);
20412056
return __r;
20422057
}

0 commit comments

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