1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
11 // template<class InputIterator>
12 // basic_string& append(InputIterator first, InputIterator last); // constexpr since C++20
17 #include "test_macros.h"
18 #include "test_iterators.h"
19 #include "min_allocator.h"
20 #include "asan_testing.h"
22 template <class S
, class It
>
23 TEST_CONSTEXPR_CXX20
void test(S s
, It first
, It last
, S expected
) {
24 s
.append(first
, last
);
25 LIBCPP_ASSERT(s
.__invariants());
26 assert(s
== expected
);
27 LIBCPP_ASSERT(is_string_asan_correct(s
));
30 #ifndef TEST_HAS_NO_EXCEPTIONS
32 operator char() const { throw 42; }
35 template <class S
, class It
>
36 TEST_CONSTEXPR_CXX20
void test_exceptions(S s
, It first
, It last
) {
38 typename
S::iterator begin
= s
.begin();
39 typename
S::iterator end
= s
.end();
42 s
.append(first
, last
);
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
);
57 TEST_CONSTEXPR_CXX20
void test_string() {
59 const char* s
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
61 test(S(), s
, s
+ 1, S("A"));
62 test(S(), s
, s
+ 10, S("ABCDEFGHIJ"));
63 test(S(), s
, s
+ 52, S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
65 test(S("12345"), s
, s
, S("12345"));
66 test(S("12345"), s
, s
+ 1, S("12345A"));
67 test(S("12345"), s
, s
+ 10, S("12345ABCDEFGHIJ"));
68 test(S("12345"), s
, s
+ 52, S("12345ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
70 test(S("1234567890"), s
, s
, S("1234567890"));
71 test(S("1234567890"), s
, s
+ 1, S("1234567890A"));
72 test(S("1234567890"), s
, s
+ 10, S("1234567890ABCDEFGHIJ"));
73 test(S("1234567890"), s
, s
+ 52, S("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
75 test(S("12345678901234567890"), s
, s
, S("12345678901234567890"));
76 test(S("12345678901234567890"),
79 S("12345678901234567890"
81 test(S("12345678901234567890"),
84 S("12345678901234567890"
86 test(S("12345678901234567890"),
89 S("12345678901234567890"
90 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
92 test(S(), cpp17_input_iterator
<const char*>(s
), cpp17_input_iterator
<const char*>(s
), S());
93 test(S(), cpp17_input_iterator
<const char*>(s
), cpp17_input_iterator
<const char*>(s
+ 1), S("A"));
94 test(S(), cpp17_input_iterator
<const char*>(s
), cpp17_input_iterator
<const char*>(s
+ 10), S("ABCDEFGHIJ"));
96 cpp17_input_iterator
<const char*>(s
),
97 cpp17_input_iterator
<const char*>(s
+ 52),
98 S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
100 test(S("12345"), cpp17_input_iterator
<const char*>(s
), cpp17_input_iterator
<const char*>(s
), S("12345"));
101 test(S("12345"), cpp17_input_iterator
<const char*>(s
), cpp17_input_iterator
<const char*>(s
+ 1), S("12345A"));
103 cpp17_input_iterator
<const char*>(s
),
104 cpp17_input_iterator
<const char*>(s
+ 10),
105 S("12345ABCDEFGHIJ"));
107 cpp17_input_iterator
<const char*>(s
),
108 cpp17_input_iterator
<const char*>(s
+ 52),
109 S("12345ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
111 test(S("1234567890"), cpp17_input_iterator
<const char*>(s
), cpp17_input_iterator
<const char*>(s
), S("1234567890"));
112 test(S("1234567890"),
113 cpp17_input_iterator
<const char*>(s
),
114 cpp17_input_iterator
<const char*>(s
+ 1),
116 test(S("1234567890"),
117 cpp17_input_iterator
<const char*>(s
),
118 cpp17_input_iterator
<const char*>(s
+ 10),
119 S("1234567890ABCDEFGHIJ"));
120 test(S("1234567890"),
121 cpp17_input_iterator
<const char*>(s
),
122 cpp17_input_iterator
<const char*>(s
+ 52),
123 S("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
125 test(S("12345678901234567890"),
126 cpp17_input_iterator
<const char*>(s
),
127 cpp17_input_iterator
<const char*>(s
),
128 S("12345678901234567890"));
129 test(S("12345678901234567890"),
130 cpp17_input_iterator
<const char*>(s
),
131 cpp17_input_iterator
<const char*>(s
+ 1),
132 S("12345678901234567890"
134 test(S("12345678901234567890"),
135 cpp17_input_iterator
<const char*>(s
),
136 cpp17_input_iterator
<const char*>(s
+ 10),
137 S("12345678901234567890"
139 test(S("12345678901234567890"),
140 cpp17_input_iterator
<const char*>(s
),
141 cpp17_input_iterator
<const char*>(s
+ 52),
142 S("12345678901234567890"
143 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
146 #ifndef TEST_HAS_NO_EXCEPTIONS
147 if (!TEST_IS_CONSTANT_EVALUATED
) { // test iterator operations that throw
148 typedef ThrowingIterator
<char> TIter
;
149 typedef cpp17_input_iterator
<TIter
> IIter
;
150 const char* s
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
151 test_exceptions(S(), IIter(TIter(s
, s
+ 10, 4, TIter::TAIncrement
)), IIter(TIter()));
152 test_exceptions(S(), IIter(TIter(s
, s
+ 10, 5, TIter::TADereference
)), IIter(TIter()));
153 test_exceptions(S(), IIter(TIter(s
, s
+ 10, 6, TIter::TAComparison
)), IIter(TIter()));
155 test_exceptions(S(), TIter(s
, s
+ 10, 4, TIter::TAIncrement
), TIter());
156 test_exceptions(S(), TIter(s
, s
+ 10, 5, TIter::TADereference
), TIter());
157 test_exceptions(S(), TIter(s
, s
+ 10, 6, TIter::TAComparison
), TIter());
160 test_exceptions(S(), w
, w
+ 100);
164 { // test appending to self
166 S s_long
= "Lorem ipsum dolor sit amet, consectetur/";
168 s_short
.append(s_short
.begin(), s_short
.end());
169 assert(s_short
== "123/123/");
170 s_short
.append(s_short
.begin(), s_short
.end());
171 assert(s_short
== "123/123/123/123/");
172 s_short
.append(s_short
.begin(), s_short
.end());
173 assert(s_short
== "123/123/123/123/123/123/123/123/");
175 s_long
.append(s_long
.begin(), s_long
.end());
176 assert(s_long
== "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/");
179 { // test appending a different type
180 const std::uint8_t p
[] = "ABCD";
187 { // regression-test appending to self in sneaky ways
189 S s_long
= "Lorem ipsum dolor sit amet, consectetur/";
190 S s_othertype
= "hello";
191 S s_sneaky
= "hello";
193 test(s_short
, s_short
.data() + s_short
.size(), s_short
.data() + s_short
.size() + 1, S("hello\0", 6));
195 s_long
.data() + s_long
.size(),
196 s_long
.data() + s_long
.size() + 1,
197 S("Lorem ipsum dolor sit amet, consectetur/\0", 41));
199 s_sneaky
.reserve(12);
200 test(s_sneaky
, s_sneaky
.data(), s_sneaky
.data() + 6, S("hellohello\0", 11));
202 if (!TEST_IS_CONSTANT_EVALUATED
) {
203 const unsigned char* first
= reinterpret_cast<const unsigned char*>(s_othertype
.data());
204 test(s_othertype
, first
+ 2, first
+ 5, S("hellollo"));
208 { // test with a move iterator that returns char&&
209 typedef forward_iterator
<const char*> It
;
210 typedef std::move_iterator
<It
> MoveIt
;
211 const char p
[] = "ABCD";
213 s
.append(MoveIt(It(std::begin(p
))), MoveIt(It(std::end(p
) - 1)));
216 { // test with a move iterator that returns char&&
217 typedef const char* It
;
218 typedef std::move_iterator
<It
> MoveIt
;
219 const char p
[] = "ABCD";
221 s
.append(MoveIt(It(std::begin(p
))), MoveIt(It(std::end(p
) - 1)));
226 TEST_CONSTEXPR_CXX20
bool test() {
227 test_string
<std::string
>();
228 #if TEST_STD_VER >= 11
229 test_string
<std::basic_string
<char, std::char_traits
<char>, min_allocator
<char> > >();
230 test_string
<std::basic_string
<char, std::char_traits
<char>, safe_allocator
<char> > >();
236 int main(int, char**) {
238 #if TEST_STD_VER > 17
239 static_assert(test());