libstdc++: Remove __memmove wrapper for constexpr algorithms
authorJonathan Wakely <jwakely@redhat.com>
Tue, 25 Feb 2020 14:16:42 +0000 (14:16 +0000)
committerJonathan Wakely <jwakely@redhat.com>
Tue, 25 Feb 2020 17:01:50 +0000 (17:01 +0000)
commit490350a11f82ee214aa8dd50b1222f3e7cffe630
treed3b3a9e7fecf510b746fd6f6cf9ccbd810d4a588
parentdfb93d0524615ce15d5f4e132f799fd836099f59
libstdc++: Remove __memmove wrapper for constexpr algorithms

The mutating sequence algorithms std::copy, std::copy_backward,
std::move and std::move_backward conditionally use __builtin_memmove
for trivially copyable types. However, because memmove isn't usable in
constant expressions the use of __builtin_memmove is wrapped in a
__memmove function which replaces __builtin_memmove with a handwritten
loop when std::is_constant_evaluated() is true.

This means we have a manual loop for non-trivially copyable cases, and a
different manual loop for trivially copyable but constexpr cases. The
latter loop has incorrect semantics for the {copy,move}_backward cases
and so isn't used for them. Until earlier today the latter loop also had
incorrect semantics for the std::move cases, trying to move from const
rvalues.

The approach taken by this patch is to remove the __memmove function
entirely and use the original (and correct) manual loops for the
constexpr cases as well as the non-trivially copyable cases. This was
already done for move_backward and copy_backward, but was incorrectly
turning copy_backward into move_backward, by failing to use the _IsMove
constant to select the right specialization. This patch also fixes that.

* include/bits/ranges_algobase.h (__copy_or_move): Do not use memmove
during constant evaluation. Call __builtin_memmove directly instead of
__memmove.
(__copy_or_move_backward): Likewise.
* include/bits/stl_algobase.h (__memmove): Remove.
(__copy_move<M, true, random_access_iterator_tag>::__copy_m)
(__copy_move_backward<M, true, random_access_iterator_tag>::__copy_m):
Use __builtin_memmove directly instead of __memmove.
(__copy_move_a2): Do not use memmove during constant evaluation.
(__copy_move_backward_a2): Use _IsMove constant to select correct
__copy_move_backward specialization.
* testsuite/25_algorithms/copy_backward/constexpr.cc: Check for copies
begin turned into moves during constant evaluation.
libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/ranges_algobase.h
libstdc++-v3/include/bits/stl_algobase.h
libstdc++-v3/testsuite/25_algorithms/copy_backward/constexpr.cc