From 789df06f876b5cc5ccd940ed76cb0b25f2fdb585 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Sun, 8 Jun 2014 16:00:02 +0000 Subject: [PATCH] Ensure SmallVector::insert doesn't overwrite the last element in the range with the already-moved-from value This would cause the last element in a range to be in a moved-from state after an insert at a non-end position, losing that value entirely in the process. Side note: move_backward is subtle. It copies [A, B) to C-1 and down. (the fact that it decrements both the second and third iterators before the first movement is the subtle part... kind of surprising, anyway) llvm-svn: 210426 --- llvm/include/llvm/ADT/SmallVector.h | 2 +- llvm/unittests/ADT/SmallVectorTest.cpp | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h index dcf0354..29ad250 100644 --- a/llvm/include/llvm/ADT/SmallVector.h +++ b/llvm/include/llvm/ADT/SmallVector.h @@ -488,9 +488,9 @@ public: } ::new ((void*) this->end()) T(::std::move(this->back())); - this->setEnd(this->end()+1); // Push everything else over. this->move_backward(I, this->end()-1, this->end()); + this->setEnd(this->end()+1); // If we just moved the element we're inserting, be sure to update // the reference. diff --git a/llvm/unittests/ADT/SmallVectorTest.cpp b/llvm/unittests/ADT/SmallVectorTest.cpp index 58f5591..cccf93b 100644 --- a/llvm/unittests/ADT/SmallVectorTest.cpp +++ b/llvm/unittests/ADT/SmallVectorTest.cpp @@ -531,4 +531,26 @@ TEST(SmallVectorCustomTest, NoAssignTest) { EXPECT_EQ(42, vec.pop_back_val().x); } +struct MovedFrom { + bool hasValue; + MovedFrom() : hasValue(true) { + } + MovedFrom(MovedFrom&& m) : hasValue(m.hasValue) { + m.hasValue = false; + } + MovedFrom &operator=(MovedFrom&& m) { + hasValue = m.hasValue; + m.hasValue = false; + return *this; + } +}; + +TEST(SmallVectorTest, MidInsert) { + SmallVector v; + v.push_back(MovedFrom()); + v.insert(v.begin(), MovedFrom()); + for (MovedFrom &m : v) + EXPECT_TRUE(m.hasValue); +} + } -- 2.7.4