This patch is similar to the <list> fix but it has a few differences. This patch doesn't use a __link_pointer typedef because we don't need to change the linked list pointers because forward_list never stores a __forward_begin_node in the linked list itself.
The issue with forward_list is that the iterators store pointers to __forward_list_node and not __forward_begin_node. This is incorrect because before_begin() and cbefore_begin() return iterators that point to a __forward_begin_node. This means we incorrectly downcast the __forward_begin_node pointer to a __node_pointer. This downcast itself is sometimes UB but it cannot be safely removed until ABI v2. The more common cause of UB is when we deference the downcast pointer. (for example __ptr_->__next_). This can be fixed without an ABI break by upcasting __ptr_ before accessing it.
The fix is as follows:
- Introduce a __iter_node_pointer typedef that works similar to __link_pointer in the last patch. In ABI v2 it is always a typedef for __begin_node_pointer.
- Change the __before_begin() method to return the correct pointer type (__begin_node_pointer), Previously it incorrectly downcasted the __forward_begin_node to a __node_pointer so it could be used to constructor the iterator types.
- Change __forward_list_iterator and __forward_list_const_iterator in the following way:
- Change __node_pointer __ptr_; member to have the __iter_node_pointer type instead.
- Add additional private constructors that accept __begin_node_pointer in addition to __node_pointer and then correctly cast them to the stored __iter_node_pointer type.
- Add __get_begin() and __get_node_unchecked() accessor methods that correctly cast __ptr_ to the expected pointer type. __get_begin() is always safe to use and should be preferred. __get_node_unchecked() can only be used on a deferencible iterator.
- Replace direct access to __forward_list_iterator::__ptr_ with the safe accessor methods.