[PATCH][Bug libstdc++/70303] Value-initialized debug iterators

François Dumont frs.dumont@gmail.com
Mon Feb 8 21:27:19 GMT 2021


On 01/02/21 8:09 pm, Jonathan Wakely wrote:
> On 01/02/21 19:30 +0100, François Dumont via Libstdc++ wrote:
>> On 01/02/21 6:43 pm, Jonathan Wakely wrote:
>>> On 31/01/21 16:59 +0100, François Dumont via Libstdc++ wrote:
>>>> After the debug issue has been fixed in PR 98466 the problem was 
>>>> not in the debug iterator implementation itself but in the deque 
>>>> iterator operator- implementation.
>>>>
>>>>     libstdc++: Make deque iterator operator- usable with value-init 
>>>> iterators
>>>>
>>>>     N3644 implies that operator- can be used on value-init 
>>>> iterators. We now return
>>>>     0 if both iterators are value initialized. If only one is value 
>>>> initialized we
>>>>     keep the UB by returning the result of a normal computation 
>>>> which is an unexpected
>>>>     value.
>>>>
>>>>     libstdc++/ChangeLog:
>>>>
>>>>             PR libstdc++/70303
>>>>             * include/bits/stl_deque.h 
>>>> (std::deque<>::operator-(iterator, iterator)):
>>>>             Return 0 if both iterators are value-initialized.
>>>>             * testsuite/23_containers/deque/70303.cc: New test.
>>>>             * testsuite/23_containers/vector/70303.cc: New test.
>>>>
>>>> Tested under Linux x86_64, ok to commit ?
>>>
>>> OK.
>>>
>>> I don't like adding the branch there though. Even with the
>>> __builtin_expect it causes worse code to be generated than the
>>> original.
>>>
>>> This would be branchless, but a bit harder to understand:
>>>
>>>     return difference_type(__x._S_buffer_size())
>>>       * (__x._M_node - __y._M_node - int(__x._M_node == __y._M_node))
>>>       + (__x._M_cur - __x._M_first) + (__y._M_last - __y._M_cur);
>>>
>>> Please commit the fix and we can think about it later.
>>
>> I do not think this work because for value-init iterators we have 
>> __x._M_node == __y._M_node == nullptr so the diff would give 
>> -_S_buffer_size().
>>
>> But I got the idear, I'll prepare the patch.
>
> Yeah, I just came back to the computer to say that it's wrong. But
> maybe this:
>
>     return difference_type(_S_buffer_size())
>       * (__x._M_node - __y._M_node - int(__x._M_node && __y._M_node))
>       + (__x._M_cur - __x._M_first) + (__y._M_last - __y._M_cur);
>
> For value-init'd iterators we'd get _S_buffer_size() * 0 + 0 - 0
>
> We could even just use int(__x._M_node != 0) because if one is null
> and the other isn't, it's UB anyway.
>
>
This is what I've tested with success. As it is a recent kind of 
regression you might want to consider it now.

     libstdc++: Remove execution branch in deque iterator operator-

     libstdc++-v3/ChangeLog:

             * include/bits/stl_deque.h
             (std::operator-(deque::iterator, deque::iterator)): Replace 
if/then with
             a null pointer test.

Ok to commit ?

François

-------------- next part --------------
A non-text attachment was scrubbed...
Name: deque_ite_operator.patch
Type: text/x-patch
Size: 1423 bytes
Desc: not available
URL: <https://gcc.gnu.org/pipermail/gcc-patches/attachments/20210208/5c2d9be7/attachment.bin>


More information about the Gcc-patches mailing list