107 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++0310 11// <algorithm>12 13// We optimize std::copy(_backward) and std::move(_backward) into memmove14// when the iterator is trivial and contiguous and the type in question15// is also trivially (copyable, movable). This test verifies that the16// optimization never eliminates an actually non-trivial copy or move.17 18#include <algorithm>19#include <iterator>20#include <cassert>21 22#include "test_macros.h"23#include "test_iterators.h"24 25struct TMBNTC {26 int *p;27 constexpr TMBNTC(int& copies) : p(&copies) {}28 constexpr TMBNTC(const TMBNTC&) = default;29 TEST_CONSTEXPR_CXX14 TMBNTC& operator=(TMBNTC&&) = default;30 TEST_CONSTEXPR_CXX14 TMBNTC& operator=(const TMBNTC&) { ++*p; return *this; }31};32 33TEST_CONSTEXPR_CXX20 bool34test_trivial_moveassign_but_no_trivial_copyassign()35{36 int copies = 0;37 TMBNTC ia[] = { copies, copies, copies, copies };38 TMBNTC ib[] = { copies, copies, copies, copies };39 std::copy(ia, ia+4, ib);40 assert(copies == 4);41 copies = 0;42 std::copy_backward(ia, ia+4, ib+4);43 assert(copies == 4);44 45 copies = 0;46 std::copy(std::make_move_iterator(ia), std::make_move_iterator(ia+4), ib);47 assert(copies == 0);48 std::copy_backward(std::make_move_iterator(ia), std::make_move_iterator(ia+4), ib+4);49 assert(copies == 0);50 51 std::move(ia, ia+4, ib);52 assert(copies == 0);53 std::move_backward(ia, ia+4, ib+4);54 assert(copies == 0);55 56 return true;57}58 59struct TCBNTM {60 int *p;61 constexpr TCBNTM(int& moves) : p(&moves) {}62 constexpr TCBNTM(const TCBNTM&) = default;63 TEST_CONSTEXPR_CXX14 TCBNTM& operator=(TCBNTM&&) { ++*p; return *this; }64 TEST_CONSTEXPR_CXX14 TCBNTM& operator=(const TCBNTM&) = default;65};66 67TEST_CONSTEXPR_CXX20 bool68test_trivial_copyassign_but_no_trivial_moveassign()69{70 int moves = 0;71 TCBNTM ia[] = { moves, moves, moves, moves };72 TCBNTM ib[] = { moves, moves, moves, moves };73 std::move(ia, ia+4, ib);74 assert(moves == 4);75 moves = 0;76 std::move_backward(ia, ia+4, ib+4);77 assert(moves == 4);78 79 moves = 0;80 std::copy(std::make_move_iterator(ia), std::make_move_iterator(ia+4), ib);81 assert(moves == 4);82 moves = 0;83 std::copy_backward(std::make_move_iterator(ia), std::make_move_iterator(ia+4), ib+4);84 assert(moves == 4);85 86 moves = 0;87 std::copy(ia, ia+4, ib);88 assert(moves == 0);89 std::copy_backward(ia, ia+4, ib+4);90 assert(moves == 0);91 92 return true;93}94 95int main(int, char**)96{97 test_trivial_moveassign_but_no_trivial_copyassign();98 test_trivial_copyassign_but_no_trivial_moveassign();99 100#if TEST_STD_VER > 17101 static_assert(test_trivial_moveassign_but_no_trivial_copyassign());102 static_assert(test_trivial_copyassign_but_no_trivial_moveassign());103#endif104 105 return 0;106}107