From 5b8c175804821e4f6e5141a7cf2ea8a0f9730834 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Thu, 26 Mar 2026 12:12:01 -0700 Subject: [PATCH] [libc++] Add another const_cast to support hash_map copy assignment There was one more const_cast needed after #183223 without which copy assignment of hash_map was broken. Add it, together with a copy assignment test. Reviewers: ldionne Pull Request: https://github.com/llvm/llvm-project/pull/188660 --- libcxx/include/__hash_table | 16 ++++++++++++---- .../test/extensions/gnu/hash_map/copy.pass.cpp | 6 +++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index ef487fb06dd5..49e2fccfd055 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,22 @@ private: _LIBCPP_HIDE_FROM_ABI __next_pointer __detach() _NOEXCEPT; - template ::value, int> = 0> + template ::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(__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&>(__lhs.first) = std::forward<_From>(__rhs).first; + __lhs.second = std::forward<_From>(__rhs).second; } - template ::value, int> = 0> + template ::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 65b8debda067..ca489e8c1c62 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&) @@ -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; }