diff --git a/llvm/include/llvm/Support/Recycler.h b/llvm/include/llvm/Support/Recycler.h index bbd9ae321ae30..693c6559ff2fd 100644 --- a/llvm/include/llvm/Support/Recycler.h +++ b/llvm/include/llvm/Support/Recycler.h @@ -60,6 +60,10 @@ class Recycler { // clear() before deleting the Recycler. assert(!FreeList && "Non-empty recycler deleted!"); } + Recycler(const Recycler &) = delete; + Recycler(Recycler &&Other) + : FreeList(std::exchange(Other.FreeList, nullptr)) {} + Recycler() = default; /// clear - Release all the tracked allocations to the allocator. The /// recycler must be free of any tracked allocations before being diff --git a/llvm/unittests/Support/CMakeLists.txt b/llvm/unittests/Support/CMakeLists.txt index d64f89847aa8e..6de8165826442 100644 --- a/llvm/unittests/Support/CMakeLists.txt +++ b/llvm/unittests/Support/CMakeLists.txt @@ -69,6 +69,7 @@ add_llvm_unittest(SupportTests PerThreadBumpPtrAllocatorTest.cpp ProcessTest.cpp ProgramTest.cpp + RecyclerTest.cpp RegexTest.cpp ReverseIterationTest.cpp ReplaceFileTest.cpp diff --git a/llvm/unittests/Support/RecyclerTest.cpp b/llvm/unittests/Support/RecyclerTest.cpp new file mode 100644 index 0000000000000..a33506b47ebea --- /dev/null +++ b/llvm/unittests/Support/RecyclerTest.cpp @@ -0,0 +1,47 @@ +//===--- unittest/Support/RecyclerTest.cpp --------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Recycler.h" +#include "llvm/Support/AllocatorBase.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +struct Object8 { + char Data[8]; +}; + +class DecoratedMallocAllocator : public MallocAllocator { +public: + int DeallocCount = 0; + + template void Deallocate(T *Ptr) { + DeallocCount++; + MallocAllocator::Deallocate(Ptr); + } +}; + +TEST(RecyclerTest, MoveConstructor) { + DecoratedMallocAllocator Allocator; + Recycler R; + Object8 *A1 = R.Allocate(Allocator); + Object8 *A2 = R.Allocate(Allocator); + R.Deallocate(Allocator, A1); + R.Deallocate(Allocator, A2); + Recycler R2(std::move(R)); + Object8 *A3 = R2.Allocate(Allocator); + R2.Deallocate(Allocator, A3); + R.clear(Allocator); // Should not deallocate anything as it was moved from. + EXPECT_EQ(Allocator.DeallocCount, 0); + R2.clear(Allocator); + EXPECT_EQ(Allocator.DeallocCount, 2); +} + +} // end anonymous namespace