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 // basic_string& assign(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,It first,It last,S expected)23 TEST_CONSTEXPR_CXX20 void test(S s, It first, It last, S expected) {
24 s.assign(first, last);
25 LIBCPP_ASSERT(s.__invariants());
26 assert(s == expected);
27 LIBCPP_ASSERT(is_string_asan_correct(s));
28 }
29
30 #ifndef TEST_HAS_NO_EXCEPTIONS
31 struct Widget {
operator charWidget32 operator char() const { throw 42; }
33 };
34
35 template <class S, class It>
test_exceptions(S s,It first,It last)36 void test_exceptions(S s, It first, It last) {
37 S original = s;
38 typename S::iterator begin = s.begin();
39 typename S::iterator end = s.end();
40
41 try {
42 s.assign(first, last);
43 assert(false);
44 } catch (...) {
45 }
46
47 // Part of "no effects" is that iterators and pointers
48 // into the string must not have been invalidated.
49 LIBCPP_ASSERT(s.__invariants());
50 assert(s == original);
51 assert(s.begin() == begin);
52 assert(s.end() == end);
53 }
54 #endif
55
56 template <class S>
test_string()57 TEST_CONSTEXPR_CXX20 void test_string() {
58 {
59 const char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
60 test(S(), s, s, S());
61 test(S(), s, s + 1, S("A"));
62 test(S(), s, s + 10, S("ABCDEFGHIJ"));
63 test(S(), s, s + 52, S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
64
65 test(S("12345"), s, s, S());
66 test(S("12345"), s, s + 1, S("A"));
67 test(S("12345"), s, s + 10, S("ABCDEFGHIJ"));
68 test(S("12345"), s, s + 52, S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
69
70 test(S("1234567890"), s, s, S());
71 test(S("1234567890"), s, s + 1, S("A"));
72 test(S("1234567890"), s, s + 10, S("ABCDEFGHIJ"));
73 test(S("1234567890"), s, s + 52, S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
74
75 test(S("12345678901234567890"), s, s, S());
76 test(S("12345678901234567890"), s, s + 1, S("A"));
77 test(S("12345678901234567890"), s, s + 10, S("ABCDEFGHIJ"));
78 test(S("12345678901234567890"), s, s + 52, S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
79
80 test(S(), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), S());
81 test(S(), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s + 1), S("A"));
82 test(S(), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s + 10), S("ABCDEFGHIJ"));
83 test(S(),
84 cpp17_input_iterator<const char*>(s),
85 cpp17_input_iterator<const char*>(s + 52),
86 S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
87
88 test(S("12345"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), S());
89 test(S("12345"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s + 1), S("A"));
90 test(S("12345"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s + 10), S("ABCDEFGHIJ"));
91 test(S("12345"),
92 cpp17_input_iterator<const char*>(s),
93 cpp17_input_iterator<const char*>(s + 52),
94 S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
95
96 test(S("1234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), S());
97 test(S("1234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s + 1), S("A"));
98 test(S("1234567890"),
99 cpp17_input_iterator<const char*>(s),
100 cpp17_input_iterator<const char*>(s + 10),
101 S("ABCDEFGHIJ"));
102 test(S("1234567890"),
103 cpp17_input_iterator<const char*>(s),
104 cpp17_input_iterator<const char*>(s + 52),
105 S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
106
107 test(S("12345678901234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), S());
108 test(S("12345678901234567890"),
109 cpp17_input_iterator<const char*>(s),
110 cpp17_input_iterator<const char*>(s + 1),
111 S("A"));
112 test(S("12345678901234567890"),
113 cpp17_input_iterator<const char*>(s),
114 cpp17_input_iterator<const char*>(s + 10),
115 S("ABCDEFGHIJ"));
116 test(S("12345678901234567890"),
117 cpp17_input_iterator<const char*>(s),
118 cpp17_input_iterator<const char*>(s + 52),
119 S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
120 }
121
122 #ifndef TEST_HAS_NO_EXCEPTIONS
123 if (!TEST_IS_CONSTANT_EVALUATED) { // test iterator operations that throw
124 typedef ThrowingIterator<char> TIter;
125 typedef cpp17_input_iterator<TIter> IIter;
126 const char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
127 test_exceptions(S(), IIter(TIter(s, s + 10, 4, TIter::TAIncrement)), IIter(TIter()));
128 test_exceptions(S(), IIter(TIter(s, s + 10, 5, TIter::TADereference)), IIter(TIter()));
129 test_exceptions(S(), IIter(TIter(s, s + 10, 6, TIter::TAComparison)), IIter(TIter()));
130
131 test_exceptions(S(), TIter(s, s + 10, 4, TIter::TAIncrement), TIter());
132 test_exceptions(S(), TIter(s, s + 10, 5, TIter::TADereference), TIter());
133 test_exceptions(S(), TIter(s, s + 10, 6, TIter::TAComparison), TIter());
134
135 Widget w[100];
136 test_exceptions(S(), w, w + 100);
137 }
138 #endif
139
140 { // test assigning to self
141 S s_short = "123/";
142 S s_long = "Lorem ipsum dolor sit amet, consectetur/";
143
144 s_short.assign(s_short.begin(), s_short.end());
145 assert(s_short == "123/");
146 s_short.assign(s_short.begin() + 2, s_short.end());
147 assert(s_short == "3/");
148
149 s_long.assign(s_long.begin(), s_long.end());
150 assert(s_long == "Lorem ipsum dolor sit amet, consectetur/");
151
152 s_long.assign(s_long.begin() + 30, s_long.end());
153 assert(s_long == "nsectetur/");
154 }
155
156 { // test assigning a different type
157 const std::uint8_t p[] = "ABCD";
158
159 S s;
160 s.assign(p, p + 4);
161 assert(s == "ABCD");
162 }
163
164 { // regression-test assigning to self in sneaky ways
165 S sneaky = "hello";
166 sneaky.resize(sneaky.capacity(), 'x');
167 S expected = sneaky + S(1, '\0');
168 test(sneaky, sneaky.data(), sneaky.data() + sneaky.size() + 1, expected);
169 }
170 }
171
test()172 TEST_CONSTEXPR_CXX20 bool test() {
173 test_string<std::string>();
174 #if TEST_STD_VER >= 11
175 test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
176 test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
177 #endif
178
179 return true;
180 }
181
main(int,char **)182 int main(int, char**) {
183 test();
184 #if TEST_STD_VER > 17
185 static_assert(test());
186 #endif
187
188 return 0;
189 }
190