This is an archive of the discontinued LLVM Phabricator instance.

[libc++] NFCI: Remove code duplication and obsolete declarations in wrap_iter
ClosedPublic

Authored by ldionne on Jun 28 2021, 9:31 AM.

Diff Detail

Event Timeline

ldionne requested review of this revision.Jun 28 2021, 9:31 AM
ldionne created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptJun 28 2021, 9:31 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript

@Quuxplusone You suggested this cleanup back in D104669 IIRC.

If buildkite is happy, I'm happy.

libcxx/include/__iterator/wrap_iter.h
221–227

Could this operator+ become a hidden friend of __wrap_iter?
I'm not asking for all the relational operators to become hidden friends, because they're parameterized on two types, _Iter1 and _Iter2 (and I don't understand the ramifications/rationale of that). But for this operator+, the transformation to hidden friend should be pretty trivial.

ldionne updated this revision to Diff 354982.Jun 28 2021, 12:14 PM

Fix build in C++03 mode.

ldionne accepted this revision.Jun 29 2021, 7:50 AM

Fixed and verified the modular build locally. We were missing an include of __algorithm/move.h in inplace_merge.h.

libcxx/include/__iterator/wrap_iter.h
221–227

I think I'd rather be consistent and have them all be non-member functions.

This revision is now accepted and ready to land.Jun 29 2021, 7:50 AM
This revision was landed with ongoing or failed builds.Jun 29 2021, 7:51 AM
This revision was automatically updated to reflect the committed changes.
bgraur added a subscriber: bgraur.Jul 10 2021, 2:33 AM

Hi Louis,

This patch introduces an error when std::rel_ops are used.
Here's a small reproducer:

#include <utility> // for std::rel_ops.
#include <vector>

using namespace std::rel_ops;

struct T;
void fn() {
  std::vector<T>::const_iterator a;
  for (std::vector<T>::const_iterator i; i >= a;)
    ;
}

The compilation result:

repro.cc:9:44: error: use of overloaded operator '>=' is ambiguous (with operand types 'std::vector<T>::const_iterator' (aka '__wrap_iter<const T *>') and 'std::vector<T>::const_iterator' (aka '__wrap_iter<const T *>'))
  for (std::vector<T>::const_iterator i; i >= a;)
                                         ~ ^  ~
/google/src/cloud/bgraur/cherrypick/google3/third_party/crosstool/v18/llvm_unstable/toolchain/bin/../include/c++/v1/__utility/rel_ops.h:56:1: note: candidate function [with _Tp = std::__wrap_iter<const T *>]
operator>=(const _Tp& __x, const _Tp& __y)
^
/google/src/cloud/bgraur/cherrypick/google3/third_party/crosstool/v18/llvm_unstable/toolchain/bin/../include/c++/v1/__iterator/wrap_iter.h:201:6: note: candidate function [with _Iter1 = const T *, _Iter2 = const T *]
bool operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
     ^
1 error generated.

Could you please take a look?

Amusing comment in GNU libstdc++ about this.
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/stl_iterator.h#L1081-L1087

It appears that the state-of-the-art fix is that we need to provide both

template <class _Iter1>
bool operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT
{
    return !(__x == __y);
}

template <class _Iter1, class _Iter2>
bool operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
{
    return !(__x == __y);
}

and so on. The single-_Iter1 versions are precisely the bits @ldionne removed. I hadn't even noticed they were there! We should put them back, plus a test case.