https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110620
--- Comment #8 from Jonathan Wakely <redi at gcc dot gnu.org> ---
That isn't necessarily true though. _S_check_init_len takes __n by non-const
reference and changes it to be the number of elements that are actually
allocated *which might be more than requested*. std::vector has to grow
exponentially, so if the current size is 10 and we ask for 12, it will actually
allocate space for 20, and set __n to 20.
So the end_of_storage is start + 20, but finish is start + 12
We could make a copy of __n before the call to _S_check_init_len, and then use
that:
const size_type __orig_n = __n;
pointer __start = this->_M_impl._M_start =
this->_M_allocate(_S_check_init_len(__n, _M_get_Tp_allocator()));
this->_M_impl._M_end_of_storage = __start + __n;
this->_M_impl._M_finish
= std::__uninitialized_copy_a(_GLIBCXX_MOVE(__first), __last,
__start, _M_get_Tp_allocator());
if (this->_M_impl._M_finish - this->_M_impl._M_start != __orig_n)
__builtin_unreachable();
Or equivalently, let _S_check_init_len write to a different variable:
size_type __n_allocated = __n;
pointer __start = this->_M_impl._M_start =
this->_M_allocate(_S_check_init_len(__n_allocated,
_M_get_Tp_allocator()));
this->_M_impl._M_end_of_storage = __start + __n_allocated;
this->_M_impl._M_finish
= std::__uninitialized_copy_a(_GLIBCXX_MOVE(__first), __last,
__start, _M_get_Tp_allocator());
if (this->_M_impl._M_finish - this->_M_impl._M_start != __n)
__builtin_unreachable();