diff --git a/llvm/include/llvm/ADT/SparseSet.h b/llvm/include/llvm/ADT/SparseSet.h index c7793117ff540..d9ded9875d377 100644 --- a/llvm/include/llvm/ADT/SparseSet.h +++ b/llvm/include/llvm/ADT/SparseSet.h @@ -129,7 +129,12 @@ class SparseSet { using DenseT = SmallVector; using size_type = unsigned; DenseT Dense; - SparseT *Sparse = nullptr; + + struct Deleter { + void operator()(SparseT *S) { free(S); } + }; + std::unique_ptr Sparse; + unsigned Universe = 0; KeyFunctorT KeyIndexOf; SparseSetValFunctor ValIndexOf; @@ -144,7 +149,7 @@ class SparseSet { SparseSet() = default; SparseSet(const SparseSet &) = delete; SparseSet &operator=(const SparseSet &) = delete; - ~SparseSet() { free(Sparse); } + SparseSet(SparseSet &&) = default; /// setUniverse - Set the universe size which determines the largest key the /// set can hold. The universe must be sized before any elements can be @@ -159,11 +164,10 @@ class SparseSet { // Hysteresis prevents needless reallocations. if (U >= Universe/4 && U <= Universe) return; - free(Sparse); // The Sparse array doesn't actually need to be initialized, so malloc // would be enough here, but that will cause tools like valgrind to // complain about branching on uninitialized data. - Sparse = static_cast(safe_calloc(U, sizeof(SparseT))); + Sparse.reset(static_cast(safe_calloc(U, sizeof(SparseT)))); Universe = U; } diff --git a/llvm/unittests/ADT/SparseSetTest.cpp b/llvm/unittests/ADT/SparseSetTest.cpp index 3eea4bde8c07c..4fbf1caa247b7 100644 --- a/llvm/unittests/ADT/SparseSetTest.cpp +++ b/llvm/unittests/ADT/SparseSetTest.cpp @@ -204,4 +204,16 @@ TEST(SparseSetTest, PopBack) { for (unsigned i = 0; i < UpperBound; ++i) ASSERT_TRUE(Set.insert(i).second); } + +TEST(SparseSetTest, MoveConstructor) { + USet Set; + Set.setUniverse(2); + Set.insert(1); + EXPECT_FALSE(Set.empty()); + // Move and check original is empty. + USet OtherSet(std::move(Set)); + EXPECT_TRUE(Set.empty()); + EXPECT_TRUE(OtherSet.contains(1)); +} + } // namespace