From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2181) id 1D3D03853808; Thu, 20 Apr 2023 13:57:48 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1D3D03853808 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1681999068; bh=/cxqbefeuFv5KyuPTZFBaOvDtHvte8eRnmnghJg6+u0=; h=From:To:Subject:Date:From; b=EGuIX+sDV97W4ZgrOv4p+Cxpp9eu25zk5xtqVBdVLKb7OHS3DwPhXR2Nnu8tV+zd4 QeptIOLue3Mz/ymXsp5HcWaSPWhFBJAeopj7DsUaNY2J6eXy2zqVV4zbo4Qi1A/WfN 59Ldf6fSSxqzhpno9js5Xm9XNT5+YXu+5eIDMgL0= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jonathan Wakely To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r12-9457] libstdc++: Avoid bogus warning in std::vector::insert [PR107852] X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/heads/releases/gcc-12 X-Git-Oldrev: e016a6ddbf0038056b9d8f2bc0bad350ff026632 X-Git-Newrev: 2e4210698c644e44f9e0645dc7bc49710fd60ce8 Message-Id: <20230420135748.1D3D03853808@sourceware.org> Date: Thu, 20 Apr 2023 13:57:48 +0000 (GMT) List-Id: https://gcc.gnu.org/g:2e4210698c644e44f9e0645dc7bc49710fd60ce8 commit r12-9457-g2e4210698c644e44f9e0645dc7bc49710fd60ce8 Author: Jonathan Wakely Date: Tue Nov 29 15:50:06 2022 +0000 libstdc++: Avoid bogus warning in std::vector::insert [PR107852] 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. (cherry picked from commit cca06f0d6d76b08ed4ddb7667eda93e2e9f2589e) Diff: --- 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;