aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/ADT/Hashing.h10
-rw-r--r--include/llvm/Support/type_traits.h18
-rw-r--r--unittests/ADT/HashingTest.cpp12
3 files changed, 35 insertions, 5 deletions
diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h
index 06dd76a2ed..1b0e66947b 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>
diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h
index 03f85e9997..f488a29c7a 100644
--- a/include/llvm/Support/type_traits.h
+++ b/include/llvm/Support/type_traits.h
@@ -125,6 +125,24 @@ struct is_integral : is_integral_impl<T> {};
template <typename T> struct is_pointer : false_type {};
template <typename T> struct is_pointer<T*> : true_type {};
+/// \brief Metafunction to compute whether a type requires alignment padding.
+/// When true, an object of this type will have padding bytes inside its
+/// 'sizeof' bytes.
+template <typename T> class is_alignment_padded {
+ struct pod_size_tester { T t; char c; };
+public:
+ enum { value = offsetof(pod_size_tester, c) != sizeof(T) };
+};
+
+/// \brief Metafunction to determine whether an adjacent pair of two types will
+/// require padding between them due to alignment.
+template <typename T, typename U> class is_pod_pair_padded {
+ struct pod_pair { T t; U u; };
+ struct pod_char_pair { T t; char c; };
+public:
+ enum { value = offsetof(pod_pair, u) != offsetof(pod_char_pair, c) };
+};
+
// enable_if_c - Enable/disable a template based on a metafunction
template<bool Cond, typename T = void>
diff --git a/unittests/ADT/HashingTest.cpp b/unittests/ADT/HashingTest.cpp
index a9458bb5a5..19a036cdf5 100644
--- a/unittests/ADT/HashingTest.cpp
+++ b/unittests/ADT/HashingTest.cpp
@@ -66,11 +66,13 @@ TEST(HashingTest, HashValueBasicTest) {
EXPECT_NE(hash_combine(42, 43), hash_value(std::make_pair(42ull, 43ull)));
EXPECT_NE(hash_combine(42, 43), hash_value(std::make_pair(42, 43ull)));
EXPECT_NE(hash_combine(42, 43), hash_value(std::make_pair(42ull, 43)));
- EXPECT_EQ(hash_combine(42, hash_combine(43, hash_combine(44, 45))),
- hash_value(
- std::make_pair(42, std::make_pair(43, std::make_pair(44, 45)))));
- EXPECT_EQ(hash_combine(42, 43), hash_value(std::make_pair(42, 43)));
- EXPECT_EQ(hash_combine(42, 43), hash_value(std::make_pair(42, 43)));
+
+ // Note that pairs are implicitly flattened to a direct sequence of data and
+ // hashed efficiently as a consequence.
+ EXPECT_EQ(hash_combine(42, 43, 44),
+ hash_value(std::make_pair(42, std::make_pair(43, 44))));
+ EXPECT_EQ(hash_value(std::make_pair(42, std::make_pair(43, 44))),
+ hash_value(std::make_pair(std::make_pair(42, 43), 44)));
}
template <typename T, size_t N> T *begin(T (&arr)[N]) { return arr; }