From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-qt1-x829.google.com (mail-qt1-x829.google.com [IPv6:2607:f8b0:4864:20::829]) by sourceware.org (Postfix) with ESMTPS id C25273956835 for ; Mon, 26 Apr 2021 23:30:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org C25273956835 Received: by mail-qt1-x829.google.com with SMTP id y12so42972712qtx.11 for ; Mon, 26 Apr 2021 16:30:26 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version:content-language; bh=gyBmZb3cNiVO2vuVVapail6Y2RVGlQeOxphcHOEuumU=; b=KbpCwrnur7hQ93ShjWqgEXY1v3QD2DsZFhXGaKJcbiy4Aupa66/EkMBYz5tCRWmjAU FuK2/+qpD7TXkukK3zaH2QAKhuYJWhVMjRhfMrItbAJhjTcT8zZSj+6pfVrpZDd+8lp8 4vjnwxF+myczhnpLkqsS/MXNcrWzKc7F16qsl8MA1tUljTvDqaMRYU3XvVDpEjDSrL/N eypiJZCD/mP1cydzSZzIC7RFAW8lyOq6ojEMdeqBRxxw8XwcwB8GYCpz4JPIwZbzaatt dQERqKoSeoG+EGkSOw4ej8qtAYBA4FBIDWy8IF7Pj9RME56D1dWDQSz/FG2yX6P4iulU QJbQ== X-Gm-Message-State: AOAM531TikRuofWu1ICWzqbrwJUTj2GavMp3H7ai2HXc4pWRQLhblQbc +QOV091hIMjWJUAhp+2FoXXYmboYu9E= X-Google-Smtp-Source: ABdhPJyNpRWiSKmmaBxhmljh9HqHKrXpTOJzjRXYbWBTviQdOYJSBatNgI36H6aAZRU+Lt1GH+X02Q== X-Received: by 2002:a05:622a:170e:: with SMTP id h14mr18717230qtk.287.1619479826301; Mon, 26 Apr 2021 16:30:26 -0700 (PDT) Received: from [192.168.0.41] (71-218-14-121.hlrn.qwest.net. [71.218.14.121]) by smtp.gmail.com with ESMTPSA id o12sm13173024qtg.14.2021.04.26.16.30.25 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 26 Apr 2021 16:30:25 -0700 (PDT) To: gcc-patches From: Martin Sebor Subject: [PATCH] define auto_vec copy ctor and assignment (PR 90904) Message-ID: Date: Mon, 26 Apr 2021 17:30:25 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.2.2 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------E88B9D80F916DE05EEF7A7A5" Content-Language: en-US X-Spam-Status: No, score=-10.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 26 Apr 2021 23:30:28 -0000 This is a multi-part message in MIME format. --------------E88B9D80F916DE05EEF7A7A5 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit PR 90904 notes that auto_vec is unsafe to copy and assign because the class manages its own memory but doesn't define (or delete) either special function. Since I first ran into the problem, auto_vec has grown a move ctor and move assignment from a dynamically-allocated vec but still no copy ctor or copy assignment operator. The attached patch adds the two special functions to auto_vec along with a few simple tests. It makes auto_vec safe to use in containers that expect copyable and assignable element types and passes bootstrap and regression testing on x86_64-linux. Martin --------------E88B9D80F916DE05EEF7A7A5 Content-Type: text/x-patch; charset=UTF-8; name="gcc-90904.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="gcc-90904.diff" 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 --------------E88B9D80F916DE05EEF7A7A5--