diff --git a/libstdc++-v3/include/bits/functional_hash.h b/libstdc++-v3/include/bits/functional_hash.h index d94843f..a217f8a 100644 --- a/libstdc++-v3/include/bits/functional_hash.h +++ b/libstdc++-v3/include/bits/functional_hash.h @@ -36,6 +36,29 @@ namespace std _GLIBCXX_VISIBILITY(default) { +namespace __detail +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Compute highest power of 2 lower or equal to __n. + template + struct _Lowest_power_of_two + { + static const size_t __val + = _Lowest_power_of_two< (__n >> 1) >::__val + 1; + }; + + template<> + struct _Lowest_power_of_two<1> + { static const size_t __val = 0; }; + + template<> + struct _Lowest_power_of_two<0> + { static const size_t __val = 0; }; + +_GLIBCXX_END_NAMESPACE_VERSION +} + _GLIBCXX_BEGIN_NAMESPACE_VERSION /** @defgroup hashes Hashes @@ -63,7 +86,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { size_t operator()(_Tp* __p) const noexcept - { return reinterpret_cast(__p); } + { + return reinterpret_cast(__p) + >> __detail::_Lowest_power_of_two::__val; + } }; // Explicit specializations for integer types. diff --git a/libstdc++-v3/testsuite/20_util/hash/quality.cc b/libstdc++-v3/testsuite/20_util/hash/quality.cc index af417ed..d9c72c7 100644 --- a/libstdc++-v3/testsuite/20_util/hash/quality.cc +++ b/libstdc++-v3/testsuite/20_util/hash/quality.cc @@ -164,9 +164,20 @@ quality_test() } } +void +pointer_quality_test() +{ + bool test __attribute__((unused)) = true; + + double d1, d2; + std::hash dh; + VERIFY( dh(&d1) % sizeof(double) != dh(&d2) % sizeof(double) ); +} + int main() { quality_test(); + pointer_quality_test(); return 0; }