diff options
author | Erik Pilkington <erik.pilkington@gmail.com> | 2018-06-04 20:38:23 +0000 |
---|---|---|
committer | Erik Pilkington <erik.pilkington@gmail.com> | 2018-06-04 20:38:23 +0000 |
commit | 55513c8efb03a53bc9e87d1eba727f8a15c1ed4d (patch) | |
tree | ffb47af052710469fb5b930e8e5327022fbe38bd /include/__hash_table | |
parent | 8d476cd6793c73cc6ac15a93a3d003733089eb2a (diff) | |
download | libcxx-55513c8efb03a53bc9e87d1eba727f8a15c1ed4d.tar.gz |
Fix a strict aliasing violation in map and unordered_map.
These containers type-punned between pair<K, V> and pair<const K, V> as an
optimization. This commit instead provides access to the pair via a pair of
references that assign through to the underlying object. It's still undefined to
mutate a const object, but clang doesn't optimize on this for data members, so
this should be safe.
Differential revision: https://reviews.llvm.org/D47607
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@333948 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/__hash_table')
-rw-r--r-- | include/__hash_table | 16 |
1 files changed, 5 insertions, 11 deletions
diff --git a/include/__hash_table b/include/__hash_table index 3f430af12..44ba268a0 100644 --- a/include/__hash_table +++ b/include/__hash_table @@ -32,13 +32,8 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#ifndef _LIBCPP_CXX03_LANG -template <class _Key, class _Tp> -union __hash_value_type; -#else template <class _Key, class _Tp> struct __hash_value_type; -#endif template <class _Key, class _Cp, class _Hash, bool = is_empty<_Hash>::value && !__libcpp_is_final<_Hash>::value> @@ -172,7 +167,7 @@ struct __hash_key_value_types { } #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY - static __container_value_type&& __move(__node_value_type& __v) { + static __container_value_type&& __move(__node_value_type& __v) { return _VSTD::move(__v); } #endif @@ -184,7 +179,6 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > { typedef _Tp mapped_type; typedef __hash_value_type<_Key, _Tp> __node_value_type; typedef pair<const _Key, _Tp> __container_value_type; - typedef pair<_Key, _Tp> __nc_value_type; typedef __container_value_type __map_value_type; static const bool __is_map = true; @@ -198,7 +192,7 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > { static typename enable_if<__is_same_uncvref<_Up, __node_value_type>::value, __container_value_type const&>::type __get_value(_Up& __t) { - return __t.__cc; + return __t.__get_value(); } template <class _Up> @@ -211,12 +205,12 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > { _LIBCPP_INLINE_VISIBILITY static __container_value_type* __get_ptr(__node_value_type& __n) { - return _VSTD::addressof(__n.__cc); + return _VSTD::addressof(__n.__get_value()); } #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY - static __nc_value_type&& __move(__node_value_type& __v) { - return _VSTD::move(__v.__nc); + static pair<key_type&&, mapped_type&&> __move(__node_value_type& __v) { + return __v.__move(); } #endif |