summaryrefslogtreecommitdiff
path: root/include/__hash_table
diff options
context:
space:
mode:
authorErik Pilkington <erik.pilkington@gmail.com>2018-06-04 20:38:23 +0000
committerErik Pilkington <erik.pilkington@gmail.com>2018-06-04 20:38:23 +0000
commit55513c8efb03a53bc9e87d1eba727f8a15c1ed4d (patch)
treeffb47af052710469fb5b930e8e5327022fbe38bd /include/__hash_table
parent8d476cd6793c73cc6ac15a93a3d003733089eb2a (diff)
downloadlibcxx-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_table16
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