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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14
10 
11 // <memory>
12 
13 // template <class InputIt, class ForwardIt>
14 // ForwardIt uninitialized_move(InputIt, InputIt, ForwardIt);
15 
16 #include <memory>
17 #include <cstdlib>
18 #include <cassert>
19 
20 #include "test_macros.h"
21 #include "test_iterators.h"
22 #include "../overload_compare_iterator.h"
23 
24 struct Counted {
25   static int count;
26   static int constructed;
resetCounted27   static void reset() { count = constructed =  0; }
CountedCounted28   explicit Counted(int&& x) : value(x) { x = 0; ++count; ++constructed; }
CountedCounted29   Counted(Counted const&) { assert(false); }
~CountedCounted30   ~Counted() { assert(count > 0); --count; }
31   friend void operator&(Counted) = delete;
32   int value;
33 };
34 int Counted::count = 0;
35 int Counted::constructed = 0;
36 
37 struct ThrowsCounted {
38   static int count;
39   static int constructed;
40   static int throw_after;
resetThrowsCounted41   static void reset() { throw_after = count = constructed =  0; }
ThrowsCountedThrowsCounted42   explicit ThrowsCounted(int&& x) {
43       ++constructed;
44       if (throw_after > 0 && --throw_after == 0) {
45           TEST_THROW(1);
46       }
47       ++count;
48       x = 0;
49   }
ThrowsCountedThrowsCounted50   ThrowsCounted(ThrowsCounted const&) { assert(false); }
~ThrowsCountedThrowsCounted51   ~ThrowsCounted() { assert(count > 0); --count; }
52   friend void operator&(ThrowsCounted) = delete;
53 };
54 int ThrowsCounted::count = 0;
55 int ThrowsCounted::constructed = 0;
56 int ThrowsCounted::throw_after = 0;
57 
test_ctor_throws()58 void test_ctor_throws()
59 {
60 #ifndef TEST_HAS_NO_EXCEPTIONS
61     using It = forward_iterator<ThrowsCounted*>;
62     const int N = 5;
63     int values[N] = {1, 2, 3, 4, 5};
64     alignas(ThrowsCounted) char pool[sizeof(ThrowsCounted)*N] = {};
65     ThrowsCounted* p = (ThrowsCounted*)pool;
66     try {
67         ThrowsCounted::throw_after = 4;
68         std::uninitialized_move(values, values + N, It(p));
69         assert(false);
70     } catch (...) {}
71     assert(ThrowsCounted::count == 0);
72     assert(ThrowsCounted::constructed == 4); // forth construction throws
73     assert(values[0] == 0);
74     assert(values[1] == 0);
75     assert(values[2] == 0);
76     assert(values[3] == 4);
77     assert(values[4] == 5);
78 #endif
79 }
80 
test_counted()81 void test_counted()
82 {
83     using It = cpp17_input_iterator<int*>;
84     using FIt = forward_iterator<Counted*>;
85     const int N = 5;
86     int values[N] = {1, 2, 3, 4, 5};
87     alignas(Counted) char pool[sizeof(Counted)*N] = {};
88     Counted* p = (Counted*)pool;
89     auto ret = std::uninitialized_move(It(values), It(values + 1), FIt(p));
90     assert(ret == FIt(p +1));
91     assert(Counted::constructed == 1);
92     assert(Counted::count == 1);
93     assert(p[0].value == 1);
94     assert(values[0] == 0);
95     ret = std::uninitialized_move(It(values+1), It(values+N), FIt(p+1));
96     assert(ret == FIt(p + N));
97     assert(Counted::count == 5);
98     assert(Counted::constructed == 5);
99     assert(p[1].value == 2);
100     assert(p[2].value == 3);
101     assert(p[3].value == 4);
102     assert(p[4].value == 5);
103     assert(values[1] == 0);
104     assert(values[2] == 0);
105     assert(values[3] == 0);
106     assert(values[4] == 0);
107     std::destroy(p, p+N);
108     assert(Counted::count == 0);
109 }
110 
main(int,char **)111 int main(int, char**) {
112     test_counted();
113     test_ctor_throws();
114 
115     // Test with an iterator that overloads operator== and operator!= as the input and output iterators
116     {
117         using T = int;
118         using Iterator = overload_compare_iterator<T*>;
119         const int N = 5;
120 
121         // input
122         {
123             char pool[sizeof(T) * N] = {0};
124             T* p = reinterpret_cast<T*>(pool);
125             T array[N] = {1, 2, 3, 4, 5};
126             std::uninitialized_move(Iterator(array), Iterator(array + N), p);
127             for (int i = 0; i != N; ++i) {
128                 assert(array[i] == p[i]);
129             }
130         }
131 
132         // output
133         {
134             char pool[sizeof(T) * N] = {0};
135             T* p = reinterpret_cast<T*>(pool);
136             T array[N] = {1, 2, 3, 4, 5};
137             std::uninitialized_move(array, array + N, Iterator(p));
138             for (int i = 0; i != N; ++i) {
139                 assert(array[i] == p[i]);
140             }
141         }
142     }
143 
144   return 0;
145 }
146