llvm.org GIT mirror llvm / 1c14489
Simplify the pair optimization. Rather than using complex type traits, just ensure that the number of bytes in the pair is the sum of the bytes in each side of the pair. As long as thats true, there are no extra bytes that might be padding. Also add a few tests that previously would have slipped through the checking. The more accurate checking mechanism catches these and ensures they are handled conservatively correctly. Thanks to Duncan for prodding me to do this right and more simply. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151891 91177308-0d34-0410-b5e6-96231b3b80d8 Chandler Carruth 8 years ago
3 changed file(s) with 22 addition(s) and 20 deletion(s). Raw diff Collapse all Expand all
356356 template struct is_hashable_data >
357357 : integral_constant::value &&
358358 is_hashable_data::value &&
359 !is_alignment_padded >::value &&
360 !is_pod_pair_padded::value)> {};
359 (sizeof(T) + sizeof(U)) ==
360 sizeof(std::pair))> {};
361361
362362 /// \brief Helper to get the hashable data representation for a type.
363363 /// This variant is enabled when the type itself can be used.
125125 template struct is_pointer : false_type {};
126126 template struct is_pointer : true_type {};
127127
128 /// \brief Metafunction to compute whether a type requires alignment padding.
129 /// When true, an object of this type will have padding bytes inside its
130 /// 'sizeof' bytes.
131 template class is_alignment_padded {
132 struct pod_size_tester { T t; char c; };
133 public:
134 enum { value = offsetof(pod_size_tester, c) != sizeof(T) };
135 };
136
137 /// \brief Metafunction to determine whether an adjacent pair of two types will
138 /// require padding between them due to alignment.
139 template class is_pod_pair_padded {
140 struct pod_pair { T t; U u; };
141 struct pod_char_pair { T t; char c; };
142 public:
143 enum { value = offsetof(pod_pair, u) != offsetof(pod_char_pair, c) };
144 };
145
146128
147129 // enable_if_c - Enable/disable a template based on a metafunction
148130 template
4040 using namespace llvm;
4141
4242 namespace {
43
44 struct NonPOD {
45 uint64_t x, y;
46 NonPOD(uint64_t x, uint64_t y) : x(x), y(y) {}
47 ~NonPOD() {}
48 friend hash_code hash_value(const NonPOD &obj) {
49 return hash_combine(obj.x, obj.y);
50 }
51 };
52
4353
4454 TEST(HashingTest, HashValueBasicTest) {
4555 int x = 42, y = 43, c = 'x';
7282 hash_value(std::make_pair(42, std::make_pair(43, 44))));
7383 EXPECT_EQ(hash_value(std::make_pair(42, std::make_pair(43, 44))),
7484 hash_value(std::make_pair(std::make_pair(42, 43), 44)));
85
86 // Ensure that pairs which have padding bytes *inside* them don't get treated
87 // this way.
88 EXPECT_EQ(hash_combine('0', hash_combine(1ull, '2')),
89 hash_value(std::make_pair('0', std::make_pair(1ull, '2'))));
90
91 // Ensure that non-POD pairs don't explode the traits used.
92 NonPOD obj1(1, 2), obj2(3, 4), obj3(5, 6);
93 EXPECT_EQ(hash_combine(obj1, hash_combine(obj2, obj3)),
94 hash_value(std::make_pair(obj1, std::make_pair(obj2, obj3))));
7595 }
7696
7797 template T *begin(T (&arr)[N]) { return arr; }