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

--- Comment #7 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Jonathan Wakely from comment #6)
> (In reply to Piotr Nycz from comment #5)
> > CLANG with its std-lib correctly (IMO) does not compile it.
> 
> As explained above, GCC is already correct here.
> 
> > I understand this is UB - but implementation might suggest it is checked
> > that iterator is biderectional (at least ) but this check has no effect.
> 
> It does if you compile with -D_GLIBCXX_CONCEPT_CHECKS

If you enable concept checks it will fail to compile:

In file included from /usr/include/c++/8/bits/concept_check.h:56,
                 from /usr/include/c++/8/bits/move.h:34,
                 from /usr/include/c++/8/bits/stl_iterator.h:65,
                 from /usr/include/c++/8/bits/forward_list.h:37,
                 from /usr/include/c++/8/forward_list:38,
                 from prev.cc:1:
/usr/include/c++/8/bits/boost_concept_check.h: In instantiation of ‘void
__gnu_cxx::_BidirectionalIteratorConcept<_Tp>::__constraints() [with _Tp =
std::_Fwd_list_iterator<int>]’:
/usr/include/c++/8/bits/boost_concept_check.h:62:39:   required from ‘void
__gnu_cxx::__function_requires() [with _Concept =
__gnu_cxx::_BidirectionalIteratorConcept<std::_Fwd_list_iterator<int> >]’
/usr/include/c++/8/bits/stl_iterator_base_funcs.h:228:7:   required from
‘_BidirectionalIterator std::prev(_BidirectionalIterator, typename
std::iterator_traits<_Iter>::difference_type) [with _BidirectionalIterator =
std::_Fwd_list_iterator<int>; typename
std::iterator_traits<_Iter>::difference_type = long int]’
prev.cc:7:35:   required from here
/usr/include/c++/8/bits/boost_concept_check.h:506:7: error: no match for
‘operator--’ (operand type is ‘std::_Fwd_list_iterator<int>’)
       --__i;                            // require predecrement operator
       ^~~~~
/usr/include/c++/8/bits/boost_concept_check.h:507:10: error: no
‘operator--(int)’ declared for postfix ‘--’ [-fpermissive]
       __i--;                            // require postdecrement operator
       ~~~^~
/usr/include/c++/8/bits/boost_concept_check.h: In instantiation of ‘void
__gnu_cxx::_ConvertibleConcept<_From, _To>::__constraints() [with _From =
std::forward_iterator_tag; _To = std::bidirectional_iterator_tag]’:
/usr/include/c++/8/bits/boost_concept_check.h:62:39:   required from ‘void
__gnu_cxx::__function_requires() [with _Concept =
__gnu_cxx::_ConvertibleConcept<std::forward_iterator_tag,
std::bidirectional_iterator_tag>]’
/usr/include/c++/8/bits/boost_concept_check.h:505:43:   required from ‘void
__gnu_cxx::_BidirectionalIteratorConcept<_Tp>::__constraints() [with _Tp =
std::_Fwd_list_iterator<int>]’
/usr/include/c++/8/bits/boost_concept_check.h:62:39:   required from ‘void
__gnu_cxx::__function_requires() [with _Concept =
__gnu_cxx::_BidirectionalIteratorConcept<std::_Fwd_list_iterator<int> >]’
/usr/include/c++/8/bits/stl_iterator_base_funcs.h:228:7:   required from
‘_BidirectionalIterator std::prev(_BidirectionalIterator, typename
std::iterator_traits<_Iter>::difference_type) [with _BidirectionalIterator =
std::_Fwd_list_iterator<int>; typename
std::iterator_traits<_Iter>::difference_type = long int]’
prev.cc:7:35:   required from here
/usr/include/c++/8/bits/boost_concept_check.h:223:27: error: conversion from
‘std::forward_iterator_tag’ to non-scalar type
‘std::bidirectional_iterator_tag’ requested
       _To __y _IsUnused = __x;
                           ^~~

But I don't recommend using those concepts checks for C++11 or later, because
some of the checks are outdated and only enforce the C++98 requirements, so
they're wrong for the current standard.

If you compile with -D_GLIBCXX_ASSERTIONS (or -D_GLIBCXX_DEBUG which also
enables the former) then it will fail at runtime when trying to advance a
non-bidirectional iterator by a negative number:

/usr/include/c++/8/bits/stl_iterator_base_funcs.h:151: constexpr void
std::__advance(_InputIterator&, _Distance, std::input_iterator_tag) [with
_InputIterator = std::_Fwd_list_iterator<int>; _Distance = long int]: Assertion
'__n >= 0' failed.
Aborted (core dumped)

So we actually already provide two ways to prevent this UB.

Reply via email to