[libcxx-commits] [libcxx] [libc++] Add another const_cast to support hash_map copy assignment (PR #188660)

Peter Collingbourne via libcxx-commits libcxx-commits at lists.llvm.org
Thu Mar 26 09:48:21 PDT 2026


https://github.com/pcc updated https://github.com/llvm/llvm-project/pull/188660

>From bf1287b42e30f2b1de7fd199864fd4974dc7f6e4 Mon Sep 17 00:00:00 2001
From: Peter Collingbourne <peter at pcc.me.uk>
Date: Wed, 25 Mar 2026 18:36:41 -0700
Subject: [PATCH 1/3] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?=
 =?UTF-8?q?itial=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1
---
 libcxx/include/__hash_table                       | 12 ++++++++----
 libcxx/test/extensions/gnu/hash_map/copy.pass.cpp |  4 ++++
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index ef487fb06dd5e..92605fcee1419 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -19,6 +19,7 @@
 #include <__cstddef/ptrdiff_t.h>
 #include <__cstddef/size_t.h>
 #include <__functional/hash.h>
+#include <__fwd/pair.h>
 #include <__iterator/iterator_traits.h>
 #include <__math/rounding_functions.h>
 #include <__memory/addressof.h>
@@ -1042,15 +1043,18 @@ private:
 
   _LIBCPP_HIDE_FROM_ABI __next_pointer __detach() _NOEXCEPT;
 
-  template <class _From, class _ValueT = _Tp, __enable_if_t<__is_hash_value_type<_ValueT>::value, int> = 0>
+  template <class _From, class _ValueT = _Tp, __enable_if_t<__is_hash_value_type<_ValueT>::value || __is_pair_v<_ValueT>, int> = 0>
   _LIBCPP_HIDE_FROM_ABI void __assign_value(__get_hash_node_value_type_t<_Tp>& __lhs, _From&& __rhs) {
     // This is technically UB, since the object was constructed as `const`.
     // Clang doesn't optimize on this currently though.
-    const_cast<key_type&>(__lhs.first) = const_cast<__copy_cvref_t<_From, key_type>&&>(__rhs.first);
-    __lhs.second                       = std::forward<_From>(__rhs).second;
+    //
+    // The enable_if check for __is_pair_v is only needed to support
+    // __gnu_cxx::hash_map and may be removed if hash_map is removed.
+    const_cast<__remove_const_t<decltype(__lhs.first)>&>(__lhs.first) = std::forward<_From>(__rhs).first;
+    __lhs.second                                                      = std::forward<_From>(__rhs).second;
   }
 
-  template <class _From, class _ValueT = _Tp, __enable_if_t<!__is_hash_value_type<_ValueT>::value, int> = 0>
+  template <class _From, class _ValueT = _Tp, __enable_if_t<!__is_hash_value_type<_ValueT>::value && !__is_pair_v<_ValueT>, int> = 0>
   _LIBCPP_HIDE_FROM_ABI void __assign_value(_Tp& __lhs, _From&& __rhs) {
     __lhs = std::forward<_From>(__rhs);
   }
diff --git a/libcxx/test/extensions/gnu/hash_map/copy.pass.cpp b/libcxx/test/extensions/gnu/hash_map/copy.pass.cpp
index 65b8debda0676..fecec671acdb5 100644
--- a/libcxx/test/extensions/gnu/hash_map/copy.pass.cpp
+++ b/libcxx/test/extensions/gnu/hash_map/copy.pass.cpp
@@ -23,5 +23,9 @@ int main(int, char**) {
 
   assert(map2.size() == 2);
 
+  map.insert(std::make_pair(3, 1));
+  map2 = map;
+  assert(map2.size() == 3);
+
   return 0;
 }

>From 048238b4ebcb4566485740954993041469ec3f4c Mon Sep 17 00:00:00 2001
From: Peter Collingbourne <peter at pcc.me.uk>
Date: Wed, 25 Mar 2026 18:45:27 -0700
Subject: [PATCH 2/3] Format

Created using spr 1.3.6-beta.1
---
 libcxx/include/__hash_table | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index 92605fcee1419..49e2fccfd055a 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -1043,7 +1043,9 @@ private:
 
   _LIBCPP_HIDE_FROM_ABI __next_pointer __detach() _NOEXCEPT;
 
-  template <class _From, class _ValueT = _Tp, __enable_if_t<__is_hash_value_type<_ValueT>::value || __is_pair_v<_ValueT>, int> = 0>
+  template <class _From,
+            class _ValueT                                                                    = _Tp,
+            __enable_if_t<__is_hash_value_type<_ValueT>::value || __is_pair_v<_ValueT>, int> = 0>
   _LIBCPP_HIDE_FROM_ABI void __assign_value(__get_hash_node_value_type_t<_Tp>& __lhs, _From&& __rhs) {
     // This is technically UB, since the object was constructed as `const`.
     // Clang doesn't optimize on this currently though.
@@ -1054,7 +1056,9 @@ private:
     __lhs.second                                                      = std::forward<_From>(__rhs).second;
   }
 
-  template <class _From, class _ValueT = _Tp, __enable_if_t<!__is_hash_value_type<_ValueT>::value && !__is_pair_v<_ValueT>, int> = 0>
+  template <class _From,
+            class _ValueT                                                                      = _Tp,
+            __enable_if_t<!__is_hash_value_type<_ValueT>::value && !__is_pair_v<_ValueT>, int> = 0>
   _LIBCPP_HIDE_FROM_ABI void __assign_value(_Tp& __lhs, _From&& __rhs) {
     __lhs = std::forward<_From>(__rhs);
   }

>From e2e2e71a5914e8699995bd3d8e03f839829f0f17 Mon Sep 17 00:00:00 2001
From: Peter Collingbourne <peter at pcc.me.uk>
Date: Thu, 26 Mar 2026 09:47:57 -0700
Subject: [PATCH 3/3] Fix gcc bot

Created using spr 1.3.6-beta.1
---
 libcxx/test/extensions/gnu/hash_map/copy.pass.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/extensions/gnu/hash_map/copy.pass.cpp b/libcxx/test/extensions/gnu/hash_map/copy.pass.cpp
index fecec671acdb5..ca489e8c1c623 100644
--- a/libcxx/test/extensions/gnu/hash_map/copy.pass.cpp
+++ b/libcxx/test/extensions/gnu/hash_map/copy.pass.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-// ADDITIONAL_COMPILE_FLAGS: -Wno-deprecated
+// ADDITIONAL_COMPILE_FLAGS: -Wno-deprecated -Wno-deprecated-copy
 
 // hash_map::hash_map(const hash_map&)
 



More information about the libcxx-commits mailing list