public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug libstdc++/94354] New: std::reverse_iterator comparison operators defined incorrectly
@ 2020-03-27 10:01 redi at gcc dot gnu.org
  2020-03-27 10:17 ` [Bug libstdc++/94354] " redi at gcc dot gnu.org
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: redi at gcc dot gnu.org @ 2020-03-27 10:01 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 94354
           Summary: std::reverse_iterator comparison operators defined
                    incorrectly
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Keywords: rejects-valid
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: redi at gcc dot gnu.org
  Target Milestone: ---

We define the comparison operators for reverse_iterator slightly differently to
how the standard specifies them, which means we incorrectly reject this:

#include <iterator>

struct Iter
{
  using iterator_category = std::random_access_iterator_tag;
  using value_type = int;
  using pointer = int*;
  using reference = int&;
  using difference_type = std::ptrdiff_t;

  Iter();

  Iter& operator++();
  Iter operator++(int);
  Iter& operator--();
  Iter operator--(int);
  int& operator*() const;
  int* operator->() const;

  int& operator[](difference_type) const;

  Iter& operator+=(difference_type);
  Iter& operator-=(difference_type);

  friend Iter operator+(Iter, difference_type);
  friend Iter operator+(difference_type, Iter);
  friend Iter operator-(Iter, difference_type);
  friend difference_type operator-(Iter, Iter);

  friend bool operator==(Iter, Iter);
  friend bool operator!=(Iter, Iter);
  friend bool operator<(Iter, Iter);
  friend bool operator>(Iter, Iter);
  friend bool operator<=(Iter, Iter);
  friend bool operator>=(Iter, Iter);
};

bool operator!=(Iter, long*);

std::reverse_iterator<Iter> l{Iter()};
std::reverse_iterator<long*> r{nullptr};

#if __cplusplus > 201703L
static_assert( std::random_access_iterator<Iter> );
static_assert( std::random_access_iterator<long*> );
#endif

bool b1 = l.base() != r.base();  // OK

bool b2 = l != r;


reviter.cc:50:13:   in 'constexpr' expansion of 'std::operator!=<Iter, long
int*>(l, r)'
/home/jwakely/gcc/10/include/c++/10.0.1/bits/stl_iterator.h:375:25: error: no
match for 'operator==' (operand types are
'std::reverse_iterator<Iter>::iterator_type' {aka 'Iter'} and
'std::reverse_iterator<long int*>::iterator_type' {aka 'long int*'})
  375 |     { return __x.base() == __y.base(); }
      |              ~~~~~~~~~~~^~~~~~~~~~~~~


The reverse_iterator's preconditions are met (both Iter and long* are random
access iterators) and so is the constraint for operator!=

Constraints: x.base() != y.base() is well-formed and convertible to bool.

But it fails because we define operator!= as !(l == r) which uses == on the
base iterator types, and they only support !=

I think the testcase should be valid for C++11 and later, as per
https://cplusplus.github.io/LWG/lwg-defects.html#280
(and also C++98 if we treat that as a DR).

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug libstdc++/94354] std::reverse_iterator comparison operators defined incorrectly
  2020-03-27 10:01 [Bug libstdc++/94354] New: std::reverse_iterator comparison operators defined incorrectly redi at gcc dot gnu.org
@ 2020-03-27 10:17 ` redi at gcc dot gnu.org
  2020-03-27 23:27 ` cvs-commit at gcc dot gnu.org
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: redi at gcc dot gnu.org @ 2020-03-27 10:17 UTC (permalink / raw)
  To: gcc-bugs

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

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Last reconfirmed|                            |2020-03-27
     Ever confirmed|0                           |1
           Assignee|unassigned at gcc dot gnu.org      |redi at gcc dot gnu.org
             Status|UNCONFIRMED                 |ASSIGNED

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
We also retain the pre-LWG280 homogeneous overloads:

  template<typename _Iterator>
    inline _GLIBCXX17_CONSTEXPR bool
    operator==(const reverse_iterator<_Iterator>& __x,
               const reverse_iterator<_Iterator>& __y)
    { return __x.base() == __y.base(); }

I don't have a demo, but this might be non-conforming for cases where we
compare reverse_iterator<T> and something convertible to that type.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug libstdc++/94354] std::reverse_iterator comparison operators defined incorrectly
  2020-03-27 10:01 [Bug libstdc++/94354] New: std::reverse_iterator comparison operators defined incorrectly redi at gcc dot gnu.org
  2020-03-27 10:17 ` [Bug libstdc++/94354] " redi at gcc dot gnu.org
@ 2020-03-27 23:27 ` cvs-commit at gcc dot gnu.org
  2020-03-27 23:44 ` redi at gcc dot gnu.org
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2020-03-27 23:27 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #2 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:

https://gcc.gnu.org/g:81a8d137c22953df2ea046466c62cd26c0dba103

commit r10-7434-g81a8d137c22953df2ea046466c62cd26c0dba103
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Mar 27 23:21:58 2020 +0000

    libstdc++: Add remaining C++20 changes to iterator adaptors

    This adds the missing parts of P0896R4 to reverse_iterator and
    move_iterator, so that they meet the C++20 requirements. This should be
    the last piece of P0896R4, meaning ranges support is now complete.

    The PR 94354 bug with reverse_iterator's comparisons is fixed for C++20
    only, but that change should be extended to C++11, C++14 and C++17 modes
    in stage 1.

            * include/bits/stl_iterator.h (reverse_iterator::iterator_concept)
            (reverse_iterator::iterator_category): Define for C++20.
            (reverse_iterator): Define comparison operators correctly for
C++20.
            (__normal_iterator): Add constraints to comparison operators for
C++20.
            (move_iterator::operator++(int)) [__cpp_lib_concepts]: Define new
            overload for input iterators.
            (move_iterator): Add constraints to comparison operators for C++20.
            Define operator<=> for C++20.
            * testsuite/24_iterators/move_iterator/input_iterator.cc: New test.
            * testsuite/24_iterators/move_iterator/move_only.cc: New test.
            * testsuite/24_iterators/move_iterator/rel_ops_c++20.cc: New test.
            * testsuite/24_iterators/reverse_iterator/rel_ops_c++20.cc: New
test.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug libstdc++/94354] std::reverse_iterator comparison operators defined incorrectly
  2020-03-27 10:01 [Bug libstdc++/94354] New: std::reverse_iterator comparison operators defined incorrectly redi at gcc dot gnu.org
  2020-03-27 10:17 ` [Bug libstdc++/94354] " redi at gcc dot gnu.org
  2020-03-27 23:27 ` cvs-commit at gcc dot gnu.org
@ 2020-03-27 23:44 ` redi at gcc dot gnu.org
  2020-05-27 20:59 ` cvs-commit at gcc dot gnu.org
  2020-05-27 20:59 ` redi at gcc dot gnu.org
  4 siblings, 0 replies; 6+ messages in thread
From: redi at gcc dot gnu.org @ 2020-03-27 23:44 UTC (permalink / raw)
  To: gcc-bugs

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

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Target Milestone|---                         |11.0

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug libstdc++/94354] std::reverse_iterator comparison operators defined incorrectly
  2020-03-27 10:01 [Bug libstdc++/94354] New: std::reverse_iterator comparison operators defined incorrectly redi at gcc dot gnu.org
                   ` (2 preceding siblings ...)
  2020-03-27 23:44 ` redi at gcc dot gnu.org
@ 2020-05-27 20:59 ` cvs-commit at gcc dot gnu.org
  2020-05-27 20:59 ` redi at gcc dot gnu.org
  4 siblings, 0 replies; 6+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2020-05-27 20:59 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #3 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:

https://gcc.gnu.org/g:979e89a9a94f66241fa8355e2b2e8f4a680c83e1

commit r11-672-g979e89a9a94f66241fa8355e2b2e8f4a680c83e1
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed May 27 21:58:56 2020 +0100

    libstdc++: Fix std::reverse_iterator comparisons (PR 94354)

    The std::reverse_iterator comparisons have always been implemented only
    in terms of equality and less than. In C++98 that made no difference for
    reasonable code, because when the underlying operators are the same type
    they are required to support all comparisons anyway.

    But since LWG 280 it's possible to compare reverse_iterator<X> and
    reverse_iterator<Y>, and comparisons between X and Y might not support
    the full set of equality and relational operators. This means that it
    matters whether we implement operator!= as x.base() != y.base() or
    !(x.base() == y.base()), and the current implementation is
    non-conforming.

    This was already fixed in GCC 10.1 for C++20, this change also fixes it
    for all other -std modes.

            PR libstdc++/94354
            * include/bits/stl_iterator.h (reverse_iterator): Fix comparison
            operators to use the correct operations on the underlying
            iterators.
            * testsuite/24_iterators/reverse_iterator/rel_ops.cc: New test.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug libstdc++/94354] std::reverse_iterator comparison operators defined incorrectly
  2020-03-27 10:01 [Bug libstdc++/94354] New: std::reverse_iterator comparison operators defined incorrectly redi at gcc dot gnu.org
                   ` (3 preceding siblings ...)
  2020-05-27 20:59 ` cvs-commit at gcc dot gnu.org
@ 2020-05-27 20:59 ` redi at gcc dot gnu.org
  4 siblings, 0 replies; 6+ messages in thread
From: redi at gcc dot gnu.org @ 2020-05-27 20:59 UTC (permalink / raw)
  To: gcc-bugs

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

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |FIXED
             Status|ASSIGNED                    |RESOLVED

--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Fixed for GCC 11

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-05-27 20:59 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-27 10:01 [Bug libstdc++/94354] New: std::reverse_iterator comparison operators defined incorrectly redi at gcc dot gnu.org
2020-03-27 10:17 ` [Bug libstdc++/94354] " redi at gcc dot gnu.org
2020-03-27 23:27 ` cvs-commit at gcc dot gnu.org
2020-03-27 23:44 ` redi at gcc dot gnu.org
2020-05-27 20:59 ` cvs-commit at gcc dot gnu.org
2020-05-27 20:59 ` redi at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).