[libc++] Remove the special logic for "noexcept iterators" in basic_string.
authorArthur O'Dwyer <arthur.j.odwyer@gmail.com>
Fri, 16 Apr 2021 21:49:57 +0000 (17:49 -0400)
committerArthur O'Dwyer <arthur.j.odwyer@gmail.com>
Mon, 26 Apr 2021 20:22:43 +0000 (16:22 -0400)
commite87479b00fcc852a54b79d2fd7f8d779e2b75f68
treed785caabd8cf2a4b1e43e8d0a061483f2e7d9ae0
parent70d94c3f2cae71ade2ceacdceb3d2e9899d2289a
[libc++] Remove the special logic for "noexcept iterators" in basic_string.

This reverts a large chunk of http://reviews.llvm.org/D15862 ,
and also fixes bugs in `insert`, `append`, and `assign`, which are now regression-tested.
(Thanks to Tim Song for pointing out the bug in `append`!)

Before this patch, we did a special dance in `append`, `assign`, and `insert`
(but not `replace`). All of these require the strong exception guarantee,
even when the user-provided InputIterator might have throwing operations.

The naive way to accomplish this is to construct a temporary string and
then append/assign/insert from the temporary; i.e., finish all the potentially
throwing and self-inspecting InputIterator operations *before* starting to
modify self. But this is slow, so we'd like to skip it when possible.

The old code (D15682) attempted to check that specific iterator operations
were nothrow: it assumed that if the iterator operations didn't throw, then
it was safe to iterate the input range multiple times and therefore it was
safe to use the fast-path non-naive version. This was wrong for two reasons:
(1) the old code checked the wrong operations (e.g. checked noexceptness of `==`,
but the code that ran used `!=`), and (2) the conversion of value_type to char
could still throw, or inspect the contents of self.

The new code is much simpler, although still much more complicated than it
really could be. We'll likely revisit this codepath at some point, but for now
this patch suffices to get it passing all the new regression tests.

The added tests all fail before this patch, and succeed afterward.
See https://quuxplusone.github.io/blog/2021/04/17/pathological-string-appends/

Differential Revision: https://reviews.llvm.org/D98573
libcxx/include/filesystem
libcxx/include/iterator
libcxx/include/string
libcxx/test/libcxx/iterators/trivial_iterators.pass.cpp [deleted file]
libcxx/test/libcxx/strings/iterators.exceptions.pass.cpp [deleted file]
libcxx/test/libcxx/strings/iterators.noexcept.pass.cpp [deleted file]
libcxx/test/std/strings/basic.string/string.modifiers/robust_against_adl.pass.cpp [new file with mode: 0644]
libcxx/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp
libcxx/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp
libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp
libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp