Author: marshall Date: Sun Sep 4 20:54:30 2016 New Revision: 280643 URL: http://llvm.org/viewvc/llvm-project?rev=280643&view=rev Log: Fix Bug 30240 - std::string: append(first, last) error when aliasing. Add test cases for append/insert/assign/replace while we're at it, and fix a similar bug in insert.
Modified: libcxx/trunk/include/string libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp Modified: libcxx/trunk/include/string URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/string?rev=280643&r1=280642&r2=280643&view=diff ============================================================================== --- libcxx/trunk/include/string (original) +++ libcxx/trunk/include/string Sun Sep 4 20:54:30 2016 @@ -1998,7 +1998,7 @@ typename enable_if >::type basic_string<_CharT, _Traits, _Allocator>::assign(_InputIterator __first, _InputIterator __last) { - basic_string __temp(__first, __last, __alloc()); + const basic_string __temp(__first, __last, __alloc()); assign(__temp.data(), __temp.size()); return *this; } @@ -2151,11 +2151,17 @@ typename enable_if >::type basic_string<_CharT, _Traits, _Allocator>::append(_InputIterator __first, _InputIterator __last) { - basic_string __temp (__first, __last, __alloc()); + const basic_string __temp (__first, __last, __alloc()); append(__temp.data(), __temp.size()); return *this; } +template <typename _Tp> +bool __ptr_in_range (const _Tp* __p, const _Tp* __first, const _Tp* __last) +{ + return __first <= __p && __p < __last; +} + template <class _CharT, class _Traits, class _Allocator> template<class _ForwardIterator> typename enable_if @@ -2171,13 +2177,21 @@ basic_string<_CharT, _Traits, _Allocator size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last)); if (__n) { - if (__cap - __sz < __n) - __grow_by(__cap, __sz + __n - __cap, __sz, __sz, 0); - pointer __p = __get_pointer() + __sz; - for (; __first != __last; ++__p, ++__first) - traits_type::assign(*__p, *__first); - traits_type::assign(*__p, value_type()); - __set_size(__sz + __n); + if ( __ptr_in_range(&*__first, data(), data() + size())) + { + const basic_string __temp (__first, __last, __alloc()); + append(__temp.data(), __temp.size()); + } + else + { + if (__cap - __sz < __n) + __grow_by(__cap, __sz + __n - __cap, __sz, __sz, 0); + pointer __p = __get_pointer() + __sz; + for (; __first != __last; ++__p, ++__first) + traits_type::assign(*__p, *__first); + traits_type::assign(*__p, value_type()); + __set_size(__sz + __n); + } } return *this; } @@ -2299,7 +2313,7 @@ basic_string<_CharT, _Traits, _Allocator "string::insert(iterator, range) called with an iterator not" " referring to this string"); #endif - basic_string __temp(__first, __last, __alloc()); + const basic_string __temp(__first, __last, __alloc()); return insert(__pos, __temp.data(), __temp.data() + __temp.size()); } @@ -2319,11 +2333,17 @@ basic_string<_CharT, _Traits, _Allocator " referring to this string"); #endif size_type __ip = static_cast<size_type>(__pos - begin()); - size_type __sz = size(); - size_type __cap = capacity(); size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last)); if (__n) { + if ( __ptr_in_range(&*__first, data(), data() + size())) + { + const basic_string __temp(__first, __last, __alloc()); + return insert(__pos, __temp.data(), __temp.data() + __temp.size()); + } + + size_type __sz = size(); + size_type __cap = capacity(); value_type* __p; if (__cap - __sz >= __n) { @@ -2523,7 +2543,7 @@ typename enable_if basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2) { - basic_string __temp(__j1, __j2, __alloc()); + const basic_string __temp(__j1, __j2, __alloc()); return this->replace(__i1, __i2, __temp); } Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff ============================================================================== --- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp (original) +++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp Sun Sep 4 20:54:30 2016 @@ -178,4 +178,21 @@ int main() test_exceptions(S(), TIter(s, s+10, 6, TIter::TAComparison), TIter()); } #endif + + { // test appending to self + typedef std::string S; + S s_short = "123/"; + S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + + s_short.append(s_short.begin(), s_short.end()); + assert(s_short == "123/123/"); + s_short.append(s_short.begin(), s_short.end()); + assert(s_short == "123/123/123/123/"); + s_short.append(s_short.begin(), s_short.end()); + assert(s_short == "123/123/123/123/123/123/123/123/"); + + s_long.append(s_long.begin(), s_long.end()); + assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); + } + } Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff ============================================================================== --- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp (original) +++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp Sun Sep 4 20:54:30 2016 @@ -61,4 +61,20 @@ int main() S("1234567890123456789012345678901234567890")); } #endif + + { // test appending to self + typedef std::string S; + S s_short = "123/"; + S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + + s_short.append(s_short.c_str()); + assert(s_short == "123/123/"); + s_short.append(s_short.c_str()); + assert(s_short == "123/123/123/123/"); + s_short.append(s_short.c_str()); + assert(s_short == "123/123/123/123/123/123/123/123/"); + + s_long.append(s_long.c_str()); + assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); + } } Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff ============================================================================== --- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp (original) +++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp Sun Sep 4 20:54:30 2016 @@ -70,4 +70,20 @@ int main() S("1234567890123456789012345678901234567890")); } #endif + + { // test appending to self + typedef std::string S; + S s_short = "123/"; + S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + + s_short.append(s_short.data(), s_short.size()); + assert(s_short == "123/123/"); + s_short.append(s_short.data(), s_short.size()); + assert(s_short == "123/123/123/123/"); + s_short.append(s_short.data(), s_short.size()); + assert(s_short == "123/123/123/123/123/123/123/123/"); + + s_long.append(s_long.data(), s_long.size()); + assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); + } } Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff ============================================================================== --- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp (original) +++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp Sun Sep 4 20:54:30 2016 @@ -179,4 +179,21 @@ int main() test_exceptions(S(), TIter(s, s+10, 6, TIter::TAComparison), TIter()); } #endif + + { // test assigning to self + typedef std::string S; + S s_short = "123/"; + S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + + s_short.assign(s_short.begin(), s_short.end()); + assert(s_short == "123/"); + s_short.assign(s_short.begin() + 2, s_short.end()); + assert(s_short == "3/"); + + s_long.assign(s_long.begin(), s_long.end()); + assert(s_long == "Lorem ipsum dolor sit amet, consectetur/"); + + s_long.assign(s_long.begin() + 30, s_long.end()); + assert(s_long == "nsectetur/"); + } } Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff ============================================================================== --- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp (original) +++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp Sun Sep 4 20:54:30 2016 @@ -61,4 +61,18 @@ int main() S("12345678901234567890")); } #endif + + { // test assignment to self + typedef std::string S; + S s_short = "123/"; + S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + + s_short.assign(s_short.c_str()); + assert(s_short == "123/"); + s_short.assign(s_short.c_str() + 2); + assert(s_short == "3/"); + + s_long.assign(s_long.c_str() + 30); + assert(s_long == "nsectetur/"); + } } Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff ============================================================================== --- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp (original) +++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp Sun Sep 4 20:54:30 2016 @@ -70,4 +70,20 @@ int main() S("12345678901234567890")); } #endif + { // test assign to self + typedef std::string S; + S s_short = "123/"; + S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + + s_short.assign(s_short.data(), s_short.size()); + assert(s_short == "123/"); + s_short.assign(s_short.data() + 2, s_short.size() - 2); + assert(s_short == "3/"); + + s_long.assign(s_long.data(), s_long.size()); + assert(s_long == "Lorem ipsum dolor sit amet, consectetur/"); + + s_long.assign(s_long.data() + 2, 8 ); + assert(s_long == "rem ipsu"); + } } Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff ============================================================================== --- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp (original) +++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp Sun Sep 4 20:54:30 2016 @@ -169,4 +169,21 @@ int main() assert(false); } #endif + + { // test inserting into self + typedef std::string S; + S s_short = "123/"; + S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + + s_short.insert(s_short.begin(), s_short.begin(), s_short.end()); + assert(s_short == "123/123/"); + s_short.insert(s_short.begin(), s_short.begin(), s_short.end()); + assert(s_short == "123/123/123/123/"); + s_short.insert(s_short.begin(), s_short.begin(), s_short.end()); + assert(s_short == "123/123/123/123/123/123/123/123/"); + + s_long.insert(s_long.begin(), s_long.begin(), s_long.end()); + assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); + } + } Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff ============================================================================== --- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp (original) +++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp Sun Sep 4 20:54:30 2016 @@ -210,4 +210,20 @@ int main() test(S("abcdefghijklmnopqrst"), 21, "12345678901234567890", S("can't happen")); } #endif + + { // test inserting into self + typedef std::string S; + S s_short = "123/"; + S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + + s_short.insert(0, s_short.c_str()); + assert(s_short == "123/123/"); + s_short.insert(0, s_short.c_str()); + assert(s_short == "123/123/123/123/"); + s_short.insert(0, s_short.c_str()); + assert(s_short == "123/123/123/123/123/123/123/123/"); + + s_long.insert(0, s_long.c_str()); + assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); + } } Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff ============================================================================== --- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp (original) +++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp Sun Sep 4 20:54:30 2016 @@ -691,4 +691,20 @@ int main() test(S("abcdefghijklmnopqrst"), 21, "12345678901234567890", 20, S("can't happen")); } #endif + + { // test inserting into self + typedef std::string S; + S s_short = "123/"; + S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + + s_short.insert(0, s_short.data(), s_short.size()); + assert(s_short == "123/123/"); + s_short.insert(0, s_short.data(), s_short.size()); + assert(s_short == "123/123/123/123/"); + s_short.insert(0, s_short.data(), s_short.size()); + assert(s_short == "123/123/123/123/123/123/123/123/"); + + s_long.insert(0, s_long.data(), s_long.size()); + assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); + } } Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff ============================================================================== --- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp (original) +++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp Sun Sep 4 20:54:30 2016 @@ -1007,4 +1007,20 @@ int main() test_exceptions(S("abcdefghijklmnopqrst"), 10, 5, TIter(s, s+10, 6, TIter::TAComparison), TIter()); } #endif + + { // test replacing into self + typedef std::string S; + S s_short = "123/"; + S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + + s_short.replace(s_short.begin(), s_short.begin(), s_short.begin(), s_short.end()); + assert(s_short == "123/123/"); + s_short.replace(s_short.begin(), s_short.begin(), s_short.begin(), s_short.end()); + assert(s_short == "123/123/123/123/"); + s_short.replace(s_short.begin(), s_short.begin(), s_short.begin(), s_short.end()); + assert(s_short == "123/123/123/123/123/123/123/123/"); + + s_long.replace(s_long.begin(), s_long.begin(), s_long.begin(), s_long.end()); + assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); + } } Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff ============================================================================== --- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp (original) +++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp Sun Sep 4 20:54:30 2016 @@ -282,4 +282,20 @@ int main() test2<S>(); } #endif + + { // test replacing into self + typedef std::string S; + S s_short = "123/"; + S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + + s_short.replace(s_short.begin(), s_short.begin(), s_short.c_str()); + assert(s_short == "123/123/"); + s_short.replace(s_short.begin(), s_short.begin(), s_short.c_str()); + assert(s_short == "123/123/123/123/"); + s_short.replace(s_short.begin(), s_short.begin(), s_short.c_str()); + assert(s_short == "123/123/123/123/123/123/123/123/"); + + s_long.replace(s_long.begin(), s_long.begin(), s_long.c_str()); + assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); + } } Modified: libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp?rev=280643&r1=280642&r2=280643&view=diff ============================================================================== --- libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp (original) +++ libcxx/trunk/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp Sun Sep 4 20:54:30 2016 @@ -972,4 +972,20 @@ int main() test8<S>(); } #endif + + { // test replacing into self + typedef std::string S; + S s_short = "123/"; + S s_long = "Lorem ipsum dolor sit amet, consectetur/"; + + s_short.replace(s_short.begin(), s_short.begin(), s_short.data(), s_short.size()); + assert(s_short == "123/123/"); + s_short.replace(s_short.begin(), s_short.begin(), s_short.data(), s_short.size()); + assert(s_short == "123/123/123/123/"); + s_short.replace(s_short.begin(), s_short.begin(), s_short.data(), s_short.size()); + assert(s_short == "123/123/123/123/123/123/123/123/"); + + s_long.replace(s_long.begin(), s_long.begin(), s_long.data(), s_long.size()); + assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); + } } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits