[libcxx-commits] [libcxx] [libc++] Avoid type-punning between __Value_type and pair (PR #134819)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Apr 8 03:34:53 PDT 2025
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/134819
>From 9621c25884242a4c46d723e3755cc85bbf1dd224 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Mon, 7 Apr 2025 15:01:38 +0200
Subject: [PATCH] [libc++] Avoid type-punning between __Value_type and pair
---
libcxx/include/__fwd/pair.h | 6 +
.../__memory/uses_allocator_construction.h | 9 +-
libcxx/include/__node_handle | 32 +++++-
libcxx/include/__tree | 104 ++++++++++-------
libcxx/include/map | 108 +++++-------------
.../tree_key_value_traits.pass.cpp | 4 -
6 files changed, 124 insertions(+), 139 deletions(-)
diff --git a/libcxx/include/__fwd/pair.h b/libcxx/include/__fwd/pair.h
index b8ba2b7e92324..6c4c088521d58 100644
--- a/libcxx/include/__fwd/pair.h
+++ b/libcxx/include/__fwd/pair.h
@@ -22,6 +22,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class, class>
struct _LIBCPP_TEMPLATE_VIS pair;
+template <class _Type>
+inline const bool __is_pair_v = false;
+
+template <class _Type1, class _Type2>
+inline const bool __is_pair_v<pair<_Type1, _Type2> > = true;
+
template <size_t _Ip, class _T1, class _T2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename tuple_element<_Ip, pair<_T1, _T2> >::type&
get(pair<_T1, _T2>&) _NOEXCEPT;
diff --git a/libcxx/include/__memory/uses_allocator_construction.h b/libcxx/include/__memory/uses_allocator_construction.h
index 955879ffc5845..49ddf99d9cc95 100644
--- a/libcxx/include/__memory/uses_allocator_construction.h
+++ b/libcxx/include/__memory/uses_allocator_construction.h
@@ -14,7 +14,6 @@
#include <__memory/uses_allocator.h>
#include <__tuple/tuple_like_no_subrange.h>
#include <__type_traits/enable_if.h>
-#include <__type_traits/is_same.h>
#include <__type_traits/remove_cv.h>
#include <__utility/declval.h>
#include <__utility/pair.h>
@@ -31,14 +30,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 17
-template <class _Type>
-inline constexpr bool __is_std_pair = false;
-
-template <class _Type1, class _Type2>
-inline constexpr bool __is_std_pair<pair<_Type1, _Type2>> = true;
-
template <class _Tp>
-inline constexpr bool __is_cv_std_pair = __is_std_pair<remove_cv_t<_Tp>>;
+inline constexpr bool __is_cv_std_pair = __is_pair_v<remove_cv_t<_Tp>>;
template <class _Tp, class = void>
struct __uses_allocator_construction_args;
diff --git a/libcxx/include/__node_handle b/libcxx/include/__node_handle
index 8f32f2de83391..6fa103dc9c037 100644
--- a/libcxx/include/__node_handle
+++ b/libcxx/include/__node_handle
@@ -62,6 +62,7 @@ public:
#include <__config>
#include <__memory/allocator_traits.h>
#include <__memory/pointer_traits.h>
+#include <__type_traits/is_specialization.h>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -173,17 +174,40 @@ struct __set_node_handle_specifics {
_LIBCPP_HIDE_FROM_ABI value_type& value() const { return static_cast<_Derived const*>(this)->__ptr_->__get_value(); }
};
+template <class, class>
+struct __hash_value_type;
+
template <class _NodeType, class _Derived>
struct __map_node_handle_specifics {
- typedef typename _NodeType::__node_value_type::key_type key_type;
- typedef typename _NodeType::__node_value_type::mapped_type mapped_type;
+ template <class _Tp>
+ struct __get_type {
+ using key_type = __remove_const_t<typename _Tp::first_type>;
+ using mapped_type = typename _Tp::second_type;
+ };
+
+ template <class _Key, class _Mapped>
+ struct __get_type<__hash_value_type<_Key, _Mapped> > {
+ using key_type = _Key;
+ using mapped_type = _Mapped;
+ };
+
+ using key_type = typename __get_type<typename _NodeType::__node_value_type>::key_type;
+ using mapped_type = typename __get_type<typename _NodeType::__node_value_type>::mapped_type;
_LIBCPP_HIDE_FROM_ABI key_type& key() const {
- return static_cast<_Derived const*>(this)->__ptr_->__get_value().__ref().first;
+ if constexpr (__is_specialization_v<typename _NodeType::__node_value_type, __hash_value_type>) {
+ return static_cast<_Derived const*>(this)->__ptr_->__get_value().__ref().first;
+ } else {
+ return const_cast<key_type&>(static_cast<_Derived const*>(this)->__ptr_->__get_value().first);
+ }
}
_LIBCPP_HIDE_FROM_ABI mapped_type& mapped() const {
- return static_cast<_Derived const*>(this)->__ptr_->__get_value().__ref().second;
+ if constexpr (__is_specialization_v<typename _NodeType::__node_value_type, __hash_value_type>) {
+ return static_cast<_Derived const*>(this)->__ptr_->__get_value().__ref().second;
+ } else {
+ return static_cast<_Derived const*>(this)->__ptr_->__get_value().second;
+ }
}
};
diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index 9d28381c8c2ce..c6087d2802e1e 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -14,6 +14,7 @@
#include <__assert>
#include <__config>
#include <__fwd/map.h>
+#include <__fwd/pair.h>
#include <__fwd/set.h>
#include <__iterator/distance.h>
#include <__iterator/iterator_traits.h>
@@ -25,6 +26,7 @@
#include <__memory/swap_allocator.h>
#include <__memory/unique_ptr.h>
#include <__type_traits/can_extract_key.h>
+#include <__type_traits/copy_cvref.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/invoke.h>
#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
template <class _Tp>
struct __tree_key_value_types {
typedef _Tp key_type;
- typedef _Tp __node_value_type;
typedef _Tp __container_value_type;
static const bool __is_map = false;
_LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(_Tp const& __v) { return __v; }
- _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(__node_value_type const& __v) { return __v; }
- _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) { return std::addressof(__n); }
- _LIBCPP_HIDE_FROM_ABI static __container_value_type&& __move(__node_value_type& __v) { return std::move(__v); }
};
template <class _Key, class _Tp>
struct __tree_key_value_types<__value_type<_Key, _Tp> > {
typedef _Key key_type;
typedef _Tp mapped_type;
- typedef __value_type<_Key, _Tp> __node_value_type;
typedef pair<const _Key, _Tp> __container_value_type;
typedef __container_value_type __map_value_type;
static const bool __is_map = true;
- _LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(__node_value_type const& __t) {
- return __t.__get_value().first;
- }
-
template <class _Up, __enable_if_t<__is_same_uncvref<_Up, __container_value_type>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(_Up& __t) {
return __t.first;
}
-
- _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(__node_value_type const& __t) {
- return __t.__get_value();
- }
-
- template <class _Up, __enable_if_t<__is_same_uncvref<_Up, __container_value_type>::value, int> = 0>
- _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) {
- return __t;
- }
-
- _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) {
- return std::addressof(__n.__get_value());
- }
-
- _LIBCPP_HIDE_FROM_ABI static pair<key_type&&, mapped_type&&> __move(__node_value_type& __v) { return __v.__move(); }
};
template <class _VoidPtr>
@@ -587,6 +565,19 @@ struct __tree_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> {
typedef __rebind_pointer_t<_AllocPtr, const _Mv> __const_map_value_type_pointer;
};
+template <class _Tp>
+struct __get_node_value_type {
+ using type _LIBCPP_NODEBUG = _Tp;
+};
+
+template <class _Key, class _ValueT>
+struct __get_node_value_type<__value_type<_Key, _ValueT> > {
+ using type _LIBCPP_NODEBUG = pair<const _Key, _ValueT>;
+};
+
+template <class _Tp>
+using __get_node_value_type_t = typename __get_node_value_type<_Tp>::type;
+
template <class _NodePtr, class _NodeT = typename pointer_traits<_NodePtr>::element_type>
struct __tree_node_types;
@@ -601,7 +592,7 @@ public:
typedef typename pointer_traits<_NodePtr>::element_type __node_type;
typedef _NodePtr __node_pointer;
- typedef _Tp __node_value_type;
+ using __node_value_type = __get_node_value_type_t<_Tp>;
typedef __rebind_pointer_t<_VoidPtr, __node_value_type> __node_value_type_pointer;
typedef __rebind_pointer_t<_VoidPtr, const __node_value_type> __const_node_value_type_pointer;
typedef typename __base::__end_node_pointer __iter_pointer;
@@ -653,11 +644,11 @@ public:
template <class _Tp, class _VoidPtr>
class _LIBCPP_STANDALONE_DEBUG __tree_node : public __tree_node_base<_VoidPtr> {
public:
- typedef _Tp __node_value_type;
+ using __node_value_type = __get_node_value_type_t<_Tp>;
__node_value_type __value_;
- _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return __value_; }
+ _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return __value_; }
~__tree_node() = delete;
__tree_node(__tree_node const&) = delete;
@@ -688,7 +679,7 @@ public:
_LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT {
if (__value_constructed)
- __alloc_traits::destroy(__na_, _NodeTypes::__get_ptr(__p->__value_));
+ __alloc_traits::destroy(__na_, std::addressof(__p->__value_));
if (__p)
__alloc_traits::deallocate(__na_, __p, 1);
}
@@ -719,7 +710,7 @@ class _LIBCPP_TEMPLATE_VIS __tree_iterator {
public:
typedef bidirectional_iterator_tag iterator_category;
- typedef _Tp value_type;
+ using value_type = __get_node_value_type_t<_Tp>;
typedef _DiffType difference_type;
typedef value_type& reference;
typedef typename _NodeTypes::__node_value_type_pointer pointer;
@@ -796,7 +787,7 @@ class _LIBCPP_TEMPLATE_VIS __tree_const_iterator {
public:
typedef bidirectional_iterator_tag iterator_category;
- typedef _Tp value_type;
+ using value_type = __get_node_value_type_t<_Tp>;
typedef _DiffType difference_type;
typedef const value_type& reference;
typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
@@ -809,7 +800,7 @@ public:
}
private:
- typedef __tree_iterator<value_type, __node_pointer, difference_type> __non_const_iterator;
+ typedef __tree_iterator<_Tp, __node_pointer, difference_type> __non_const_iterator;
public:
_LIBCPP_HIDE_FROM_ABI __tree_const_iterator(__non_const_iterator __p) _NOEXCEPT : __ptr_(__p.__ptr_) {}
@@ -1276,6 +1267,32 @@ private:
}
_LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__tree&, false_type) _NOEXCEPT {}
+ template <class _From, __enable_if_t<__is_pair_v<__remove_cvref_t<_From> >, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI static void __assign_value(__get_node_value_type_t<value_type>& __lhs, _From&& __rhs) {
+ using __punned_type = pair<typename _NodeTypes::key_type, typename _NodeTypes::mapped_type>;
+
+ reinterpret_cast<__punned_type&>(__lhs) = reinterpret_cast<__copy_cvref_t<_From, __punned_type>&&>(__rhs);
+ }
+
+ template <class _To,
+ class _From,
+ class _ValueT = _Tp,
+ __enable_if_t<__is_tree_value_type<_ValueT>::value && !__is_pair_v<__remove_cvref_t<_From> >, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI static void __assign_value(_To& __lhs, _From&& __rhs) {
+ static_assert(__is_pair_v<__remove_cvref_t<_From> >);
+ using __punned_type = pair<typename _NodeTypes::key_type, typename _NodeTypes::mapped_type>;
+
+ reinterpret_cast<__punned_type&>(__lhs) = __rhs;
+ }
+
+ template <class _To,
+ class _From,
+ class _ValueT = _Tp,
+ __enable_if_t<!__is_tree_value_type<_ValueT>::value && !__is_pair_v<__remove_cvref_t<_From> >, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI static void __assign_value(_To& __lhs, _From&& __rhs) {
+ __lhs = std::forward<_From>(__rhs);
+ }
+
struct _DetachedTreeCache {
_LIBCPP_HIDE_FROM_ABI explicit _DetachedTreeCache(__tree* __t) _NOEXCEPT
: __t_(__t),
@@ -1416,13 +1433,13 @@ void __tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _
if (size() != 0) {
_DetachedTreeCache __cache(this);
for (; __cache.__get() && __first != __last; ++__first) {
- __cache.__get()->__value_ = *__first;
+ __assign_value(__cache.__get()->__value_, *__first);
__node_insert_multi(__cache.__get());
__cache.__advance();
}
}
for (; __first != __last; ++__first)
- __insert_multi(_NodeTypes::__get_value(*__first));
+ __insert_multi(*__first);
}
template <class _Tp, class _Compare, class _Allocator>
@@ -1501,13 +1518,19 @@ void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type) {
if (size() != 0) {
_DetachedTreeCache __cache(this);
while (__cache.__get() != nullptr && __t.size() != 0) {
- __cache.__get()->__value_ = std::move(__t.remove(__t.begin())->__value_);
+ __assign_value(__cache.__get()->__value_, std::move(__t.remove(__t.begin())->__value_));
__node_insert_multi(__cache.__get());
__cache.__advance();
}
}
- while (__t.size() != 0)
- __insert_multi(__e, _NodeTypes::__move(__t.remove(__t.begin())->__value_));
+ while (__t.size() != 0) {
+ if constexpr (__is_tree_value_type<_Tp>::value) {
+ using __punned_type = pair<typename _NodeTypes::key_type, typename _NodeTypes::mapped_type>;
+ __insert_multi(__e, reinterpret_cast<__punned_type&&>(__t.remove(__t.begin())->__value_));
+ } else {
+ __insert_multi(__e, std::move(__t.remove(__t.begin())->__value_));
+ }
+ }
}
}
@@ -1533,7 +1556,7 @@ void __tree<_Tp, _Compare, _Allocator>::destroy(__node_pointer __nd) _NOEXCEPT {
destroy(static_cast<__node_pointer>(__nd->__left_));
destroy(static_cast<__node_pointer>(__nd->__right_));
__node_allocator& __na = __node_alloc();
- __node_traits::destroy(__na, _NodeTypes::__get_ptr(__nd->__value_));
+ __node_traits::destroy(__na, std::addressof(__nd->__value_));
__node_traits::deallocate(__na, __nd, 1);
}
}
@@ -1803,10 +1826,9 @@ template <class _Tp, class _Compare, class _Allocator>
template <class... _Args>
typename __tree<_Tp, _Compare, _Allocator>::__node_holder
__tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&&... __args) {
- static_assert(!__is_tree_value_type<_Args...>::value, "Cannot construct from __value_type");
__node_allocator& __na = __node_alloc();
__node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
- __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), std::forward<_Args>(__args)...);
+ __node_traits::construct(__na, std::addressof(__h->__value_), std::forward<_Args>(__args)...);
__h.get_deleter().__value_constructed = true;
return __h;
}
@@ -1874,7 +1896,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const __container_value_
__node_pointer __r = static_cast<__node_pointer>(__child);
bool __inserted = false;
if (__child == nullptr) {
- __nd->__value_ = __v;
+ __assign_value(__nd->__value_, __v);
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
__r = __nd;
__inserted = true;
@@ -2036,7 +2058,7 @@ typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allo
__node_pointer __np = __p.__get_np();
iterator __r = __remove_node_pointer(__np);
__node_allocator& __na = __node_alloc();
- __node_traits::destroy(__na, _NodeTypes::__get_ptr(const_cast<__node_value_type&>(*__p)));
+ __node_traits::destroy(__na, std::addressof(const_cast<__node_value_type&>(*__p)));
__node_traits::deallocate(__na, __np, 1);
return __r;
}
diff --git a/libcxx/include/map b/libcxx/include/map
index e7e0c14e36999..e60ecac9c28d1 100644
--- a/libcxx/include/map
+++ b/libcxx/include/map
@@ -645,13 +645,13 @@ public:
: _Compare(__c) {}
_LIBCPP_HIDE_FROM_ABI const _Compare& key_comp() const _NOEXCEPT { return *this; }
_LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _CP& __y) const {
- return static_cast<const _Compare&>(*this)(__x.__get_value().first, __y.__get_value().first);
+ return static_cast<const _Compare&>(*this)(__x.first, __y.first);
}
_LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _Key& __y) const {
- return static_cast<const _Compare&>(*this)(__x.__get_value().first, __y);
+ return static_cast<const _Compare&>(*this)(__x.first, __y);
}
_LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _CP& __y) const {
- return static_cast<const _Compare&>(*this)(__x, __y.__get_value().first);
+ return static_cast<const _Compare&>(*this)(__x, __y.first);
}
_LIBCPP_HIDE_FROM_ABI void swap(__map_value_compare& __y) _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) {
using std::swap;
@@ -661,12 +661,12 @@ public:
# if _LIBCPP_STD_VER >= 14
template <typename _K2>
_LIBCPP_HIDE_FROM_ABI bool operator()(const _K2& __x, const _CP& __y) const {
- return static_cast<const _Compare&>(*this)(__x, __y.__get_value().first);
+ return static_cast<const _Compare&>(*this)(__x, __y.first);
}
template <typename _K2>
_LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _K2& __y) const {
- return static_cast<const _Compare&>(*this)(__x.__get_value().first, __y);
+ return static_cast<const _Compare&>(*this)(__x.first, __y);
}
# endif
};
@@ -683,13 +683,13 @@ public:
_LIBCPP_HIDE_FROM_ABI const _Compare& key_comp() const _NOEXCEPT { return __comp_; }
_LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _CP& __y) const {
- return __comp_(__x.__get_value().first, __y.__get_value().first);
+ return __comp_(__x.first, __y.first);
}
_LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _Key& __y) const {
- return __comp_(__x.__get_value().first, __y);
+ return __comp_(__x.first, __y);
}
_LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _CP& __y) const {
- return __comp_(__x, __y.__get_value().first);
+ return __comp_(__x, __y.first);
}
void swap(__map_value_compare& __y) _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) {
using std::swap;
@@ -763,64 +763,7 @@ class __map_const_iterator;
# ifndef _LIBCPP_CXX03_LANG
template <class _Key, class _Tp>
-struct _LIBCPP_STANDALONE_DEBUG __value_type {
- typedef _Key key_type;
- typedef _Tp mapped_type;
- typedef pair<const key_type, mapped_type> value_type;
- typedef pair<key_type&, mapped_type&> __nc_ref_pair_type;
- typedef pair<key_type&&, mapped_type&&> __nc_rref_pair_type;
-
-private:
- value_type __cc_;
-
-public:
- _LIBCPP_HIDE_FROM_ABI value_type& __get_value() {
-# if _LIBCPP_STD_VER >= 17
- return *std::launder(std::addressof(__cc_));
-# else
- return __cc_;
-# endif
- }
-
- _LIBCPP_HIDE_FROM_ABI const value_type& __get_value() const {
-# if _LIBCPP_STD_VER >= 17
- return *std::launder(std::addressof(__cc_));
-# else
- return __cc_;
-# endif
- }
-
- _LIBCPP_HIDE_FROM_ABI __nc_ref_pair_type __ref() {
- value_type& __v = __get_value();
- return __nc_ref_pair_type(const_cast<key_type&>(__v.first), __v.second);
- }
-
- _LIBCPP_HIDE_FROM_ABI __nc_rref_pair_type __move() {
- value_type& __v = __get_value();
- return __nc_rref_pair_type(std::move(const_cast<key_type&>(__v.first)), std::move(__v.second));
- }
-
- _LIBCPP_HIDE_FROM_ABI __value_type& operator=(const __value_type& __v) {
- __ref() = __v.__get_value();
- return *this;
- }
-
- _LIBCPP_HIDE_FROM_ABI __value_type& operator=(__value_type&& __v) {
- __ref() = __v.__move();
- return *this;
- }
-
- template <class _ValueTp, __enable_if_t<__is_same_uncvref<_ValueTp, value_type>::value, int> = 0>
- _LIBCPP_HIDE_FROM_ABI __value_type& operator=(_ValueTp&& __v) {
- __ref() = std::forward<_ValueTp>(__v);
- return *this;
- }
-
- __value_type() = delete;
- ~__value_type() = delete;
- __value_type(const __value_type&) = delete;
- __value_type(__value_type&&) = delete;
-};
+struct _LIBCPP_STANDALONE_DEBUG __value_type;
# else
@@ -872,8 +815,8 @@ public:
_LIBCPP_HIDE_FROM_ABI __map_iterator(_TreeIterator __i) _NOEXCEPT : __i_(__i) {}
- _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __i_->__get_value(); }
- _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits<pointer>::pointer_to(__i_->__get_value()); }
+ _LIBCPP_HIDE_FROM_ABI reference operator*() const { return *__i_; }
+ _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits<pointer>::pointer_to(*__i_); }
_LIBCPP_HIDE_FROM_ABI __map_iterator& operator++() {
++__i_;
@@ -930,8 +873,8 @@ public:
_LIBCPP_HIDE_FROM_ABI
__map_const_iterator(__map_iterator< typename _TreeIterator::__non_const_iterator> __i) _NOEXCEPT : __i_(__i.__i_) {}
- _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __i_->__get_value(); }
- _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits<pointer>::pointer_to(__i_->__get_value()); }
+ _LIBCPP_HIDE_FROM_ABI reference operator*() const { return *__i_; }
+ _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits<pointer>::pointer_to(*__i_); }
_LIBCPP_HIDE_FROM_ABI __map_const_iterator& operator++() {
++__i_;
@@ -999,7 +942,7 @@ public:
private:
typedef std::__value_type<key_type, mapped_type> __value_type;
- typedef __map_value_compare<key_type, __value_type, key_compare> __vc;
+ typedef __map_value_compare<key_type, value_type, key_compare> __vc;
typedef __rebind_alloc<allocator_traits<allocator_type>, __value_type> __allocator_type;
typedef __tree<__value_type, __vc, __allocator_type> __base;
typedef typename __base::__node_traits __node_traits;
@@ -1305,7 +1248,7 @@ public:
__tree_.__emplace_hint_unique_key_args(__h.__i_, __k, std::move(__k), std::forward<_Vp>(__v));
if (!__inserted)
- __r->__get_value().second = std::forward<_Vp>(__v);
+ __r->second = std::forward<_Vp>(__v);
return __r;
}
@@ -1510,8 +1453,10 @@ map<_Key, _Tp, _Compare, _Allocator>::map(map&& __m, const allocator_type& __a)
: __tree_(std::move(__m.__tree_), typename __base::allocator_type(__a)) {
if (__a != __m.get_allocator()) {
const_iterator __e = cend();
- while (!__m.empty())
- __tree_.__insert_unique(__e.__i_, __m.__tree_.remove(__m.begin().__i_)->__value_.__move());
+ while (!__m.empty()) {
+ __tree_.__insert_unique(
+ __e.__i_, reinterpret_cast<pair<_Key, _Tp>&&>(__m.__tree_.remove(__m.begin().__i_)->__value_));
+ }
}
}
@@ -1519,8 +1464,7 @@ template <class _Key, class _Tp, class _Compare, class _Allocator>
_Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) {
return __tree_
.__emplace_unique_key_args(__k, std::piecewise_construct, std::forward_as_tuple(__k), std::forward_as_tuple())
- .first->__get_value()
- .second;
+ .first->second;
}
template <class _Key, class _Tp, class _Compare, class _Allocator>
@@ -1530,8 +1474,7 @@ _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](key_type&& __k) {
return __tree_
.__emplace_unique_key_args(
__k, std::piecewise_construct, std::forward_as_tuple(std::move(__k)), std::forward_as_tuple())
- .first->__get_value()
- .second;
+ .first->second;
// NOLINTEND(bugprone-use-after-move)
}
@@ -1570,7 +1513,7 @@ _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) {
__node_base_pointer& __child = __tree_.__find_equal(__parent, __k);
if (__child == nullptr)
std::__throw_out_of_range("map::at: key not found");
- return static_cast<__node_pointer>(__child)->__value_.__get_value().second;
+ return static_cast<__node_pointer>(__child)->__value_.second;
}
template <class _Key, class _Tp, class _Compare, class _Allocator>
@@ -1579,7 +1522,7 @@ const _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) const {
__node_base_pointer __child = __tree_.__find_equal(__parent, __k);
if (__child == nullptr)
std::__throw_out_of_range("map::at: key not found");
- return static_cast<__node_pointer>(__child)->__value_.__get_value().second;
+ return static_cast<__node_pointer>(__child)->__value_.second;
}
template <class _Key, class _Tp, class _Compare, class _Allocator>
@@ -1685,7 +1628,7 @@ public:
private:
typedef std::__value_type<key_type, mapped_type> __value_type;
- typedef __map_value_compare<key_type, __value_type, key_compare> __vc;
+ typedef __map_value_compare<key_type, value_type, key_compare> __vc;
typedef __rebind_alloc<allocator_traits<allocator_type>, __value_type> __allocator_type;
typedef __tree<__value_type, __vc, __allocator_type> __base;
typedef typename __base::__node_traits __node_traits;
@@ -2100,7 +2043,8 @@ multimap<_Key, _Tp, _Compare, _Allocator>::multimap(multimap&& __m, const alloca
if (__a != __m.get_allocator()) {
const_iterator __e = cend();
while (!__m.empty())
- __tree_.__insert_multi(__e.__i_, std::move(__m.__tree_.remove(__m.begin().__i_)->__value_.__move()));
+ __tree_.__insert_multi(
+ __e.__i_, reinterpret_cast<pair<_Key, _Tp>&&>(__m.__tree_.remove(__m.begin().__i_)->__value_));
}
}
# endif
diff --git a/libcxx/test/libcxx/containers/associative/tree_key_value_traits.pass.cpp b/libcxx/test/libcxx/containers/associative/tree_key_value_traits.pass.cpp
index e3a5a6f634138..04dcb8f54fafc 100644
--- a/libcxx/test/libcxx/containers/associative/tree_key_value_traits.pass.cpp
+++ b/libcxx/test/libcxx/containers/associative/tree_key_value_traits.pass.cpp
@@ -21,7 +21,6 @@ void testKeyValueTrait() {
typedef int Tp;
typedef std::__tree_key_value_types<Tp> Traits;
static_assert((std::is_same<Traits::key_type, int>::value), "");
- static_assert((std::is_same<Traits::__node_value_type, Tp>::value), "");
static_assert((std::is_same<Traits::__container_value_type, Tp>::value), "");
static_assert(Traits::__is_map == false, "");
}
@@ -29,7 +28,6 @@ void testKeyValueTrait() {
typedef std::pair<int, int> Tp;
typedef std::__tree_key_value_types<Tp> Traits;
static_assert((std::is_same<Traits::key_type, Tp>::value), "");
- static_assert((std::is_same<Traits::__node_value_type, Tp>::value), "");
static_assert((std::is_same<Traits::__container_value_type, Tp>::value), "");
static_assert(Traits::__is_map == false, "");
}
@@ -37,7 +35,6 @@ void testKeyValueTrait() {
typedef std::pair<const int, int> Tp;
typedef std::__tree_key_value_types<Tp> Traits;
static_assert((std::is_same<Traits::key_type, Tp>::value), "");
- static_assert((std::is_same<Traits::__node_value_type, Tp>::value), "");
static_assert((std::is_same<Traits::__container_value_type, Tp>::value), "");
static_assert(Traits::__is_map == false, "");
}
@@ -46,7 +43,6 @@ void testKeyValueTrait() {
typedef std::__tree_key_value_types<Tp> Traits;
static_assert((std::is_same<Traits::key_type, int>::value), "");
static_assert((std::is_same<Traits::mapped_type, int>::value), "");
- static_assert((std::is_same<Traits::__node_value_type, Tp>::value), "");
static_assert((std::is_same<Traits::__container_value_type, std::pair<const int, int> >::value), "");
static_assert((std::is_same<Traits::__map_value_type, std::pair<const int, int> >::value), "");
static_assert(Traits::__is_map == true, "");
More information about the libcxx-commits
mailing list