diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/include/llvm/Support/Allocator.h | 35 | ||||
| -rw-r--r-- | llvm/unittests/Support/AllocatorTest.cpp | 15 | 
2 files changed, 47 insertions, 3 deletions
diff --git a/llvm/include/llvm/Support/Allocator.h b/llvm/include/llvm/Support/Allocator.h index a2923fdd691..cc3675c9380 100644 --- a/llvm/include/llvm/Support/Allocator.h +++ b/llvm/include/llvm/Support/Allocator.h @@ -138,9 +138,6 @@ template <typename AllocatorT = MallocAllocator, size_t SlabSize = 4096,  class BumpPtrAllocatorImpl      : public AllocatorBase<            BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold>> { -  BumpPtrAllocatorImpl(const BumpPtrAllocatorImpl &) LLVM_DELETED_FUNCTION; -  void operator=(const BumpPtrAllocatorImpl &) LLVM_DELETED_FUNCTION; -  public:    static_assert(SizeThreshold <= SlabSize,                  "The SizeThreshold must be at most the SlabSize to ensure " @@ -153,11 +150,43 @@ public:    BumpPtrAllocatorImpl(T &&Allocator)        : CurPtr(nullptr), End(nullptr), BytesAllocated(0),          Allocator(std::forward<T &&>(Allocator)) {} + +  // Manually implement a move constructor as we must clear the old allocators +  // slabs as a matter of correctness. +  BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old) +      : CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)), +        CustomSizedSlabs(std::move(Old.CustomSizedSlabs)), +        BytesAllocated(Old.BytesAllocated), +        Allocator(std::move(Old.Allocator)) { +    Old.CurPtr = Old.End = nullptr; +    Old.BytesAllocated = 0; +    Old.Slabs.clear(); +    Old.CustomSizedSlabs.clear(); +  } +    ~BumpPtrAllocatorImpl() {      DeallocateSlabs(Slabs.begin(), Slabs.end());      DeallocateCustomSizedSlabs();    } +  BumpPtrAllocatorImpl &operator=(BumpPtrAllocatorImpl &&RHS) { +    DeallocateSlabs(Slabs.begin(), Slabs.end()); +    DeallocateCustomSizedSlabs(); + +    CurPtr = RHS.CurPtr; +    End = RHS.End; +    BytesAllocated = RHS.BytesAllocated; +    Slabs = std::move(RHS.Slabs); +    CustomSizedSlabs = std::move(RHS.CustomSizedSlabs); +    Allocator = std::move(RHS.Allocator); + +    RHS.CurPtr = RHS.End = nullptr; +    RHS.BytesAllocated = 0; +    RHS.Slabs.clear(); +    RHS.CustomSizedSlabs.clear(); +    return *this; +  } +    /// \brief Deallocate all but the current slab and reset the current pointer    /// to the beginning of it, freeing all memory allocated so far.    void Reset() { diff --git a/llvm/unittests/Support/AllocatorTest.cpp b/llvm/unittests/Support/AllocatorTest.cpp index 8c2ddadf7fa..0fc84c7613f 100644 --- a/llvm/unittests/Support/AllocatorTest.cpp +++ b/llvm/unittests/Support/AllocatorTest.cpp @@ -29,6 +29,21 @@ TEST(AllocatorTest, Basics) {    EXPECT_EQ(2, b[9]);    EXPECT_EQ(3, *c);    EXPECT_EQ(1U, Alloc.GetNumSlabs()); + +  BumpPtrAllocator Alloc2 = std::move(Alloc); +  EXPECT_EQ(0U, Alloc.GetNumSlabs()); +  EXPECT_EQ(1U, Alloc2.GetNumSlabs()); + +  // Make sure the old pointers still work. These are especially interesting +  // under ASan or Valgrind. +  EXPECT_EQ(1, *a); +  EXPECT_EQ(2, b[0]); +  EXPECT_EQ(2, b[9]); +  EXPECT_EQ(3, *c); + +  Alloc = std::move(Alloc2); +  EXPECT_EQ(0U, Alloc2.GetNumSlabs()); +  EXPECT_EQ(1U, Alloc.GetNumSlabs());  }  // Allocate enough bytes to create three slabs.  | 

