diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h --- a/llvm/include/llvm/ADT/SmallVector.h +++ b/llvm/include/llvm/ADT/SmallVector.h @@ -593,7 +593,7 @@ return; if (N < this->size()) { - this->pop_back_n(this->size() - N); + this->truncate(N); return; } @@ -612,12 +612,19 @@ /// Like resize, but \ref T is POD, the new values won't be initialized. void resize_for_overwrite(size_type N) { resizeImpl(N); } + /// Like resize, but requires that \p N is less than \a size(). + void truncate(size_type N) { + assert(this->size() >= N && "Cannot increase size with truncate"); + this->destroy_range(this->begin() + N, this->end()); + this->set_size(N); + } + void resize(size_type N, ValueParamT NV) { if (N == this->size()) return; if (N < this->size()) { - this->pop_back_n(this->size() - N); + this->truncate(N); return; } @@ -632,8 +639,7 @@ void pop_back_n(size_type NumItems) { assert(this->size() >= NumItems); - this->destroy_range(this->end() - NumItems, this->end()); - this->set_size(this->size() - NumItems); + truncate(this->size() - NumItems); } LLVM_NODISCARD T pop_back_val() { diff --git a/llvm/unittests/ADT/SmallVectorTest.cpp b/llvm/unittests/ADT/SmallVectorTest.cpp --- a/llvm/unittests/ADT/SmallVectorTest.cpp +++ b/llvm/unittests/ADT/SmallVectorTest.cpp @@ -309,6 +309,32 @@ EXPECT_EQ(5, Constructable::getNumDestructorCalls()); } +// Truncate test. +TYPED_TEST(SmallVectorTest, TruncateTest) { + SCOPED_TRACE("TruncateTest"); + + this->theVector.reserve(3); + this->makeSequence(this->theVector, 1, 3); + this->theVector.truncate(1); + + this->assertValuesInOrder(this->theVector, 1u, 1); + EXPECT_EQ(6, Constructable::getNumConstructorCalls()); + EXPECT_EQ(5, Constructable::getNumDestructorCalls()); + +#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST + EXPECT_DEATH(this->theVector.truncate(2), "Cannot increase size"); +#endif + this->theVector.truncate(1); + this->assertValuesInOrder(this->theVector, 1u, 1); + EXPECT_EQ(6, Constructable::getNumConstructorCalls()); + EXPECT_EQ(5, Constructable::getNumDestructorCalls()); + + this->theVector.truncate(0); + this->assertEmpty(this->theVector); + EXPECT_EQ(6, Constructable::getNumConstructorCalls()); + EXPECT_EQ(6, Constructable::getNumDestructorCalls()); +} + // Resize bigger test. TYPED_TEST(SmallVectorTest, ResizeGrowTest) { SCOPED_TRACE("ResizeGrowTest");