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 // <string>
10
11 // template<class InputIterator>
12 // iterator insert(const_iterator p, InputIterator first, InputIterator last); // constexpr since C++20
13
14 #include <string>
15 #include <cassert>
16
17 #include "test_macros.h"
18 #include "test_iterators.h"
19 #include "min_allocator.h"
20 #include "asan_testing.h"
21
22 template <class S, class It>
test(S s,typename S::difference_type pos,It first,It last,S expected)23 TEST_CONSTEXPR_CXX20 void test(S s, typename S::difference_type pos, It first, It last, S expected) {
24 typename S::const_iterator p = s.cbegin() + pos;
25 typename S::iterator i = s.insert(p, first, last);
26 LIBCPP_ASSERT(s.__invariants());
27 assert(i - s.begin() == pos);
28 assert(s == expected);
29 LIBCPP_ASSERT(is_string_asan_correct(s));
30 }
31
32 #ifndef TEST_HAS_NO_EXCEPTIONS
33 struct Widget {
operator charWidget34 operator char() const { throw 42; }
35 };
36
37 template <class S, class It>
test_exceptions(S s,typename S::difference_type pos,It first,It last)38 TEST_CONSTEXPR_CXX20 void test_exceptions(S s, typename S::difference_type pos, It first, It last) {
39 typename S::const_iterator p = s.cbegin() + pos;
40
41 S original = s;
42 typename S::iterator begin = s.begin();
43 typename S::iterator end = s.end();
44
45 try {
46 s.insert(p, first, last);
47 assert(false);
48 } catch (...) {
49 }
50
51 // Part of "no effects" is that iterators and pointers
52 // into the string must not have been invalidated.
53 LIBCPP_ASSERT(s.__invariants());
54 assert(s == original);
55 assert(s.begin() == begin);
56 assert(s.end() == end);
57 }
58 #endif
59
60 template <class S>
test_string()61 TEST_CONSTEXPR_CXX20 void test_string() {
62 const char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
63 test(S(), 0, s, s, S());
64 test(S(), 0, s, s + 1, S("A"));
65 test(S(), 0, s, s + 10, S("ABCDEFGHIJ"));
66 test(S(), 0, s, s + 52, S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
67
68 test(S("12345"), 0, s, s, S("12345"));
69 test(S("12345"), 1, s, s + 1, S("1A2345"));
70 test(S("12345"), 4, s, s + 10, S("1234ABCDEFGHIJ5"));
71 test(S("12345"), 5, s, s + 52, S("12345ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
72
73 test(S("1234567890"), 0, s, s, S("1234567890"));
74 test(S("1234567890"), 1, s, s + 1, S("1A234567890"));
75 test(S("1234567890"), 10, s, s + 10, S("1234567890ABCDEFGHIJ"));
76 test(S("1234567890"), 8, s, s + 52, S("12345678ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz90"));
77
78 test(S("12345678901234567890"), 3, s, s, S("12345678901234567890"));
79 test(S("12345678901234567890"), 3, s, s + 1, S("123A45678901234567890"));
80 test(S("12345678901234567890"), 15, s, s + 10, S("123456789012345ABCDEFGHIJ67890"));
81 test(S("12345678901234567890"),
82 20,
83 s,
84 s + 52,
85 S("12345678901234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
86
87 test(S(), 0, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), S());
88 test(S(), 0, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s + 1), S("A"));
89 test(S(), 0, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s + 10), S("ABCDEFGHIJ"));
90 test(S(),
91 0,
92 cpp17_input_iterator<const char*>(s),
93 cpp17_input_iterator<const char*>(s + 52),
94 S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
95
96 test(S("12345"), 0, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), S("12345"));
97 test(S("12345"), 1, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s + 1), S("1A2345"));
98 test(S("12345"),
99 4,
100 cpp17_input_iterator<const char*>(s),
101 cpp17_input_iterator<const char*>(s + 10),
102 S("1234ABCDEFGHIJ5"));
103 test(S("12345"),
104 5,
105 cpp17_input_iterator<const char*>(s),
106 cpp17_input_iterator<const char*>(s + 52),
107 S("12345ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
108
109 test(S("1234567890"), 0, cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), S("1234567890"));
110 test(S("1234567890"),
111 1,
112 cpp17_input_iterator<const char*>(s),
113 cpp17_input_iterator<const char*>(s + 1),
114 S("1A234567890"));
115 test(S("1234567890"),
116 10,
117 cpp17_input_iterator<const char*>(s),
118 cpp17_input_iterator<const char*>(s + 10),
119 S("1234567890ABCDEFGHIJ"));
120 test(S("1234567890"),
121 8,
122 cpp17_input_iterator<const char*>(s),
123 cpp17_input_iterator<const char*>(s + 52),
124 S("12345678ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz90"));
125
126 test(S("12345678901234567890"),
127 3,
128 cpp17_input_iterator<const char*>(s),
129 cpp17_input_iterator<const char*>(s),
130 S("12345678901234567890"));
131 test(S("12345678901234567890"),
132 3,
133 cpp17_input_iterator<const char*>(s),
134 cpp17_input_iterator<const char*>(s + 1),
135 S("123A45678901234567890"));
136 test(S("12345678901234567890"),
137 15,
138 cpp17_input_iterator<const char*>(s),
139 cpp17_input_iterator<const char*>(s + 10),
140 S("123456789012345ABCDEFGHIJ67890"));
141 test(S("12345678901234567890"),
142 20,
143 cpp17_input_iterator<const char*>(s),
144 cpp17_input_iterator<const char*>(s + 52),
145 S("12345678901234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
146 }
147
test()148 TEST_CONSTEXPR_CXX20 bool test() {
149 test_string<std::string>();
150 #if TEST_STD_VER >= 11
151 test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
152 test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
153 #endif
154
155 #ifndef TEST_HAS_NO_EXCEPTIONS
156 if (!TEST_IS_CONSTANT_EVALUATED) { // test iterator operations that throw
157 typedef std::string S;
158 typedef ThrowingIterator<char> TIter;
159 typedef cpp17_input_iterator<TIter> IIter;
160 const char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
161 test_exceptions(S(), 0, IIter(TIter(s, s + 10, 4, TIter::TAIncrement)), IIter(TIter()));
162 test_exceptions(S(), 0, IIter(TIter(s, s + 10, 5, TIter::TADereference)), IIter(TIter()));
163 test_exceptions(S(), 0, IIter(TIter(s, s + 10, 6, TIter::TAComparison)), IIter(TIter()));
164
165 test_exceptions(S(), 0, TIter(s, s + 10, 4, TIter::TAIncrement), TIter());
166 test_exceptions(S(), 0, TIter(s, s + 10, 5, TIter::TADereference), TIter());
167 test_exceptions(S(), 0, TIter(s, s + 10, 6, TIter::TAComparison), TIter());
168
169 Widget w[100];
170 test_exceptions(S(), 0, w, w + 100);
171 }
172 #endif
173
174 { // test inserting into self
175 typedef std::string S;
176 S s_short = "123/";
177 S s_long = "Lorem ipsum dolor sit amet, consectetur/";
178
179 s_short.insert(s_short.begin(), s_short.begin(), s_short.end());
180 assert(s_short == "123/123/");
181 s_short.insert(s_short.begin(), s_short.begin(), s_short.end());
182 assert(s_short == "123/123/123/123/");
183 s_short.insert(s_short.begin(), s_short.begin(), s_short.end());
184 assert(s_short == "123/123/123/123/123/123/123/123/");
185
186 s_long.insert(s_long.begin(), s_long.begin(), s_long.end());
187 assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/");
188 }
189
190 { // test assigning a different type
191 typedef std::string S;
192 const std::uint8_t p[] = "ABCD";
193
194 S s;
195 s.insert(s.begin(), p, p + 4);
196 assert(s == "ABCD");
197 }
198
199 if (!TEST_IS_CONSTANT_EVALUATED) { // regression-test inserting into self in sneaky ways
200 std::string s_short = "hello";
201 std::string s_long = "Lorem ipsum dolor sit amet, consectetur/";
202 std::string s_othertype = "hello";
203 const unsigned char* first = reinterpret_cast<const unsigned char*>(s_othertype.data());
204
205 test(s_short, 0, s_short.data() + s_short.size(), s_short.data() + s_short.size() + 1, std::string("\0hello", 6));
206 test(s_long,
207 0,
208 s_long.data() + s_long.size(),
209 s_long.data() + s_long.size() + 1,
210 std::string("\0Lorem ipsum dolor sit amet, consectetur/", 41));
211 test(s_othertype, 1, first + 2, first + 5, std::string("hlloello"));
212 }
213
214 { // test with a move iterator that returns char&&
215 typedef cpp17_input_iterator<const char*> It;
216 typedef std::move_iterator<It> MoveIt;
217 const char p[] = "ABCD";
218 std::string s;
219 s.insert(s.begin(), MoveIt(It(std::begin(p))), MoveIt(It(std::end(p) - 1)));
220 assert(s == "ABCD");
221 }
222 { // test with a move iterator that returns char&&
223 typedef forward_iterator<const char*> It;
224 typedef std::move_iterator<It> MoveIt;
225 const char p[] = "ABCD";
226 std::string s;
227 s.insert(s.begin(), MoveIt(It(std::begin(p))), MoveIt(It(std::end(p) - 1)));
228 assert(s == "ABCD");
229 }
230 { // test with a move iterator that returns char&&
231 typedef const char* It;
232 typedef std::move_iterator<It> MoveIt;
233 const char p[] = "ABCD";
234 std::string s;
235 s.insert(s.begin(), MoveIt(It(std::begin(p))), MoveIt(It(std::end(p) - 1)));
236 assert(s == "ABCD");
237 }
238 return true;
239 }
240
main(int,char **)241 int main(int, char**) {
242 test();
243 #if TEST_STD_VER > 17
244 static_assert(test());
245 #endif
246
247 return 0;
248 }
249