<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/56741>56741</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            `std::copy` forwards to `memmove` in too many cases
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            libc++
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          philnik777
      </td>
    </tr>
</table>

<pre>
    `std::copy` forwards to `memmove` with a `move_iterator` even if the type isn't `trivially_move_assignable`.

Here is a reproducer:
```c++

struct TriviallyCopyableNotTriviallyMovable {
  bool* move_assigned_;
  TEST_CONSTEXPR_CXX20 TriviallyCopyableNotTriviallyMovable() = default;
  TEST_CONSTEXPR_CXX20 TriviallyCopyableNotTriviallyMovable(bool* move_assigned) : move_assigned_(move_assigned) {}
  TEST_CONSTEXPR_CXX20 TriviallyCopyableNotTriviallyMovable(const TriviallyCopyableNotTriviallyMovable&) = default;
  TEST_CONSTEXPR_CXX20 TriviallyCopyableNotTriviallyMovable(TriviallyCopyableNotTriviallyMovable&&) = default;

  TEST_CONSTEXPR_CXX20 TriviallyCopyableNotTriviallyMovable&
  operator=(const TriviallyCopyableNotTriviallyMovable&) = default;
  TEST_CONSTEXPR_CXX20 TriviallyCopyableNotTriviallyMovable& operator=(TriviallyCopyableNotTriviallyMovable&&) {
    *move_assigned_ = true;
    return *this;
  }
};

static_assert(std::is_trivially_copy_assignable<TriviallyCopyableNotTriviallyMovable>::value, "");
static_assert(!std::is_trivially_move_assignable<TriviallyCopyableNotTriviallyMovable>::value, "");

TEST_CONSTEXPR_CXX20 bool test_move() {
  bool move_assigned[10] {};
  TriviallyCopyableNotTriviallyMovable from[10]{};
  TriviallyCopyableNotTriviallyMovable to[10]{
      {move_assigned + 0},
      {move_assigned + 1},
      {move_assigned + 2},
      {move_assigned + 3},
      {move_assigned + 4},
      {move_assigned + 5},
      {move_assigned + 6},
      {move_assigned + 7},
      {move_assigned + 8},
      {move_assigned + 9}};

  std::copy(std::begin(from), std::end(from), std::begin(to));

  struct IsMoveAssigned {
    TEST_CONSTEXPR_CXX20 bool operator()(bool b) { return b; }
  };

  assert(std::all_of(std::begin(move_assigned), std::end(move_assigned), IsMoveAssigned()));

  return true;
}

```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzNVk2P2jAQ_TXOxSpyHPJ1yIGPXbWHbqvuHvaGktiAW4OR7bDi33ccSAiQVbMVlSpZkHieZ54nM88uFDtkKCLGMhRMYJRqd4B3vFT6LdfMYKswvG_4ZqP23FnehF3jvJ6EmYWwXOdWaWfie77FYontmmN72HEszBbR2Dqw1WIvcikPi3pZboxYbfNCOp8jROaITI6_n7l2CyGE5jutWFVy7bgdIRE5jhLRqRudhcbqqrT4pQk0g624AE_KtnNf1d5NYRSflmJcKCURneAOLc4WKGgBLw_PL4vZt6fnl4fX7z8Ws9dXSgZFQTRBNMUomGPGl3kl7Z289lI-hrrZB01uUbD5eH4PIqXammEZRzT6N7kYHPzd-HdgETU-1O7UDcH8v0hPdMXog9k6dwnGUHCXpVWzhZ7jHaoYmtZWeuvQdi1Mx9SWnHsIrjo3t6J0nrm2wLJVI2EWZ91w0tTVjWA2aDfBw9HXPpdAlc6AGq1H2rK4jo-o30_hWrruR-H42_ulXbdjy42twzeicilgV1IQTn2CwnnT6Z1SGiKOS602jYu_82BVd31bG64IphdMIRNTTFwEOvsjzh-IowNxwUDceCAuHIiLBuLigbhkIC51uJvmw_jy8O-0X8FXAg7wpC4IKFao3NbGt-wdS7MKisBZrmvcxasP6i8GyoVPWobdSnm_EVo9q_vgdBji4tQTjfwUEBR3Drm-bd_KDZTwQi37MnB9hvakog9yucWGcm9STsQv9PQsmZeXH49nfhQmSZRQ4nssC1gapLlnhZX8g7c5ASGVwpt8e8BlbrjxKi2ztbU741zQRxgruPFVxah0n_pRyn3z9wmuZz95CSl8FMZU3MBDGMVj31tnnDBGfBax0g-ZD4Wy9KOCpGnMkjJhLPJkXnBpMtAJUEIpiuZCB7IYzj2RUUIpiWlEyTjw0xHxwyCkY5oG4TIgSYzGhG9yIUeOyEjplaezmlNRrQwYpTDWnI2n78LreOA_r-xa6Wy3FnIrfsVx7NU7yGr6vwE5L2jS">