diff options
author | Chandler Carruth <chandlerc@gmail.com> | 2012-03-02 09:26:36 +0000 |
---|---|---|
committer | Chandler Carruth <chandlerc@gmail.com> | 2012-03-02 09:26:36 +0000 |
commit | 4d628e200f7133e353c38806b57a229ef6ad2ab4 (patch) | |
tree | 9cb8db0b305fbf1266adc7327b1a35ec1278eec3 /include/llvm/ADT/Hashing.h | |
parent | c7384cfc7addb5d2818ac0bb4492778f28183c49 (diff) | |
download | external_llvm-4d628e200f7133e353c38806b57a229ef6ad2ab4.zip external_llvm-4d628e200f7133e353c38806b57a229ef6ad2ab4.tar.gz external_llvm-4d628e200f7133e353c38806b57a229ef6ad2ab4.tar.bz2 |
We really want to hash pairs of directly-hashable data as directly
hashable data. This matters when we have pair<T*, U*> as a key, which is
quite common in DenseMap, etc. To that end, we need to detect when this
is safe. The requirements on a generic std::pair<T, U> are:
1) Both T and U must satisfy the existing is_hashable_data trait. Note
that this includes the requirement that T and U have no internal
padding bits or other bits not contributing directly to equality.
2) The alignment constraints of std::pair<T, U> do not require padding
between consecutive objects.
3) The alignment constraints of U and the size of T do not conspire to
require padding between the first and second elements.
Grow two somewhat magical traits to detect this by forming a pod
structure and inspecting offset artifacts on it. Hopefully this won't
cause any compilers to panic.
Added and adjusted tests now that pairs, even nested pairs, are treated
as just sequences of data.
Thanks to Jeffrey Yasskin for helping me sort through this and reviewing
the somewhat subtle traits.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151883 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm/ADT/Hashing.h')
-rw-r--r-- | include/llvm/ADT/Hashing.h | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h index 06dd76a..1b0e669 100644 --- a/include/llvm/ADT/Hashing.h +++ b/include/llvm/ADT/Hashing.h @@ -350,6 +350,16 @@ template <typename T> struct is_hashable_data : integral_constant<bool, ((is_integral<T>::value || is_pointer<T>::value) && 64 % sizeof(T) == 0)> {}; +// Special case std::pair to detect when both types are viable and when there +// is no alignment-derived padding in the pair. This is a bit of a lie because +// std::pair isn't truly POD, but it's close enough in all reasonable +// implementations for our use case of hashing the underlying data. +template <typename T, typename U> struct is_hashable_data<std::pair<T, U> > + : integral_constant<bool, (is_hashable_data<T>::value && + is_hashable_data<U>::value && + !is_alignment_padded<std::pair<T, U> >::value && + !is_pod_pair_padded<T, U>::value)> {}; + /// \brief Helper to get the hashable data representation for a type. /// This variant is enabled when the type itself can be used. template <typename T> |