PR middle-end/90904 - vec assignment and copying undefined gcc/ChangeLog: * vec.c (test_copy_assign): New function. (vec_c_tests): Call it. * vec.h (auto_vec copy ctor): Define. (auto_vec::operator=): Define. diff --git a/gcc/vec.c b/gcc/vec.c index f9dbb2cac31..c9299875257 100644 --- a/gcc/vec.c +++ b/gcc/vec.c @@ -317,6 +317,83 @@ test_safe_push () ASSERT_EQ (7, v[2]); } +/* Verify that auto_vec copy ctor and assignment work correctly. */ + +static void +test_copy_assign () +{ + auto_vec a0; + auto_vec b0 (0); + auto_vec c0 (7); + ASSERT_EQ (0, b0.length ()); + ASSERT_EQ (0, c0.length ()); + + a0 = a0; + ASSERT_EQ (0, a0.length ()); + b0 = a0; + ASSERT_EQ (0, b0.length ()); + c0 = a0; + ASSERT_EQ (0, c0.length ()); + + auto_vec a3; + a3.safe_push (5); + a3.safe_push (6); + a3.safe_push (7); + + auto_vec b3 (a3); + ASSERT_EQ (3, b3.length ()); + ASSERT_EQ (5, b3[0]); + ASSERT_EQ (6, b3[1]); + ASSERT_EQ (7, b3[2]); + + auto_vec c3; + c3 = b3; + ASSERT_EQ (3, c3.length ()); + ASSERT_EQ (5, c3[0]); + ASSERT_EQ (6, c3[1]); + ASSERT_EQ (7, c3[2]); + + auto_vec d4; + d4.safe_push (1); + d4.safe_push (2); + d4.safe_push (3); + d4.safe_push (4); + + c3 = d4; + ASSERT_EQ (4, c3.length ()); + ASSERT_EQ (1, c3[0]); + ASSERT_EQ (2, c3[1]); + ASSERT_EQ (3, c3[2]); + ASSERT_EQ (4, c3[3]); + + d4 = a3; + ASSERT_EQ (3, d4.length ()); + ASSERT_EQ (5, d4[0]); + ASSERT_EQ (6, d4[1]); + ASSERT_EQ (7, d4[2]); + + a3 = b0; + ASSERT_EQ (0, a3.length ()); + + b3 = b0; + ASSERT_EQ (0, b3.length ()); + + c3 = c0; + ASSERT_EQ (0, c3.length ()); + + b0 = d4; + ASSERT_EQ (3, b0.length ()); + ASSERT_EQ (5, b0[0]); + ASSERT_EQ (6, b0[1]); + ASSERT_EQ (7, b0[2]); + + c0 = d4; + ASSERT_EQ (3, c0.length ()); + ASSERT_EQ (5, c0[0]); + ASSERT_EQ (6, c0[1]); + ASSERT_EQ (7, c0[2]); +} + /* Verify that vec::truncate works correctly. */ static void @@ -549,6 +626,7 @@ vec_c_tests () { test_quick_push (); test_safe_push (); + test_copy_assign (); test_truncate (); test_safe_grow_cleared (); test_pop (); diff --git a/gcc/vec.h b/gcc/vec.h index 24df2db0eeb..61397bb7ee0 100644 --- a/gcc/vec.h +++ b/gcc/vec.h @@ -1551,12 +1551,21 @@ public: auto_vec (size_t n CXX_MEM_STAT_INFO) { this->create (n PASS_MEM_STAT); } ~auto_vec () { this->release (); } + /* Copy ctor. */ + auto_vec (const auto_vec&); + + /* Move ctor from a heap-allocated vec. */ auto_vec (vec&& r) { gcc_assert (!r.using_auto_storage ()); this->m_vec = r.m_vec; r.m_vec = NULL; } + + /* Copy asssignment. */ + auto_vec& operator= (const auto_vec&); + + /* Move asssignment from a heap-allocated vec. */ auto_vec& operator= (vec&& r) { gcc_assert (!r.using_auto_storage ()); @@ -1567,6 +1576,49 @@ public: } }; +/* Copy elements from R to *THIS. */ + +template +auto_vec::auto_vec (const auto_vec& r) +{ + const unsigned n = r.length (); + this->create (n); + if (n) + { + vec_copy_construct (this->address (), r.address (), n); + this->m_vec->m_vecpfx.m_num = n; + } +} + +/* Assign elements from R over *THIS, invoking the copy assignment + operator on the initial elements and the copy ctor on the excess. */ + +template +auto_vec& auto_vec::operator= (const auto_vec& r) +{ + unsigned n0 = this->length (); + const unsigned n1 = r.length (); + if (n0 < n1) + this->safe_grow (n1); + else + { + this->truncate (n1); + n0 = n1; + } + + T *dst = this->address (); + const T *src = r.address (); + + /* Copy-assign over the first N0 elements. */ + for (unsigned i = 0; i != n0; ++i) + dst[i] = src[i]; + + if (n0 < n1) + /* Copy-construct elements in excess of N0. */ + vec_copy_construct (dst + n0, src + n0, n1 - n0); + + return *this; +} /* Allocate heap memory for pointer V and create the internal vector with space for NELEMS elements. If NELEMS is 0, the internal