[libcxx-commits] [libcxx] map, unordered_map: use static method for getting value of __hash_value_type (PR #135365)

via libcxx-commits libcxx-commits at lists.llvm.org
Fri Apr 11 06:23:53 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Sergey (sssersh)

<details>
<summary>Changes</summary>

Method __get_value() in __hash_value_type is used to access to address of stored in __hash_value_type value.

This method called in __hash_table::__construct_node via _NodeTypes::__get_ptr() before creation of object __hash_value_type.

But according to [basic.life]:
"Before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that represents the address of the storage location where the object will be or was located may be used but only in limited ways.[...]
The program has undefined behavior if [...] the pointer is used to access a non-static data member or call a non-static member function of the object [...]".

But it's possible to access to member in __hash_value_type using pointer interconvertibility according to [basic.compound]: "Two objects a and b are pointer-interconvertible if [...] - one is a standard-layout class object and the other is the first non-static data member of that object, or, if the object has no non-static data members, the first base class subobject of that object, or [...]. If two objects are pointer-interconvertible, then they have the same address, and it is possible to obtain a pointer to one from a pointer to the other via a reinterpret_cast."


---

Patch is 43.81 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/135365.diff


9 Files Affected:

- (modified) libcxx/include/__cxx03/__hash_table (+2-2) 
- (modified) libcxx/include/__cxx03/__tree (+3-3) 
- (modified) libcxx/include/__cxx03/map (+57-41) 
- (modified) libcxx/include/__cxx03/unordered_map (+22-10) 
- (modified) libcxx/include/__hash_table (+2-2) 
- (modified) libcxx/include/__tree (+2-2) 
- (modified) libcxx/include/ext/hash_map (+4-4) 
- (modified) libcxx/include/map (+56-41) 
- (modified) libcxx/include/unordered_map (+60-40) 


``````````diff
diff --git a/libcxx/include/__cxx03/__hash_table b/libcxx/include/__cxx03/__hash_table
index a4eff8c654f11..4ffe633b14501 100644
--- a/libcxx/include/__cxx03/__hash_table
+++ b/libcxx/include/__cxx03/__hash_table
@@ -183,7 +183,7 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > {
 
   template <class _Up, __enable_if_t<__is_same_uncvref<_Up, __node_value_type>::value, int> = 0>
   _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) {
-    return __t.__get_value();
+    return _Up::__get_value(__t);
   }
 
   template <class _Up, __enable_if_t<__is_same_uncvref<_Up, __container_value_type>::value, int> = 0>
@@ -192,7 +192,7 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > {
   }
 
   _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) {
-    return std::addressof(__n.__get_value());
+    return std::addressof(__node_value_type::__get_value(__n));
   }
   _LIBCPP_HIDE_FROM_ABI static pair<key_type&&, mapped_type&&> __move(__node_value_type& __v) { return __v.__move(); }
 };
diff --git a/libcxx/include/__cxx03/__tree b/libcxx/include/__cxx03/__tree
index aec20a7541b26..1c4cd18804817 100644
--- a/libcxx/include/__cxx03/__tree
+++ b/libcxx/include/__cxx03/__tree
@@ -533,7 +533,7 @@ struct __tree_key_value_types<__value_type<_Key, _Tp> > {
   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;
+    return __node_value_type::__get_value(__t).first;
   }
 
   template <class _Up, __enable_if_t<__is_same_uncvref<_Up, __container_value_type>::value, int> = 0>
@@ -542,7 +542,7 @@ struct __tree_key_value_types<__value_type<_Key, _Tp> > {
   }
 
   _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(__node_value_type const& __t) {
-    return __t.__get_value();
+    return __node_value_type::__get_value(__t);
   }
 
   template <class _Up, __enable_if_t<__is_same_uncvref<_Up, __container_value_type>::value, int> = 0>
@@ -551,7 +551,7 @@ struct __tree_key_value_types<__value_type<_Key, _Tp> > {
   }
 
   _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) {
-    return std::addressof(__n.__get_value());
+    return std::addressof(__node_value_type::__get_value(__n));
   }
 
   _LIBCPP_HIDE_FROM_ABI static pair<key_type&&, mapped_type&&> __move(__node_value_type& __v) { return __v.__move(); }
diff --git a/libcxx/include/__cxx03/map b/libcxx/include/__cxx03/map
index ca097f583acc0..3371f3d7dcd3f 100644
--- a/libcxx/include/__cxx03/map
+++ b/libcxx/include/__cxx03/map
@@ -584,6 +584,7 @@ erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred);  // C++20
 #include <__cxx03/__memory/allocator.h>
 #include <__cxx03/__tree>
 #include <__cxx03/__type_traits/is_allocator.h>
+#include <__cxx03/__type_traits/is_standard_layout.h>
 #include <__cxx03/__utility/forward.h>
 #include <__cxx03/__utility/piecewise_construct.h>
 #include <__cxx03/__utility/swap.h>
@@ -616,13 +617,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)(_CP::__get_value(__x).first, _CP::__get_value(__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)(_CP::__get_value(__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, _CP::__get_value(__y).first);
   }
   _LIBCPP_HIDE_FROM_ABI void swap(__map_value_compare& __y) _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) {
     using std::swap;
@@ -632,12 +633,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, _CP::__get_value(__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)(_CP::__get_value(__x).first, __y);
   }
 #endif
 };
@@ -654,13 +655,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_(_CP::__get_value(__x).first, _CP::__get_value(__y).first);
   }
   _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _Key& __y) const {
-    return __comp_(__x.__get_value().first, __y);
+    return __comp_(_CP::__get_value(__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, _CP::__get_value(__y).first);
   }
   void swap(__map_value_compare& __y) _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) {
     using std::swap;
@@ -670,12 +671,12 @@ public:
 #if _LIBCPP_STD_VER >= 14
   template <typename _K2>
   _LIBCPP_HIDE_FROM_ABI bool operator()(const _K2& __x, const _CP& __y) const {
-    return __comp_(__x, __y.__get_value().first);
+    return __comp_(__x, _CP::__get_value(__y).first);
   }
 
   template <typename _K2>
   _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _K2& __y) const {
-    return __comp_(__x.__get_value().first, __y);
+    return __comp_(_CP::__get_value(__x).first, __y);
   }
 #endif
 };
@@ -691,6 +692,7 @@ template <class _Allocator>
 class __map_node_destructor {
   typedef _Allocator allocator_type;
   typedef allocator_traits<allocator_type> __alloc_traits;
+  typedef __alloc_traits::value_type value_type;
 
 public:
   typedef typename __alloc_traits::pointer pointer;
@@ -720,9 +722,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(value_type::__get_value(__p->__value_).second));
     if (__first_constructed)
-      __alloc_traits::destroy(__na_, std::addressof(__p->__value_.__get_value().first));
+      __alloc_traits::destroy(__na_, std::addressof(value_type::__get_value(__p->__value_).first));
     if (__p)
       __alloc_traits::deallocate(__na_, __p, 1);
   }
@@ -749,34 +751,34 @@ private:
   value_type __cc_;
 
 public:
-  _LIBCPP_HIDE_FROM_ABI value_type& __get_value() {
+  _LIBCPP_HIDE_FROM_ABI static value_type& __get_value(__hash_value_type& __v) {
 #  if _LIBCPP_STD_VER >= 17
-    return *std::launder(std::addressof(__cc_));
+    return *std::launder(std::addressof(reinterpret_cast<const value_type&>(__v)));
 #  else
-    return __cc_;
+    return reinterpret_cast<const value_type&>(__v);
 #  endif
   }
 
-  _LIBCPP_HIDE_FROM_ABI const value_type& __get_value() const {
+  _LIBCPP_HIDE_FROM_ABI static const value_type& __get_value(const __hash_value_type& __v) {
 #  if _LIBCPP_STD_VER >= 17
-    return *std::launder(std::addressof(__cc_));
+    return *std::launder(std::addressof(reinterpret_cast<value_type&>(__v)));
 #  else
-    return __cc_;
+    return reinterpret_cast<value_type&>(__v);
 #  endif
   }
 
   _LIBCPP_HIDE_FROM_ABI __nc_ref_pair_type __ref() {
-    value_type& __v = __get_value();
+    value_type& __v = __get_value(*this);
     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();
+    value_type& __v = __get_value(*this);
     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();
+    __ref() = __get_value(__v);
     return *this;
   }
 
@@ -808,9 +810,17 @@ struct __value_type {
 private:
   value_type __cc_;
 
+private:
+  static_assert(is_standard_layout_v<__hash_value_type<_Key, _Tp>>, "");
+
 public:
-  _LIBCPP_HIDE_FROM_ABI value_type& __get_value() { return __cc_; }
-  _LIBCPP_HIDE_FROM_ABI const value_type& __get_value() const { return __cc_; }
+  _LIBCPP_HIDE_FROM_ABI static value_type& __get_value(__hash_value_type& __v) {
+    return reinterpret_cast<value_type&>(__v);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI static const value_type& __get_value(const __hash_value_type& __v) const {
+    return reinterpret_cast<const value_type&>(__v);
+  }
 
   __value_type()                               = delete;
   __value_type(__value_type const&)            = delete;
@@ -847,8 +857,10 @@ 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 value_type::__get_value(*__i_); }
+  _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
+    return pointer_traits<pointer>::pointer_to(value_type::__get_value(*__i_));
+  }
 
   _LIBCPP_HIDE_FROM_ABI __map_iterator& operator++() {
     ++__i_;
@@ -905,8 +917,10 @@ 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 value_type::__get_value(*__i_); }
+  _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
+    return pointer_traits<pointer>::pointer_to(value_type::__get_value(*__i_));
+  }
 
   _LIBCPP_HIDE_FROM_ABI __map_const_iterator& operator++() {
     ++__i_;
@@ -1269,7 +1283,7 @@ public:
     auto [__r, __inserted] = __tree_.__emplace_hint_unique_key_args(__h.__i_, __k, __k, std::forward<_Vp>(__v));
 
     if (!__inserted)
-      __r->__get_value().second = std::forward<_Vp>(__v);
+      __value_type::__get_value(*__r).second = std::forward<_Vp>(__v);
 
     return __r;
   }
@@ -1280,7 +1294,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);
+      __value_type::__get_value(*__r).second = std::forward<_Vp>(__v);
 
     return __r;
   }
@@ -1492,9 +1506,10 @@ map<_Key, _Tp, _Compare, _Allocator>::map(map&& __m, const allocator_type& __a)
 
 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()
+  return _Tp::__get_value(__tree_
+                              .__emplace_unique_key_args(
+                                  __k, std::piecewise_construct, std::forward_as_tuple(__k), std::forward_as_tuple())
+                              .first)
       .second;
 }
 
@@ -1502,10 +1517,11 @@ template <class _Key, class _Tp, class _Compare, class _Allocator>
 _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](key_type&& __k) {
   // TODO investigate this clang-tidy warning.
   // NOLINTBEGIN(bugprone-use-after-move)
-  return __tree_
-      .__emplace_unique_key_args(
-          __k, std::piecewise_construct, std::forward_as_tuple(std::move(__k)), std::forward_as_tuple())
-      .first->__get_value()
+  return _Tp::__get_value(
+             __tree_
+                 .__emplace_unique_key_args(
+                     __k, std::piecewise_construct, std::forward_as_tuple(std::move(__k)), std::forward_as_tuple())
+                 .first)
       .second;
   // NOLINTEND(bugprone-use-after-move)
 }
@@ -1517,9 +1533,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(_Tp::__get_value(__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(_Tp::__get_value(__h->__value_).second));
   __h.get_deleter().__second_constructed = true;
   return __h;
 }
@@ -1534,7 +1550,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 _Tp::__get_value(__r->__value_).second;
 }
 
 #endif // _LIBCPP_CXX03_LANG
@@ -1545,7 +1561,7 @@ _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) {
   __node_base_pointer& __child = __tree_.__find_equal(__parent, __k);
   if (__child == nullptr)
     __throw_out_of_range("map::at:  key not found");
-  return static_cast<__node_pointer>(__child)->__value_.__get_value().second;
+  return _Tp::__get_value(static_cast<__node_pointer>(__child)->__value_).second;
 }
 
 template <class _Key, class _Tp, class _Compare, class _Allocator>
@@ -1554,7 +1570,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)
     __throw_out_of_range("map::at:  key not found");
-  return static_cast<__node_pointer>(__child)->__value_.__get_value().second;
+  return _Tp::__get_value(static_cast<__node_pointer>(__child)->__value_).second;
 }
 
 template <class _Key, class _Tp, class _Compare, class _Allocator>
diff --git a/libcxx/include/__cxx03/unordered_map b/libcxx/include/__cxx03/unordered_map
index 10e84f35a3578..647c00a5a0594 100644
--- a/libcxx/include/__cxx03/unordered_map
+++ b/libcxx/include/__cxx03/unordered_map
@@ -594,6 +594,7 @@ template <class Key, class T, class Hash, class Pred, class Alloc>
 #include <__cxx03/__memory/addressof.h>
 #include <__cxx03/__memory/allocator.h>
 #include <__cxx03/__type_traits/is_allocator.h>
+#include <__cxx03/__type_traits/is_standard_layout.h>
 #include <__cxx03/__type_traits/type_identity.h>
 #include <__cxx03/__utility/forward.h>
 #include <__cxx03/stdexcept>
@@ -823,30 +824,33 @@ struct _LIBCPP_STANDALONE_DEBUG __hash_value_type {
 private:
   value_type __cc_;
 
+private:
+  static_assert(std::is_standard_layout_v<__hash_value_type<_Key, _Tp>>, "");
+
 public:
-  _LIBCPP_HIDE_FROM_ABI value_type& __get_value() {
+  _LIBCPP_HIDE_FROM_ABI static value_type& __get_value(__hash_value_type& __v) {
 #  if _LIBCPP_STD_VER >= 17
-    return *std::launder(std::addressof(__cc_));
+    return *std::launder(std::addressof(reinterpret_cast<const value_type&>(__v)));
 #  else
-    return __cc_;
+    return reinterpret_cast<const value_type&>(__v);
 #  endif
   }
 
-  _LIBCPP_HIDE_FROM_ABI const value_type& __get_value() const {
+  _LIBCPP_HIDE_FROM_ABI static const value_type& __get_value(const __hash_value_type& __v) {
 #  if _LIBCPP_STD_VER >= 17
-    return *std::launder(std::addressof(__cc_));
+    return *std::launder(std::addressof(reinterpret_cast<value_type&>(__v)));
 #  else
-    return __cc_;
+    return reinterpret_cast<value_type&>(__v);
 #  endif
   }
 
   _LIBCPP_HIDE_FROM_ABI __nc_ref_pair_type __ref() {
-    value_type& __v = __get_value();
+    value_type& __v = __get_value(*this);
     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();
+    value_type& __v = __get_value(*this);
     return __nc_rref_pair_type(std::move(const_cast<key_type&>(__v.first)), std::move(__v.second));
   }
 
@@ -885,9 +889,17 @@ struct __hash_value_type {
 private:
   value_type __cc_;
 
+private:
+  static_assert(is_standard_layout_v<__hash_value_type<_Key, _Tp>>, "");
+
 public:
-  _LIBCPP_HIDE_FROM_ABI value_type& __get_value() { return __cc_; }
-  _LIBCPP_HIDE_FROM_ABI const value_type& __get_value() const { return __cc_; }
+  _LIBCPP_HIDE_FROM_ABI static value_type& __get_value(__hash_value_type& __v) {
+    return reinterpret_cast<value_type&>(__v);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI static const value_type& __get_value(const __hash_value_type& __v) const {
+    return reinterpret_cast<const value_type&>(__v);
+  }
 
   ~__hash_value_type() = delete;
 };
diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index fca58ca296067..9bcf042a9306e 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -193,7 +193,7 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > {
 
   template <class _Up, __enable_if_t<__is_same_uncvref<_Up, __node_value_type>::value, int> = 0>
   _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) {
-    return __t.__get_value();
+    return __node_value_type::__get_value(__t);
   }
 
   template <class _Up, __enable_if_t<__is_same_uncvref<_Up, __container_value_type>::value, int> = 0>
@@ -202,7 +202,7 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > {
   }
 
   _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) {
-    return std::addressof(__n.__get_value());
+    return std::addressof(__node_value_type::__get_value(__n));
   }
   _LIBCPP_HIDE_FROM_ABI static pair<key_type&&, mapped_type&&> __move(__node_value_type& __v) { return __v.__move(); }
 };
diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index e84bc4ffda0bd..bcb25924b0bed 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -534,7 +534,7 @@ struct __tree_key_value_types<__value_type<_Key, _Tp> > {
   }
 
   _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(__node_value_type const& __t) {
-    return __t.__get_value();
+    return __node_value_type::__get_value(__t);
   }
 
   template <class _Up, __enable_if_t<__is_same_uncvref<_Up, __container_value_type>::value, int> = 0>
@@ -543,7 +543,7 @@ struct __tree_key_value_types<__value_type<_Key, _Tp> > {
   }
 
   _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) {
-    return std::addressof(__n.__get_value());
+    return std::addressof(__node_value_type::__get_value(__n));
   }
 
   _LIBCPP_HIDE_FROM_ABI static pair<key_type&&, mapped_type&&> __move(__node_value_type& __v) { return __v.__move(); }
diff --git a/libcxx/include/ext/hash_map b/libcxx/include/ext/hash_map
index da2a34aa56dfb..d5f7f7e02d128 100644
--- a/libcxx/include/ext/hash_map
+++ b/libcxx/include/ext/hash_map
@@ -329,9 +329,9 @@ public:
 
   _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) {
     if (__second_constructed)
-      __alloc_traits::destroy(__na_, std::addressof(__p->__get_value().second));
+      __alloc_traits::destroy(__na_, std::addressof(value_type::__get_value(*__p).second));
     if (__first_constructed)
-      __alloc_traits::destroy(__na_, std::addressof(__p->__get_value().first));
+      __alloc_traits::destroy(__na_, std::addressof(value_type::__get_value(*__p).first));
     if (__p)
       __alloc_traits::deallocate(__na_, __p, 1);
   }
@@ -614,9 +614,9 @@ typename hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__node_holder
 hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__construct_node(const key_type& __k) {
   __node_allocator& __na = __table_.__node_alloc();
   __node_holder ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/135365


More information about the libcxx-commits mailing list