Commit 9149ae09 authored by Christian Sigg's avatar Christian Sigg
Browse files

Support value-typed references in iterator facade's operator->()

Add a PointerProxy similar to the existing iterator_facade_base::ReferenceProxy and return it from the arrow operator. This prevents iterator facades with a reference type that is not a true reference to take the address of a temporary.

Forward the reference type of the mapped_iterator to the iterator adaptor which in turn forwards it to the iterator facade. This fixes mlir::op_iterator::operator->() to take the address of a temporary.

Make some polishing changes to op_iterator and op_filter_iterator.

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D109490
parent 49c519a8
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -272,13 +272,15 @@ template <typename T> auto drop_begin(T &&RangeOrContainer, size_t N = 1) {
// be applied whenever operator* is invoked on the iterator.

template <typename ItTy, typename FuncTy,
          typename FuncReturnTy =
          typename ReferenceTy =
              decltype(std::declval<FuncTy>()(*std::declval<ItTy>()))>
class mapped_iterator
    : public iterator_adaptor_base<
          mapped_iterator<ItTy, FuncTy>, ItTy,
          typename std::iterator_traits<ItTy>::iterator_category,
             typename std::remove_reference<FuncReturnTy>::type> {
          std::remove_reference_t<ReferenceTy>,
          typename std::iterator_traits<ItTy>::difference_type,
          std::remove_reference_t<ReferenceTy> *, ReferenceTy> {
public:
  mapped_iterator(ItTy U, FuncTy F)
    : mapped_iterator::iterator_adaptor_base(std::move(U)), F(std::move(F)) {}
@@ -287,7 +289,7 @@ public:

  const FuncTy &getFunction() const { return F; }

  FuncReturnTy operator*() const { return F(*this->I); }
  ReferenceTy operator*() const { return F(*this->I); }

private:
  FuncTy F;
+23 −5
Original line number Diff line number Diff line
@@ -95,6 +95,22 @@ protected:
    operator ReferenceT() const { return *I; }
  };

  /// A proxy object for computing a pointer via indirecting a copy of a
  /// reference. This is used in APIs which need to produce a pointer but for
  /// which the reference might be a temporary. The proxy preserves the
  /// reference internally and exposes the pointer via a arrow operator.
  class PointerProxy {
    friend iterator_facade_base;

    ReferenceT R;

    template <typename RefT>
    PointerProxy(RefT &&R) : R(std::forward<RefT>(R)) {}

  public:
    PointerT operator->() const { return &R; }
  };

public:
  DerivedT operator+(DifferenceTypeT n) const {
    static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value,
@@ -172,19 +188,21 @@ public:
    return !(static_cast<const DerivedT &>(*this) < RHS);
  }

  PointerT operator->() { return &static_cast<DerivedT *>(this)->operator*(); }
  PointerT operator->() const {
    return &static_cast<const DerivedT *>(this)->operator*();
  PointerProxy operator->() {
    return static_cast<DerivedT *>(this)->operator*();
  }
  PointerProxy operator->() const {
    return static_cast<const DerivedT *>(this)->operator*();
  }
  ReferenceProxy operator[](DifferenceTypeT n) {
    static_assert(IsRandomAccess,
                  "Subscripting is only defined for random access iterators.");
    return ReferenceProxy(static_cast<DerivedT *>(this)->operator+(n));
    return static_cast<DerivedT *>(this)->operator+(n);
  }
  ReferenceProxy operator[](DifferenceTypeT n) const {
    static_assert(IsRandomAccess,
                  "Subscripting is only defined for random access iterators.");
    return ReferenceProxy(static_cast<const DerivedT *>(this)->operator+(n));
    return static_cast<const DerivedT *>(this)->operator+(n);
  }
};

+2 −4
Original line number Diff line number Diff line
@@ -52,7 +52,6 @@ class PredecessorIterator final
  static Block *unwrap(BlockOperand &value);

public:
  using reference = Block *;

  /// Initializes the operand type iterator to the specified operand iterator.
  PredecessorIterator(ValueUseIterator<BlockOperand> it)
@@ -151,7 +150,7 @@ public:
                                                                &filter) {}

  /// Allow implicit conversion to the underlying iterator.
  operator IteratorT() const { return this->wrapped(); }
  operator const IteratorT &() const { return this->wrapped(); }
};

/// This class provides iteration over the held operations of a block for a
@@ -163,7 +162,6 @@ class op_iterator
  static OpT unwrap(Operation &op) { return cast<OpT>(op); }

public:
  using reference = OpT;

  /// Initializes the iterator to the specified filter iterator.
  op_iterator(op_filter_iterator<OpT, IteratorT> it)
@@ -171,7 +169,7 @@ public:
                              OpT (*)(Operation &)>(it, &unwrap) {}

  /// Allow implicit conversion to the underlying block iterator.
  operator IteratorT() const { return this->wrapped(); }
  operator const IteratorT &() const { return this->wrapped(); }
};
} // end namespace detail
} // end namespace mlir
+0 −6
Original line number Diff line number Diff line
@@ -299,9 +299,6 @@ public:

    /// Initializes the float element iterator to the specified iterator.
    FloatElementIterator(const llvm::fltSemantics &smt, IntElementIterator it);

  public:
    using reference = APFloat;
  };

  /// Iterator for walking over complex APFloat values.
@@ -314,9 +311,6 @@ public:
    /// Initializes the float element iterator to the specified iterator.
    ComplexFloatElementIterator(const llvm::fltSemantics &smt,
                                ComplexIntElementIterator it);

  public:
    using reference = std::complex<APFloat>;
  };

  //===--------------------------------------------------------------------===//
+0 −2
Original line number Diff line number Diff line
@@ -128,8 +128,6 @@ class ValueTypeIterator final
  static Type unwrap(Value value) { return value.getType(); }

public:
  using reference = Type;

  /// Provide a const dereference method.
  Type operator*() const { return unwrap(*this->I); }

Loading