diff --git a/libcxx/include/functional b/libcxx/include/functional index 243f3984d1a9..ee0424d07075 100644 --- a/libcxx/include/functional +++ b/libcxx/include/functional @@ -1916,123 +1916,91 @@ struct _LIBCPP_VISIBLE hash template <> struct _LIBCPP_VISIBLE hash - : public unary_function + : public __scalar_hash { - _LIBCPP_INLINE_VISIBILITY - size_t operator()(long long __v) const _NOEXCEPT - { - if (sizeof(long long) == sizeof(size_t)) - return __v; - union - { - long long __l; - struct - { - size_t __a; - size_t __b; - } __s; - } __u; - __u.__l = __v; - return __u.__s.__a ^ __u.__s.__b; - } }; template <> struct _LIBCPP_VISIBLE hash - : public unary_function + : public __scalar_hash { - _LIBCPP_INLINE_VISIBILITY - size_t operator()(unsigned long long __v) const _NOEXCEPT - { - if (sizeof(unsigned long long) == sizeof(size_t)) - return __v; - union - { - unsigned long long __l; - struct - { - size_t __a; - size_t __b; - } __s; - } __u; - __u.__l = __v; - return __u.__s.__a ^ __u.__s.__b; - } }; template <> struct _LIBCPP_VISIBLE hash - : public unary_function + : public __scalar_hash { _LIBCPP_INLINE_VISIBILITY size_t operator()(float __v) const _NOEXCEPT { + // -0.0 and 0.0 should return same hash if (__v == 0) return 0; - union - { - size_t __d; - float __f; - } __u; - __u.__f = __v; - return __u.__d; + return __scalar_hash::operator()(__v); } }; template <> struct _LIBCPP_VISIBLE hash - : public unary_function + : public __scalar_hash { _LIBCPP_INLINE_VISIBILITY size_t operator()(double __v) const _NOEXCEPT { - if (__v == 0) - return 0; - if (sizeof(double) == sizeof(size_t)) - { - union - { - double __f; - size_t __d; - } __u; - __u.__f = __v; - return __u.__d; - } - union - { - float __f; - size_t __d; - } __u; - __u.__f = __v; - return __u.__d; + // -0.0 and 0.0 should return same hash + if (__v == 0) + return 0; + return __scalar_hash::operator()(__v); } }; template <> struct _LIBCPP_VISIBLE hash - : public unary_function + : public __scalar_hash { _LIBCPP_INLINE_VISIBILITY size_t operator()(long double __v) const _NOEXCEPT { + // -0.0 and 0.0 should return same hash if (__v == 0) return 0; - if (sizeof(double) == sizeof(size_t)) +#if defined(__i386__) + // Zero out padding bits + union { - union + long double __t; + struct { - double __f; + size_t __a; + size_t __b; + size_t __c; size_t __d; - } __u; - __u.__f = __v; - return __u.__d; - } - union { - float __f; - size_t __d; + }; } __u; - __u.__f = __v; - return __u.__d; + __u.__a = 0; + __u.__b = 0; + __u.__c = 0; + __u.__d = 0; + __u.__t = __v; + return __u.__a ^ __u.__b ^ __u.__c ^ __u.__d; +#elif defined(__x86_64__) + // Zero out padding bits + union + { + long double __t; + struct + { + size_t __a; + size_t __b; + }; + } __u; + __u.__a = 0; + __u.__b = 0; + __u.__t = __v; + return __u.__a ^ __u.__b; +#else + return __scalar_hash::operator()(__v); +#endif } }; diff --git a/libcxx/include/memory b/libcxx/include/memory index e8abdbeee0a2..bab71b4daf64 100644 --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -2719,18 +2719,116 @@ operator>=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {re template struct hash; -template -struct _LIBCPP_VISIBLE hash<_Tp*> - : public unary_function<_Tp*, size_t> +template +struct __scalar_hash; + +template +struct __scalar_hash<_Tp, 0> + : public unary_function<_Tp, size_t> { _LIBCPP_INLINE_VISIBILITY - size_t operator()(_Tp* __v) const _NOEXCEPT + size_t operator()(_Tp __v) const _NOEXCEPT { - const size_t* const __p = reinterpret_cast(&__v); - return *__p; + union + { + _Tp __t; + size_t __a; + } __u; + __u.__a = 0; + __u.__t = __v; + return __u.__a; } }; +template +struct __scalar_hash<_Tp, 1> + : public unary_function<_Tp, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp __v) const _NOEXCEPT + { + union + { + _Tp __t; + size_t __a; + } __u; + __u.__t = __v; + return __u.__a; + } +}; + +template +struct __scalar_hash<_Tp, 2> + : public unary_function<_Tp, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp __v) const _NOEXCEPT + { + union + { + _Tp __t; + struct + { + size_t __a; + size_t __b; + }; + } __u; + __u.__t = __v; + return __u.__a ^ __u.__b; + } +}; + +template +struct __scalar_hash<_Tp, 3> + : public unary_function<_Tp, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp __v) const _NOEXCEPT + { + union + { + _Tp __t; + struct + { + size_t __a; + size_t __b; + size_t __c; + }; + } __u; + __u.__t = __v; + return __u.__a ^ __u.__b ^ __u.__c; + } +}; + +template +struct __scalar_hash<_Tp, 4> + : public unary_function<_Tp, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp __v) const _NOEXCEPT + { + union + { + _Tp __t; + struct + { + size_t __a; + size_t __b; + size_t __c; + size_t __d; + }; + } __u; + __u.__t = __v; + return __u.__a ^ __u.__b ^ __u.__c ^ __u.__d; + } +}; + +template +struct _LIBCPP_VISIBLE hash<_Tp*> + : public __scalar_hash<_Tp*> +{ +}; + template struct _LIBCPP_VISIBLE hash > {