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 | // const allocator_type& a); |
13 | |
14 | #include <vector> |
15 | #include <cassert> |
16 | #include <cstddef> |
17 | |
18 | #include "test_macros.h" |
19 | #include "test_iterators.h" |
20 | #include "test_allocator.h" |
21 | #include "min_allocator.h" |
22 | #include "asan_testing.h" |
23 | #if TEST_STD_VER >= 11 |
24 | #include "emplace_constructible.h" |
25 | #include "container_test_types.h" |
26 | #endif |
27 | |
28 | template <class C, class Iterator, class A> |
29 | TEST_CONSTEXPR_CXX20 void test(Iterator first, Iterator last, const A& a) { |
30 | C c(first, last, a); |
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 | |
39 | #if TEST_STD_VER >= 11 |
40 | |
41 | template <class T> |
42 | struct implicit_conv_allocator : min_allocator<T> { |
43 | TEST_CONSTEXPR implicit_conv_allocator(void*) {} |
44 | TEST_CONSTEXPR implicit_conv_allocator(const implicit_conv_allocator&) = default; |
45 | |
46 | template <class U> |
47 | TEST_CONSTEXPR implicit_conv_allocator(implicit_conv_allocator<U>) {} |
48 | }; |
49 | |
50 | #endif |
51 | |
52 | TEST_CONSTEXPR_CXX20 void basic_tests() { |
53 | { |
54 | int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 1, 0}; |
55 | int* an = a + sizeof(a) / sizeof(a[0]); |
56 | std::allocator<int> alloc; |
57 | test<std::vector<int> >(cpp17_input_iterator<const int*>(a), |
58 | cpp17_input_iterator<const int*>(an), alloc); |
59 | test<std::vector<int> >(forward_iterator<const int*>(a), |
60 | forward_iterator<const int*>(an), alloc); |
61 | test<std::vector<int> >(bidirectional_iterator<const int*>(a), |
62 | bidirectional_iterator<const int*>(an), alloc); |
63 | test<std::vector<int> >(random_access_iterator<const int*>(a), |
64 | random_access_iterator<const int*>(an), alloc); |
65 | test<std::vector<int> >(a, an, alloc); |
66 | } |
67 | #if TEST_STD_VER >= 11 |
68 | { |
69 | int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 1, 0}; |
70 | int* an = a + sizeof(a) / sizeof(a[0]); |
71 | min_allocator<int> alloc; |
72 | test<std::vector<int, min_allocator<int> > >( |
73 | cpp17_input_iterator<const int*>(a), cpp17_input_iterator<const int*>(an), alloc); |
74 | test<std::vector<int, min_allocator<int> > >( |
75 | forward_iterator<const int*>(a), forward_iterator<const int*>(an), |
76 | alloc); |
77 | test<std::vector<int, min_allocator<int> > >( |
78 | bidirectional_iterator<const int*>(a), |
79 | bidirectional_iterator<const int*>(an), alloc); |
80 | test<std::vector<int, min_allocator<int> > >( |
81 | random_access_iterator<const int*>(a), |
82 | random_access_iterator<const int*>(an), alloc); |
83 | test<std::vector<int, min_allocator<int> > >(a, an, alloc); |
84 | test<std::vector<int, implicit_conv_allocator<int> > >(a, an, nullptr); |
85 | } |
86 | { |
87 | int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 1, 0}; |
88 | int* an = a + sizeof(a) / sizeof(a[0]); |
89 | safe_allocator<int> alloc; |
90 | test<std::vector<int, safe_allocator<int> > >( |
91 | cpp17_input_iterator<const int*>(a), cpp17_input_iterator<const int*>(an), alloc); |
92 | test<std::vector<int, safe_allocator<int> > >( |
93 | forward_iterator<const int*>(a), forward_iterator<const int*>(an), alloc); |
94 | test<std::vector<int, safe_allocator<int> > >( |
95 | bidirectional_iterator<const int*>(a), bidirectional_iterator<const int*>(an), alloc); |
96 | test<std::vector<int, safe_allocator<int> > >( |
97 | random_access_iterator<const int*>(a), random_access_iterator<const int*>(an), alloc); |
98 | test<std::vector<int, safe_allocator<int> > >(a, an, alloc); |
99 | } |
100 | |
101 | // Regression test for https://github.com/llvm/llvm-project/issues/46841 |
102 | { |
103 | min_allocator<int> alloc; |
104 | std::vector<int, min_allocator<int> > v1({}, forward_iterator<const int*>{}, alloc); |
105 | std::vector<int, min_allocator<int> > v2(forward_iterator<const int*>{}, {}, alloc); |
106 | } |
107 | #endif |
108 | } |
109 | |
110 | TEST_CONSTEXPR_CXX20 void emplaceable_concept_tests() { |
111 | #if TEST_STD_VER >= 11 |
112 | int arr1[] = {42}; |
113 | int arr2[] = {1, 101, 42}; |
114 | { |
115 | using T = EmplaceConstructible<int>; |
116 | using It = forward_iterator<int*>; |
117 | using Alloc = std::allocator<T>; |
118 | Alloc a; |
119 | { |
120 | std::vector<T> v(It(arr1), It(std::end(arr1)), a); |
121 | assert(v[0].value == 42); |
122 | } |
123 | { |
124 | std::vector<T> v(It(arr2), It(std::end(arr2)), a); |
125 | assert(v[0].value == 1); |
126 | assert(v[1].value == 101); |
127 | assert(v[2].value == 42); |
128 | } |
129 | } |
130 | { |
131 | using T = EmplaceConstructibleAndMoveInsertable<int>; |
132 | using It = cpp17_input_iterator<int*>; |
133 | using Alloc = std::allocator<T>; |
134 | Alloc a; |
135 | { |
136 | std::vector<T> v(It(arr1), It(std::end(arr1)), a); |
137 | assert(v[0].copied == 0); |
138 | assert(v[0].value == 42); |
139 | } |
140 | { |
141 | std::vector<T> v(It(arr2), It(std::end(arr2)), a); |
142 | assert(v[0].value == 1); |
143 | assert(v[1].value == 101); |
144 | assert(v[2].copied == 0); |
145 | assert(v[2].value == 42); |
146 | } |
147 | } |
148 | #endif |
149 | } |
150 | |
151 | void test_ctor_under_alloc() { |
152 | #if TEST_STD_VER >= 11 |
153 | int arr1[] = {42}; |
154 | int arr2[] = {1, 101, 42}; |
155 | { |
156 | using C = TCT::vector<>; |
157 | using It = forward_iterator<int*>; |
158 | using Alloc = typename C::allocator_type; |
159 | Alloc a; |
160 | { |
161 | ExpectConstructGuard<int&> G(1); |
162 | C v(It(arr1), It(std::end(arr1)), a); |
163 | } |
164 | { |
165 | ExpectConstructGuard<int&> G(3); |
166 | C v(It(arr2), It(std::end(arr2)), a); |
167 | } |
168 | } |
169 | { |
170 | using C = TCT::vector<>; |
171 | using It = cpp17_input_iterator<int*>; |
172 | using Alloc = typename C::allocator_type; |
173 | Alloc a; |
174 | { |
175 | ExpectConstructGuard<int&> G(1); |
176 | C v(It(arr1), It(std::end(arr1)), a); |
177 | } |
178 | { |
179 | //ExpectConstructGuard<int&> G(3); |
180 | //C v(It(arr2), It(std::end(arr2)), a); |
181 | } |
182 | } |
183 | #endif |
184 | } |
185 | |
186 | TEST_CONSTEXPR_CXX20 bool test() { |
187 | basic_tests(); |
188 | emplaceable_concept_tests(); // See PR34898 |
189 | |
190 | return true; |
191 | } |
192 | |
193 | int main(int, char**) { |
194 | test(); |
195 | #if TEST_STD_VER > 17 |
196 | static_assert(test()); |
197 | #endif |
198 | test_ctor_under_alloc(); |
199 | |
200 | return 0; |
201 | } |
202 | |