https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110620

--- Comment #9 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
(In reply to Jonathan Wakely from comment #8)
> 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.

Oh I missed that and I am lucky I hadn't tested my proposed change yet.


> 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();

I wonder if we should do something similar for _M_end_of_storage here with __n
too? But maybe the optimizers can figure it out without any extra help. Though
With if the type was a character type maybe __uninitialized_copy_a might cause
the aliasing analysis not to be enough. (maybe that is for another time).

Reply via email to