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

            Bug ID: 97232
           Summary: Iterator category of "std::prev" are not checked
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: lesley at lesleylai dot info
  Target Milestone: ---

As Matt Godbolt tweeted
https://twitter.com/mattgodbolt/status/1310590905217409024?s=20, `std::prev`
silently accepts a forward iterator and crash at runtime. Here is his sample
code: https://godbolt.org/z/9cKKsT

I found the implementation in `bits/stl_iterator_base_funcs.h` looks like this:

  template<typename _BidirectionalIterator>
    inline _GLIBCXX17_CONSTEXPR _BidirectionalIterator
    prev(_BidirectionalIterator __x, typename
         iterator_traits<_BidirectionalIterator>::difference_type __n = 1) 
    {
      // concept requirements
      __glibcxx_function_requires(_BidirectionalIteratorConcept<
                                  _BidirectionalIterator>)
      std::advance(__x, -__n);
      return __x;
    }

The `__glibcxx_function_requires` is a no-op be default, and the whole Concept
Checking mechanism seems to be outdated. Instead, checking
`_BidirectionalIterator` with a `static_assert` should solve this problem:

  template<typename _BidirectionalIterator>
    inline _GLIBCXX17_CONSTEXPR _BidirectionalIterator
    prev(_BidirectionalIterator __x, typename
         iterator_traits<_BidirectionalIterator>::difference_type __n = 1) 
    {
      static_assert(is_same<typename
std::iterator_traits<_BidirectionalIterator>::value_type, 
               std::bidirectional_iterator_tag>::value, "_BidirectionalIterator
must be a bidirectional_iterator");

      std::advance(__x, -__n);
      return __x;
    }

Reply via email to