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 | // <vector> |
10 | |
11 | // template <class InputIter> vector(InputIter first, InputIter last); |
12 | |
13 | #include <vector> |
14 | #include <cassert> |
15 | #include <cstddef> |
16 | |
17 | #include "test_macros.h" |
18 | #include "test_iterators.h" |
19 | #include "test_allocator.h" |
20 | #include "min_allocator.h" |
21 | #include "asan_testing.h" |
22 | #if TEST_STD_VER >= 11 |
23 | #include "emplace_constructible.h" |
24 | #include "container_test_types.h" |
25 | #endif |
26 | |
27 | template <class C, class Iterator> |
28 | TEST_CONSTEXPR_CXX20 void test(Iterator first, Iterator last) { |
29 | { |
30 | C c(first, last); |
31 | LIBCPP_ASSERT(c.__invariants()); |
32 | assert(c.size() == static_cast<std::size_t>(std::distance(first, last))); |
33 | LIBCPP_ASSERT(is_contiguous_container_asan_correct(c)); |
34 | for (typename C::const_iterator i = c.cbegin(), e = c.cend(); i != e; |
35 | ++i, ++first) |
36 | assert(*i == *first); |
37 | } |
38 | // Test with an empty range |
39 | { |
40 | C c(first, first); |
41 | LIBCPP_ASSERT(c.__invariants()); |
42 | assert(c.empty()); |
43 | LIBCPP_ASSERT(is_contiguous_container_asan_correct(c)); |
44 | } |
45 | } |
46 | |
47 | TEST_CONSTEXPR_CXX20 void basic_test_cases() { |
48 | int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 1, 0}; |
49 | int* an = a + sizeof(a) / sizeof(a[0]); |
50 | test<std::vector<int> >(cpp17_input_iterator<const int*>(a), |
51 | cpp17_input_iterator<const int*>(an)); |
52 | test<std::vector<int> >(forward_iterator<const int*>(a), |
53 | forward_iterator<const int*>(an)); |
54 | test<std::vector<int> >(bidirectional_iterator<const int*>(a), |
55 | bidirectional_iterator<const int*>(an)); |
56 | test<std::vector<int> >(random_access_iterator<const int*>(a), |
57 | random_access_iterator<const int*>(an)); |
58 | test<std::vector<int> >(a, an); |
59 | |
60 | test<std::vector<int, limited_allocator<int, 63> > >( |
61 | cpp17_input_iterator<const int*>(a), cpp17_input_iterator<const int*>(an)); |
62 | // Add 1 for implementations that dynamically allocate a container proxy. |
63 | test<std::vector<int, limited_allocator<int, 18 + 1> > >( |
64 | forward_iterator<const int*>(a), forward_iterator<const int*>(an)); |
65 | test<std::vector<int, limited_allocator<int, 18 + 1> > >( |
66 | bidirectional_iterator<const int*>(a), |
67 | bidirectional_iterator<const int*>(an)); |
68 | test<std::vector<int, limited_allocator<int, 18 + 1> > >( |
69 | random_access_iterator<const int*>(a), |
70 | random_access_iterator<const int*>(an)); |
71 | test<std::vector<int, limited_allocator<int, 18 + 1> > >(a, an); |
72 | #if TEST_STD_VER >= 11 |
73 | test<std::vector<int, min_allocator<int> > >(cpp17_input_iterator<const int*>(a), |
74 | cpp17_input_iterator<const int*>(an)); |
75 | test<std::vector<int, min_allocator<int> > >( |
76 | forward_iterator<const int*>(a), forward_iterator<const int*>(an)); |
77 | test<std::vector<int, min_allocator<int> > >( |
78 | bidirectional_iterator<const int*>(a), |
79 | bidirectional_iterator<const int*>(an)); |
80 | test<std::vector<int, min_allocator<int> > >( |
81 | random_access_iterator<const int*>(a), |
82 | random_access_iterator<const int*>(an)); |
83 | test<std::vector<int> >(a, an); |
84 | test<std::vector<int, safe_allocator<int> > >( |
85 | cpp17_input_iterator<const int*>(a), cpp17_input_iterator<const int*>(an)); |
86 | test<std::vector<int, safe_allocator<int> > >(forward_iterator<const int*>(a), forward_iterator<const int*>(an)); |
87 | test<std::vector<int, safe_allocator<int> > >( |
88 | bidirectional_iterator<const int*>(a), bidirectional_iterator<const int*>(an)); |
89 | test<std::vector<int, safe_allocator<int> > >( |
90 | random_access_iterator<const int*>(a), random_access_iterator<const int*>(an)); |
91 | |
92 | // Regression test for https://github.com/llvm/llvm-project/issues/46841 |
93 | { |
94 | std::vector<int> v1({}, forward_iterator<const int*>{}); |
95 | std::vector<int> v2(forward_iterator<const int*>{}, {}); |
96 | } |
97 | #endif |
98 | } |
99 | |
100 | TEST_CONSTEXPR_CXX20 void emplaceable_concept_tests() { |
101 | #if TEST_STD_VER >= 11 |
102 | int arr1[] = {42}; |
103 | int arr2[] = {1, 101, 42}; |
104 | { |
105 | using T = EmplaceConstructible<int>; |
106 | using It = forward_iterator<int*>; |
107 | { |
108 | std::vector<T> v(It(arr1), It(std::end(arr1))); |
109 | assert(v[0].value == 42); |
110 | } |
111 | { |
112 | std::vector<T> v(It(arr2), It(std::end(arr2))); |
113 | assert(v[0].value == 1); |
114 | assert(v[1].value == 101); |
115 | assert(v[2].value == 42); |
116 | } |
117 | } |
118 | { |
119 | using T = EmplaceConstructibleAndMoveInsertable<int>; |
120 | using It = cpp17_input_iterator<int*>; |
121 | { |
122 | std::vector<T> v(It(arr1), It(std::end(arr1))); |
123 | assert(v[0].copied == 0); |
124 | assert(v[0].value == 42); |
125 | } |
126 | { |
127 | std::vector<T> v(It(arr2), It(std::end(arr2))); |
128 | //assert(v[0].copied == 0); |
129 | assert(v[0].value == 1); |
130 | //assert(v[1].copied == 0); |
131 | assert(v[1].value == 101); |
132 | assert(v[2].copied == 0); |
133 | assert(v[2].value == 42); |
134 | } |
135 | } |
136 | #endif |
137 | } |
138 | |
139 | void test_ctor_under_alloc() { |
140 | #if TEST_STD_VER >= 11 |
141 | int arr1[] = {42}; |
142 | int arr2[] = {1, 101, 42}; |
143 | { |
144 | using C = TCT::vector<>; |
145 | using It = forward_iterator<int*>; |
146 | { |
147 | ExpectConstructGuard<int&> G(1); |
148 | C v(It(arr1), It(std::end(arr1))); |
149 | } |
150 | { |
151 | ExpectConstructGuard<int&> G(3); |
152 | C v(It(arr2), It(std::end(arr2))); |
153 | } |
154 | } |
155 | { |
156 | using C = TCT::vector<>; |
157 | using It = cpp17_input_iterator<int*>; |
158 | { |
159 | ExpectConstructGuard<int&> G(1); |
160 | C v(It(arr1), It(std::end(arr1))); |
161 | } |
162 | { |
163 | //ExpectConstructGuard<int&> G(3); |
164 | //C v(It(arr2), It(std::end(arr2)), a); |
165 | } |
166 | } |
167 | #endif |
168 | } |
169 | |
170 | // In C++03, you can't instantiate a template with a local type. |
171 | struct B1 { int x; }; |
172 | struct B2 { int y; }; |
173 | struct Der : B1, B2 { int z; }; |
174 | |
175 | // Initialize a vector with a different value type. |
176 | TEST_CONSTEXPR_CXX20 void test_ctor_with_different_value_type() { |
177 | { |
178 | // Make sure initialization is performed with each element value, not with |
179 | // a memory blob. |
180 | float array[3] = {0.0f, 1.0f, 2.0f}; |
181 | TEST_DIAGNOSTIC_PUSH |
182 | TEST_MSVC_DIAGNOSTIC_IGNORED(4244) // conversion from 'float' to 'int', possible loss of data |
183 | std::vector<int> v(array, array + 3); |
184 | TEST_DIAGNOSTIC_POP |
185 | assert(v[0] == 0); |
186 | assert(v[1] == 1); |
187 | assert(v[2] == 2); |
188 | } |
189 | { |
190 | Der z; |
191 | Der *array[1] = { &z }; |
192 | // Though the types Der* and B2* are very similar, initialization still cannot |
193 | // be done with `memcpy`. |
194 | std::vector<B2*> v(array, array + 1); |
195 | assert(v[0] == &z); |
196 | } |
197 | { |
198 | // Though the types are different, initialization can be done with `memcpy`. |
199 | std::int32_t array[1] = { -1 }; |
200 | std::vector<std::uint32_t> v(array, array + 1); |
201 | assert(v[0] == 4294967295U); |
202 | } |
203 | } |
204 | |
205 | TEST_CONSTEXPR_CXX20 bool tests() { |
206 | basic_test_cases(); |
207 | emplaceable_concept_tests(); // See PR34898 |
208 | test_ctor_with_different_value_type(); |
209 | |
210 | return true; |
211 | } |
212 | |
213 | int main(int, char**) |
214 | { |
215 | tests(); |
216 | test_ctor_under_alloc(); |
217 | #if TEST_STD_VER > 17 |
218 | static_assert(tests()); |
219 | #endif |
220 | return 0; |
221 | } |
222 | |