summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Blaikie <dblaikie@gmail.com>2014-06-08 16:00:02 +0000
committerDavid Blaikie <dblaikie@gmail.com>2014-06-08 16:00:02 +0000
commite570687bd8bff68921a2fa9840ad5aa270a8c9d8 (patch)
treecab9e031a8838a003c8dece669181cf44c6fabdb
parent6e0ab2f54c1ce957cd067a78b0dd34bd79cf1a54 (diff)
downloadllvm-e570687bd8bff68921a2fa9840ad5aa270a8c9d8.tar.gz
llvm-e570687bd8bff68921a2fa9840ad5aa270a8c9d8.tar.bz2
llvm-e570687bd8bff68921a2fa9840ad5aa270a8c9d8.tar.xz
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) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210426 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/ADT/SmallVector.h2
-rw-r--r--unittests/ADT/SmallVectorTest.cpp22
2 files changed, 23 insertions, 1 deletions
diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h
index dcf0354860..29ad250010 100644
--- a/include/llvm/ADT/SmallVector.h
+++ b/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/unittests/ADT/SmallVectorTest.cpp b/unittests/ADT/SmallVectorTest.cpp
index 58f55914ba..cccf93b6bc 100644
--- a/unittests/ADT/SmallVectorTest.cpp
+++ b/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<MovedFrom, 3> v;
+ v.push_back(MovedFrom());
+ v.insert(v.begin(), MovedFrom());
+ for (MovedFrom &m : v)
+ EXPECT_TRUE(m.hasValue);
+}
+
}