Index: llvm/include/llvm/ADT/IntervalMap.h =================================================================== --- llvm/include/llvm/ADT/IntervalMap.h +++ llvm/include/llvm/ADT/IntervalMap.h @@ -969,19 +969,19 @@ private: // The root data is either a RootLeaf or a RootBranchData instance. - AlignedCharArrayUnion data; + AlignedCharArrayUnion data = {}; // Tree height. // 0: Leaves in root. // 1: Root points to leaf. // 2: root->branch->leaf ... - unsigned height; + unsigned height = 0; // Number of entries in the root node. - unsigned rootSize; + unsigned rootSize = 0; // Allocator used for creating external nodes. - Allocator &allocator; + Allocator *allocator = nullptr; /// Represent data as a node type without breaking aliasing rules. template T &dataAs() const { return *bit_cast(&data); } @@ -1010,12 +1010,12 @@ KeyT &rootBranchStart() { return rootBranchData().start; } template NodeT *newNode() { - return new(allocator.template Allocate()) NodeT(); + return new (allocator->template Allocate()) NodeT(); } template void deleteNode(NodeT *P) { P->~NodeT(); - allocator.Deallocate(P); + allocator->Deallocate(P); } IdxPair branchRoot(unsigned Position); @@ -1041,12 +1041,30 @@ void deleteNode(IntervalMapImpl::NodeRef Node, unsigned Level); public: - explicit IntervalMap(Allocator &a) : height(0), rootSize(0), allocator(a) { + explicit IntervalMap(Allocator &a) : height(0), rootSize(0), allocator(&a) { assert((uintptr_t(&data) & (alignof(RootLeaf) - 1)) == 0 && "Insufficient alignment"); new(&rootLeaf()) RootLeaf(); } + IntervalMap(IntervalMap const &RHS) { *this = RHS; } + IntervalMap &operator=(IntervalMap const &RHS) { + clear(); + allocator = RHS.allocator; + for (auto It = RHS.begin(), End = RHS.end(); It != End; ++It) + insert(It.start(), It.stop(), It.value()); + return *this; + } + + IntervalMap(IntervalMap &&RHS) { *this = std::move(RHS); } + IntervalMap &operator=(IntervalMap &&RHS) { + std::swap(data, RHS.data); + std::swap(height, RHS.height); + std::swap(rootSize, RHS.rootSize); + std::swap(allocator, RHS.allocator); + return *this; + } + ~IntervalMap() { clear(); rootLeaf().~RootLeaf(); Index: llvm/unittests/ADT/IntervalMapTest.cpp =================================================================== --- llvm/unittests/ADT/IntervalMapTest.cpp +++ llvm/unittests/ADT/IntervalMapTest.cpp @@ -620,26 +620,70 @@ } +void setupOverlaps(UUMap &M) { + M.insert(10, 20, 0); + M.insert(30, 40, 0); + M.insert(50, 60, 0); +} + +void checkOverlaps(UUMap &M) { + EXPECT_FALSE(M.overlaps(0, 9)); + EXPECT_TRUE(M.overlaps(0, 10)); + EXPECT_TRUE(M.overlaps(0, 15)); + EXPECT_TRUE(M.overlaps(0, 25)); + EXPECT_TRUE(M.overlaps(0, 45)); + EXPECT_TRUE(M.overlaps(10, 45)); + EXPECT_TRUE(M.overlaps(30, 45)); + EXPECT_TRUE(M.overlaps(35, 36)); + EXPECT_TRUE(M.overlaps(40, 45)); + EXPECT_FALSE(M.overlaps(45, 45)); + EXPECT_TRUE(M.overlaps(60, 60)); + EXPECT_TRUE(M.overlaps(60, 66)); + EXPECT_FALSE(M.overlaps(66, 66)); +} + +TEST(IntervalMapTest, Copy) { + // Test that copy assignment and initialization works. + UUHalfOpenMap::Allocator Allocator; + UUMap Src(Allocator); + setupOverlaps(Src); + + UUMap CopyAssignmentDst(Allocator); + CopyAssignmentDst = Src; + + UUMap CopyInitDst(Src); + + checkOverlaps(Src); + Src.clear(); + + checkOverlaps(CopyAssignmentDst); + checkOverlaps(CopyInitDst); +} + +TEST(IntervalMapTest, Move) { + // Test that move assignment and initialization works. + UUHalfOpenMap::Allocator Allocator; + // Double check that MoveAssignmentDst owns all its data by moving from an + // object that is destroyed before we call checkOverlaps. + UUMap MoveAssignmentDst(Allocator); + { + UUMap Src(Allocator); + setupOverlaps(Src); + MoveAssignmentDst = std::move(Src); + } + checkOverlaps(MoveAssignmentDst); + + UUMap MoveInitSrc(Allocator); + setupOverlaps(MoveInitSrc); + UUMap MoveInitDst(std::move(MoveInitSrc)); + checkOverlaps(MoveInitDst); +} + TEST(IntervalMapTest, Overlaps) { UUMap::Allocator allocator; UUMap map(allocator); - map.insert(10, 20, 0); - map.insert(30, 40, 0); - map.insert(50, 60, 0); - - EXPECT_FALSE(map.overlaps(0, 9)); - EXPECT_TRUE(map.overlaps(0, 10)); - EXPECT_TRUE(map.overlaps(0, 15)); - EXPECT_TRUE(map.overlaps(0, 25)); - EXPECT_TRUE(map.overlaps(0, 45)); - EXPECT_TRUE(map.overlaps(10, 45)); - EXPECT_TRUE(map.overlaps(30, 45)); - EXPECT_TRUE(map.overlaps(35, 36)); - EXPECT_TRUE(map.overlaps(40, 45)); - EXPECT_FALSE(map.overlaps(45, 45)); - EXPECT_TRUE(map.overlaps(60, 60)); - EXPECT_TRUE(map.overlaps(60, 66)); - EXPECT_FALSE(map.overlaps(66, 66)); + setupOverlaps(map); + checkOverlaps(map); } TEST(IntervalMapTest, OverlapsHalfOpen) {