summaryrefslogtreecommitdiff
path: root/unittests
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2014-04-30 15:49:06 +0000
committerDouglas Gregor <dgregor@apple.com>2014-04-30 15:49:06 +0000
commit3bdb9015b1226c33231794c1ace84cd5b8a7e6f3 (patch)
tree7cc92aeb99609b844538cc3a0974937ac2c8b0a3 /unittests
parent41fb11790562745484a1aaade7377d11d970972a (diff)
downloadllvm-3bdb9015b1226c33231794c1ace84cd5b8a7e6f3.tar.gz
llvm-3bdb9015b1226c33231794c1ace84cd5b8a7e6f3.tar.bz2
llvm-3bdb9015b1226c33231794c1ace84cd5b8a7e6f3.tar.xz
Fix a use of uninitialized memory in SmallVector's move-assignment operator.
When we were moving from a larger vector to a smaller one but didn't need to re-allocate, we would move-assign over uninitialized memory in the target, then move-construct that same data again. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207663 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests')
-rw-r--r--unittests/ADT/SmallVectorTest.cpp63
1 files changed, 54 insertions, 9 deletions
diff --git a/unittests/ADT/SmallVectorTest.cpp b/unittests/ADT/SmallVectorTest.cpp
index 90c7982699..58f55914ba 100644
--- a/unittests/ADT/SmallVectorTest.cpp
+++ b/unittests/ADT/SmallVectorTest.cpp
@@ -29,27 +29,43 @@ private:
static int numDestructorCalls;
static int numAssignmentCalls;
+ bool constructed;
int value;
public:
- Constructable() : value(0) {
+ Constructable() : constructed(true), value(0) {
++numConstructorCalls;
}
- Constructable(int val) : value(val) {
+ Constructable(int val) : constructed(true), value(val) {
++numConstructorCalls;
}
- Constructable(const Constructable & src) {
+ Constructable(const Constructable & src) : constructed(true) {
+ value = src.value;
+ ++numConstructorCalls;
+ }
+
+ Constructable(Constructable && src) : constructed(true) {
value = src.value;
++numConstructorCalls;
}
~Constructable() {
+ EXPECT_TRUE(constructed);
++numDestructorCalls;
+ constructed = false;
}
Constructable & operator=(const Constructable & src) {
+ EXPECT_TRUE(constructed);
+ value = src.value;
+ ++numAssignmentCalls;
+ return *this;
+ }
+
+ Constructable & operator=(Constructable && src) {
+ EXPECT_TRUE(constructed);
value = src.value;
++numAssignmentCalls;
return *this;
@@ -338,6 +354,36 @@ TYPED_TEST(SmallVectorTest, AssignTest) {
this->assertValuesInOrder(this->theVector, 2u, 77, 77);
}
+// Move-assign test
+TYPED_TEST(SmallVectorTest, MoveAssignTest) {
+ SCOPED_TRACE("MoveAssignTest");
+
+ // Set up our vector with a single element, but enough capacity for 4.
+ this->theVector.reserve(4);
+ this->theVector.push_back(Constructable(1));
+
+ // Set up the other vector with 2 elements.
+ this->otherVector.push_back(Constructable(2));
+ this->otherVector.push_back(Constructable(3));
+
+ // Move-assign from the other vector.
+ this->theVector = std::move(this->otherVector);
+
+ // Make sure we have the right result.
+ this->assertValuesInOrder(this->theVector, 2u, 2, 3);
+
+ // Make sure the # of constructor/destructor calls line up. There
+ // are two live objects after clearing the other vector.
+ this->otherVector.clear();
+ EXPECT_EQ(Constructable::getNumConstructorCalls()-2,
+ Constructable::getNumDestructorCalls());
+
+ // There shouldn't be any live objects any more.
+ this->theVector.clear();
+ EXPECT_EQ(Constructable::getNumConstructorCalls(),
+ Constructable::getNumDestructorCalls());
+}
+
// Erase a single element
TYPED_TEST(SmallVectorTest, EraseTest) {
SCOPED_TRACE("EraseTest");
@@ -455,13 +501,12 @@ TYPED_TEST(SmallVectorTest, DirectVectorTest) {
this->theVector.reserve(4);
EXPECT_LE(4u, this->theVector.capacity());
EXPECT_EQ(0, Constructable::getNumConstructorCalls());
- this->theVector.end()[0] = 1;
- this->theVector.end()[1] = 2;
- this->theVector.end()[2] = 3;
- this->theVector.end()[3] = 4;
- this->theVector.set_size(4);
+ this->theVector.push_back(1);
+ this->theVector.push_back(2);
+ this->theVector.push_back(3);
+ this->theVector.push_back(4);
EXPECT_EQ(4u, this->theVector.size());
- EXPECT_EQ(4, Constructable::getNumConstructorCalls());
+ EXPECT_EQ(8, Constructable::getNumConstructorCalls());
EXPECT_EQ(1, this->theVector[0].getValue());
EXPECT_EQ(2, this->theVector[1].getValue());
EXPECT_EQ(3, this->theVector[2].getValue());