[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
Sat Apr 12 01:22:47 PDT 2025
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/134819
>From 0eeaaaf975182a1a5818f798d1dab502f6a525e2 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 | 97 ++++++++------
libcxx/include/map | 125 +++++-------------
.../tree_key_value_traits.pass.cpp | 4 -
libcxx/utils/gdb/libcxx/printers.py | 4 +-
7 files changed, 124 insertions(+), 153 deletions(-)
diff --git a/libcxx/include/__fwd/pair.h b/libcxx/include/__fwd/pair.h
index ea81a81ef8e11..cf07eabab6903 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 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 08c4ffa5ff17b..5c559c657ef50 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 e84bc4ffda0bd..4275133f8a351 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 _LIBCPP_NODEBUG = 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 _LIBCPP_NODEBUG = __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 _LIBCPP_NODEBUG = __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 __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 __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_) {}
@@ -1135,6 +1126,17 @@ public:
return __emplace_hint_multi(__p, std::forward<_Vp>(__v));
}
+ template <class _ValueT = _Tp, __enable_if_t<__is_tree_value_type<_ValueT>::value, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI void __insert_from_orphaned_node(const_iterator __p, __get_node_value_type_t<_Tp>&& __value) {
+ using __key_type = typename _NodeTypes::key_type;
+ __emplace_hint_multi(__p, const_cast<__key_type&&>(__value.first), std::move(__value.second));
+ }
+
+ template <class _ValueT = _Tp, __enable_if_t<!__is_tree_value_type<_ValueT>::value, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI void __insert_from_orphaned_node(const_iterator __p, _Tp&& __value) {
+ __emplace_hint_multi(__p, std::move(__value));
+ }
+
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool>
__node_assign_unique(const __container_value_type& __v, __node_pointer __dest);
@@ -1276,6 +1278,19 @@ 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 __key_type = typename _NodeTypes::key_type;
+
+ const_cast<__key_type&>(__lhs.first) = const_cast<__copy_cvref_t<_From, __key_type>&&>(__rhs.first);
+ __lhs.second = std::forward<_From>(__rhs).second;
+ }
+
+ template <class _To, class _From, class _ValueT = _Tp, __enable_if_t<!__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 +1431,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 +1516,14 @@ 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) {
+ __insert_from_orphaned_node(__e, std::move(__t.remove(__t.begin())->__value_));
+ }
}
}
@@ -1533,7 +1549,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 +1819,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 +1889,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 +2051,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 a244696295fb8..1821aa0155a29 100644
--- a/libcxx/include/map
+++ b/libcxx/include/map
@@ -593,7 +593,6 @@ erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred); // C++20
# include <__memory/pointer_traits.h>
# include <__memory/unique_ptr.h>
# include <__memory_resource/polymorphic_allocator.h>
-# include <__new/launder.h>
# include <__node_handle>
# include <__ranges/concepts.h>
# include <__ranges/container_compatible_range.h>
@@ -645,13 +644,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 +660,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
};
@@ -682,15 +681,9 @@ public:
: __comp_(__c) {}
_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);
- }
- _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _Key& __y) const {
- return __comp_(__x.__get_value().first, __y);
- }
- _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _CP& __y) const {
- return __comp_(__x, __y.__get_value().first);
- }
+ _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _CP& __y) const { return __comp_(__x.first, __y.first); }
+ _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _Key& __y) const { return __comp_(__x.first, __y); }
+ _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _CP& __y) const { return __comp_(__x, __y.first); }
void swap(__map_value_compare& __y) _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) {
using std::swap;
swap(__comp_, __y.__comp_);
@@ -749,9 +742,9 @@ public:
_LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT {
if (__second_constructed)
- __alloc_traits::destroy(__na_, std::addressof(__p->__value_.__get_value().second));
+ __alloc_traits::destroy(__na_, std::addressof(__p->__value_.second));
if (__first_constructed)
- __alloc_traits::destroy(__na_, std::addressof(__p->__value_.__get_value().first));
+ __alloc_traits::destroy(__na_, std::addressof(__p->__value_.first));
if (__p)
__alloc_traits::deallocate(__na_, __p, 1);
}
@@ -763,64 +756,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 +808,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 +866,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 +935,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 +1241,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 +1446,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 +1457,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 +1467,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)
}
@@ -1542,9 +1478,9 @@ typename map<_Key, _Tp, _Compare, _Allocator>::__node_holder
map<_Key, _Tp, _Compare, _Allocator>::__construct_node_with_key(const key_type& __k) {
__node_allocator& __na = __tree_.__node_alloc();
__node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
- __node_traits::construct(__na, std::addressof(__h->__value_.__get_value().first), __k);
+ __node_traits::construct(__na, std::addressof(__h->__value_.first), __k);
__h.get_deleter().__first_constructed = true;
- __node_traits::construct(__na, std::addressof(__h->__value_.__get_value().second));
+ __node_traits::construct(__na, std::addressof(__h->__value_.second));
__h.get_deleter().__second_constructed = true;
return __h;
}
@@ -1559,7 +1495,7 @@ _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) {
__tree_.__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
__r = __h.release();
}
- return __r->__value_.__get_value().second;
+ return __r->__value_.second;
}
# endif // _LIBCPP_CXX03_LANG
@@ -1570,7 +1506,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 +1515,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 +1621,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 +2036,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, "");
diff --git a/libcxx/utils/gdb/libcxx/printers.py b/libcxx/utils/gdb/libcxx/printers.py
index 31c27a1959cb2..e3d5d87aca325 100644
--- a/libcxx/utils/gdb/libcxx/printers.py
+++ b/libcxx/utils/gdb/libcxx/printers.py
@@ -673,7 +673,7 @@ def display_hint(self):
return "map"
def _get_key_value(self, node):
- key_value = _cc_field(node.cast(self.util.cast_type).dereference())
+ key_value = node.cast(self.util.cast_type).dereference()["__value_"]
return [key_value["first"], key_value["second"]]
@@ -738,7 +738,7 @@ def __init__(self, val):
self._initialize(val["__i_"], _remove_generics(_prettify_typename(val.type)))
def _get_node_value(self, node):
- return _cc_field(node)
+ return node["__value_"]
class SetIteratorPrinter(AbstractRBTreeIteratorPrinter):
More information about the libcxx-commits
mailing list