llvm.org GIT mirror llvm / 8dffa4a
Add a unit test for 'swap', and fix a pile of bugs in SmallDenseMap::swap. First, make it parse cleanly. Yay for uninstantiated methods. Second, make the inline-buckets case work correctly. This is way trickier than it should be due to the uninitialized values in empty and tombstone buckets. Finally fix a few typos that caused construction/destruction mismatches in the counting unittest. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@158641 91177308-0d34-0410-b5e6-96231b3b80d8 Chandler Carruth 8 years ago
2 changed file(s) with 70 addition(s) and 7 deletion(s). Raw diff Collapse all Expand all
715715 }
716716
717717 void swap(SmallDenseMap& RHS) {
718 std::swap(NumEntries, RHS.NumEntries);
718 unsigned TmpNumEntries = RHS.NumEntries;
719 RHS.NumEntries = NumEntries;
720 NumEntries = TmpNumEntries;
719721 std::swap(NumTombstones, RHS.NumTombstones);
722
723 const KeyT EmptyKey = this->getEmptyKey();
724 const KeyT TombstoneKey = this->getTombstoneKey();
720725 if (Small && RHS.Small) {
721 for (unsigned i = 0, e = InlineBuckets; i != e; ++i)
722 std::swap(getInlineBuckets()[i], RHS.getInlineBuckes()[i]);
726 // If we're swapping inline bucket arrays, we have to cope with some of
727 // the tricky bits of DenseMap's storage system: the buckets are not
728 // fully initialized. Thus we swap every key, but we may have
729 // a one-directional move of the value.
730 for (unsigned i = 0, e = InlineBuckets; i != e; ++i) {
731 BucketT *LHSB = &getInlineBuckets()[i],
732 *RHSB = &RHS.getInlineBuckets()[i];
733 bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->first, EmptyKey) &&
734 !KeyInfoT::isEqual(LHSB->first, TombstoneKey));
735 bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->first, EmptyKey) &&
736 !KeyInfoT::isEqual(RHSB->first, TombstoneKey));
737 if (hasLHSValue && hasRHSValue) {
738 // Swap together if we can...
739 std::swap(*LHSB, *RHSB);
740 continue;
741 }
742 // Swap separately and handle any assymetry.
743 std::swap(LHSB->first, RHSB->first);
744 if (hasLHSValue) {
745 new (&RHSB->second) ValueT(llvm_move(LHSB->second));
746 LHSB->second.~ValueT();
747 } else if (hasRHSValue) {
748 new (&LHSB->second) ValueT(llvm_move(RHSB->second));
749 RHSB->second.~ValueT();
750 }
751 }
723752 return;
724753 }
725754 if (!Small && !RHS.Small) {
736765 LargeSide.getLargeRep()->~LargeRep();
737766 LargeSide.Small = true;
738767 // This is similar to the standard move-from-old-buckets, but the bucket
739 // count hasn't actually rotate in this case. So we have to carefully
768 // count hasn't actually rotated in this case. So we have to carefully
740769 // move construct the keys and values into their new locations, but there
741770 // is no need to re-hash things.
742 const KeyT EmptyKey = this->getEmptyKey();
743 const KeyT TombstoneKey = this->getTombstoneKey();
744771 for (unsigned i = 0, e = InlineBuckets; i != e; ++i) {
745772 BucketT *NewB = &LargeSide.getInlineBuckets()[i],
746773 *OldB = &SmallSide.getInlineBuckets()[i];
747774 new (&NewB->first) KeyT(llvm_move(OldB->first));
748 NewB->first.~KeyT();
775 OldB->first.~KeyT();
749776 if (!KeyInfoT::isEqual(NewB->first, EmptyKey) &&
750777 !KeyInfoT::isEqual(NewB->first, TombstoneKey)) {
751778 new (&NewB->second) ValueT(llvm_move(OldB->second));
217217 EXPECT_EQ(this->getValue(), copyMap[this->getKey()]);
218218 }
219219
220 // Test swap method
221 TYPED_TEST(DenseMapTest, SwapTest) {
222 this->Map[this->getKey()] = this->getValue();
223 TypeParam otherMap;
224
225 this->Map.swap(otherMap);
226 EXPECT_EQ(0u, this->Map.size());
227 EXPECT_TRUE(this->Map.empty());
228 EXPECT_EQ(1u, otherMap.size());
229 EXPECT_EQ(this->getValue(), otherMap[this->getKey()]);
230
231 this->Map.swap(otherMap);
232 EXPECT_EQ(0u, otherMap.size());
233 EXPECT_TRUE(otherMap.empty());
234 EXPECT_EQ(1u, this->Map.size());
235 EXPECT_EQ(this->getValue(), this->Map[this->getKey()]);
236
237 // Make this more interesting by inserting 100 numbers into the map.
238 for (int i = 0; i < 100; ++i)
239 this->Map[this->getKey(i)] = this->getValue(i);
240
241 this->Map.swap(otherMap);
242 EXPECT_EQ(0u, this->Map.size());
243 EXPECT_TRUE(this->Map.empty());
244 EXPECT_EQ(100u, otherMap.size());
245 for (int i = 0; i < 100; ++i)
246 EXPECT_EQ(this->getValue(i), otherMap[this->getKey(i)]);
247
248 this->Map.swap(otherMap);
249 EXPECT_EQ(0u, otherMap.size());
250 EXPECT_TRUE(otherMap.empty());
251 EXPECT_EQ(100u, this->Map.size());
252 for (int i = 0; i < 100; ++i)
253 EXPECT_EQ(this->getValue(i), this->Map[this->getKey(i)]);
254 }
255
220256 // A more complex iteration test
221257 TYPED_TEST(DenseMapTest, IterationTest) {
222258 bool visited[100];