[libcxx-commits] [PATCH] D129823: [libc++][ranges] Make range algorithms support proxy iterators

Konstantin Varlamov via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Thu Aug 11 19:39:44 PDT 2022


var-const added a comment.

@rupprecht Thanks a lot for the reproducer! The issue here is the `varlen_element`'s heuristics for creating an independent copy of the underlying data. Currently, it's done in the move constructor, on the assumption that insertion sort inside `std::sort` would necessarily call the move constructor. However, this assumption is no longer true.

Previously, the temporary element would be created like this (simplified):

  value_type temp = std::move(*iter);

`*iter` returns a prvalue `varlen_element`, which `std::move` then casts to an rvalue reference, which results in the move constructor being invoked.

After the rewrite, the call to `std::move(*iter)` is replaced by an internal function `__iter_move` which emulates C++20's `iter_move`. `__iter_move` notices that `*iter` returns a temporary and thus also returns a value; attempting to cast it to an rvalue reference would result in a dangling reference:

  // simplified
  template <class _Iter, enable_if_t<IterDerefReturnsPrvalue<_Iter>>
  typename _Iter::value_type __iter_move(_Iter& __iter) {
    return *__iter;
  }

Due to mandatory copy elision, the move constructor is no longer invoked:

  value_type temp = __iter_move(*iter);

Instead, the result of calling `*iter` is stored right in `temp`, with no copying or moving involved.

Since there was no call to the move constructor, now two `varlen_element`s are shallow copies of each other, sharing a pointer to the same underlying data. Thus, the value of the temporary changes when the value of the original iterator from which it was created changes; that's how the repro case ends up with two `2439` elements.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129823/new/

https://reviews.llvm.org/D129823



More information about the libcxx-commits mailing list