From patchwork Tue Nov 29 17:14:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 1710206 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=iPQ7zAl4; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4NM89s4Lc6z23nT for ; Wed, 30 Nov 2022 04:15:45 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 8B8ED385221B for ; Tue, 29 Nov 2022 17:15:43 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8B8ED385221B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1669742143; bh=839+WqtVWERgRR/DY67tNn6a3sjycnFxvco3zd0OVPw=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=iPQ7zAl4nTX2sgaLWjV6nMVsFLDfZfUuxHZTErdDYMUgOXU3mQ0JBR82AVQUc/6sf AZN58Tqdp1dBgInk4EZvMf/n4B5Se/dnfPf1Ksw0dRnohKVEKvs57cLCJkb2aYHYQV mBSpYITM1vWU9Lh/iaaa4eZfV3JDrDWJXhdWV94o= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 1958C3857400 for ; Tue, 29 Nov 2022 17:14:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 1958C3857400 Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-196-xxMiRHiFM1qkt6Enu4j-Mw-1; Tue, 29 Nov 2022 12:14:47 -0500 X-MC-Unique: xxMiRHiFM1qkt6Enu4j-Mw-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 342CA3C1022D; Tue, 29 Nov 2022 17:14:47 +0000 (UTC) Received: from localhost (unknown [10.33.36.164]) by smtp.corp.redhat.com (Postfix) with ESMTP id ED3B42024CB7; Tue, 29 Nov 2022 17:14:46 +0000 (UTC) To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Avoid bogus warning in std::vector::insert [PR107852] Date: Tue, 29 Nov 2022 17:14:46 +0000 Message-Id: <20221129171446.149751-1-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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-Patchwork-Original-From: Jonathan Wakely via Gcc-patches From: Jonathan Wakely Reply-To: Jonathan Wakely Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Tested x86_64-linux. Pushed to trunk. -- >8 -- GCC assumes that any global variable might be modified by operator new, and so in the testcase for this PR all data members get reloaded after allocating new storage. By making local copies of the _M_start and _M_finish members we avoid that, and then the compiler has enough info to remove the dead branches that trigger bogus -Warray-bounds warnings. libstdc++-v3/ChangeLog: PR libstdc++/107852 PR libstdc++/106199 PR libstdc++/100366 * include/bits/vector.tcc (vector::_M_fill_insert): Copy _M_start and _M_finish members before allocating. (vector::_M_default_append): Likewise. (vector::_M_range_insert): Likewise. --- libstdc++-v3/include/bits/vector.tcc | 63 ++++++++++++++++------------ 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc index 33faabf2eae..27ef1a4ee7f 100644 --- a/libstdc++-v3/include/bits/vector.tcc +++ b/libstdc++-v3/include/bits/vector.tcc @@ -539,9 +539,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if (__elems_after > __n) { _GLIBCXX_ASAN_ANNOTATE_GROW(__n); - std::__uninitialized_move_a(this->_M_impl._M_finish - __n, - this->_M_impl._M_finish, - this->_M_impl._M_finish, + std::__uninitialized_move_a(__old_finish - __n, + __old_finish, + __old_finish, _M_get_Tp_allocator()); this->_M_impl._M_finish += __n; _GLIBCXX_ASAN_ANNOTATE_GREW(__n); @@ -554,7 +554,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { _GLIBCXX_ASAN_ANNOTATE_GROW(__n); this->_M_impl._M_finish = - std::__uninitialized_fill_n_a(this->_M_impl._M_finish, + std::__uninitialized_fill_n_a(__old_finish, __n - __elems_after, __x_copy, _M_get_Tp_allocator()); @@ -569,9 +569,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } else { + // Make local copies of these members because the compiler thinks + // the allocator can alter them if 'this' is globally reachable. + pointer __old_start = this->_M_impl._M_start; + pointer __old_finish = this->_M_impl._M_finish; + const pointer __pos = __position.base(); + const size_type __len = _M_check_len(__n, "vector::_M_fill_insert"); - const size_type __elems_before = __position - begin(); + const size_type __elems_before = __pos - __old_start; pointer __new_start(this->_M_allocate(__len)); pointer __new_finish(__new_start); __try @@ -584,15 +590,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __new_finish = std::__uninitialized_move_if_noexcept_a - (this->_M_impl._M_start, __position.base(), - __new_start, _M_get_Tp_allocator()); + (__old_start, __pos, __new_start, _M_get_Tp_allocator()); __new_finish += __n; __new_finish = std::__uninitialized_move_if_noexcept_a - (__position.base(), this->_M_impl._M_finish, - __new_finish, _M_get_Tp_allocator()); + (__pos, __old_finish, __new_finish, _M_get_Tp_allocator()); } __catch(...) { @@ -606,12 +610,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_deallocate(__new_start, __len); __throw_exception_again; } - std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, - _M_get_Tp_allocator()); + std::_Destroy(__old_start, __old_finish, _M_get_Tp_allocator()); _GLIBCXX_ASAN_ANNOTATE_REINIT; - _M_deallocate(this->_M_impl._M_start, - this->_M_impl._M_end_of_storage - - this->_M_impl._M_start); + _M_deallocate(__old_start, + this->_M_impl._M_end_of_storage - __old_start); this->_M_impl._M_start = __new_start; this->_M_impl._M_finish = __new_finish; this->_M_impl._M_end_of_storage = __new_start + __len; @@ -645,6 +647,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } else { + // Make local copies of these members because the compiler thinks + // the allocator can alter them if 'this' is globally reachable. + pointer __old_start = this->_M_impl._M_start; + pointer __old_finish = this->_M_impl._M_finish; + const size_type __len = _M_check_len(__n, "vector::_M_default_append"); pointer __new_start(this->_M_allocate(__len)); @@ -660,7 +667,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_deallocate(__new_start, __len); __throw_exception_again; } - _S_relocate(this->_M_impl._M_start, this->_M_impl._M_finish, + _S_relocate(__old_start, __old_finish, __new_start, _M_get_Tp_allocator()); } else @@ -672,7 +679,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __n, _M_get_Tp_allocator()); __destroy_from = __new_start + __size; std::__uninitialized_move_if_noexcept_a( - this->_M_impl._M_start, this->_M_impl._M_finish, + __old_start, __old_finish, __new_start, _M_get_Tp_allocator()); } __catch(...) @@ -683,13 +690,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_deallocate(__new_start, __len); __throw_exception_again; } - std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, + std::_Destroy(__old_start, __old_finish, _M_get_Tp_allocator()); } _GLIBCXX_ASAN_ANNOTATE_REINIT; - _M_deallocate(this->_M_impl._M_start, - this->_M_impl._M_end_of_storage - - this->_M_impl._M_start); + _M_deallocate(__old_start, + this->_M_impl._M_end_of_storage - __old_start); this->_M_impl._M_start = __new_start; this->_M_impl._M_finish = __new_start + __size + __n; this->_M_impl._M_end_of_storage = __new_start + __len; @@ -782,6 +788,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } else { + // Make local copies of these members because the compiler + // thinks the allocator can alter them if 'this' is globally + // reachable. + pointer __old_start = this->_M_impl._M_start; + pointer __old_finish = this->_M_impl._M_finish; + const size_type __len = _M_check_len(__n, "vector::_M_range_insert"); pointer __new_start(this->_M_allocate(__len)); @@ -790,7 +802,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { __new_finish = std::__uninitialized_move_if_noexcept_a - (this->_M_impl._M_start, __position.base(), + (__old_start, __position.base(), __new_start, _M_get_Tp_allocator()); __new_finish = std::__uninitialized_copy_a(__first, __last, @@ -798,7 +810,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_get_Tp_allocator()); __new_finish = std::__uninitialized_move_if_noexcept_a - (__position.base(), this->_M_impl._M_finish, + (__position.base(), __old_finish, __new_finish, _M_get_Tp_allocator()); } __catch(...) @@ -808,12 +820,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_deallocate(__new_start, __len); __throw_exception_again; } - std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, + std::_Destroy(__old_start, __old_finish, _M_get_Tp_allocator()); _GLIBCXX_ASAN_ANNOTATE_REINIT; - _M_deallocate(this->_M_impl._M_start, - this->_M_impl._M_end_of_storage - - this->_M_impl._M_start); + _M_deallocate(__old_start, + this->_M_impl._M_end_of_storage - __old_start); this->_M_impl._M_start = __new_start; this->_M_impl._M_finish = __new_finish; this->_M_impl._M_end_of_storage = __new_start + __len;