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.