https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108846

--- Comment #35 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-13 branch has been updated by Jonathan Wakely
<r...@gcc.gnu.org>:

https://gcc.gnu.org/g:84eb2ddc53344259c5b3980d1b5dad69b82bfe8b

commit r13-9540-g84eb2ddc53344259c5b3980d1b5dad69b82bfe8b
Author: Giuseppe D'Angelo <giuseppe.dang...@kdab.com>
Date:   Fri Aug 23 15:05:54 2024 +0200

    libstdc++: Do not use use memmove for 1-element ranges [PR108846,PR116471]

    This commit ports the fixes already applied by r13-6372-g822a11a1e642e0
    to the range-based versions of copy/move algorithms.

    When doing so, a further bug (PR116471) was discovered in the
    implementation of the range-based algorithms: although the algorithms
    are already constrained by the indirectly_copyable/movable concepts,
    there was a failing static_assert in the memmove path.

    This static_assert checked that iterator's value type was assignable by
    using the is_copy_assignable (move) type traits. However, this is a
    problem, because the traits are too strict when checking for constness;
    a type like

      struct S { S& operator=(S &) = default; };

    is trivially copyable (and thus could benefit of the memmove path),
    but it does not satisfy is_copy_assignable because the operator takes
    by non-const reference.

    Now, the reason for the check to be there is because a type with
    a deleted assignment operator like

      struct E { E& operator=(const E&) = delete; };

    is still trivially copyable, but not assignable. We don't want
    algorithms like std::ranges::copy to compile because they end up
    selecting the memmove path, "ignoring" the fact that E isn't even
    copy assignable.

    But the static_assert isn't needed here any longer: as noted before,
    the ranges algorithms already have the appropriate constraints; and
    even if they didn't, there's now a non-discarded codepath to deal with
    ranges of length 1 where there is an explicit assignment operation.

    Therefore, this commit removes it. (In fact, r13-6372-g822a11a1e642e0
    removed the same static_assert from the non-ranges algorithms.)

    libstdc++-v3/ChangeLog:

            PR libstdc++/108846
            PR libstdc++/116471
            * include/bits/ranges_algobase.h (__assign_one): New helper
            function.
            (__copy_or_move): Remove a spurious static_assert; use
            __assign_one for memcpyable ranges of length 1.
            (__copy_or_move_backward): Likewise.
            * testsuite/25_algorithms/copy/108846.cc: Extend to range-based
            algorithms, and cover both memcpyable and non-memcpyable
            cases.
            * testsuite/25_algorithms/copy_backward/108846.cc: Likewise.
            * testsuite/25_algorithms/copy_n/108846.cc: Likewise.
            * testsuite/25_algorithms/move/108846.cc: Likewise.
            * testsuite/25_algorithms/move_backward/108846.cc: Likewise.

    Signed-off-by: Giuseppe D'Angelo <giuseppe.dang...@kdab.com>
    (cherry picked from commit 5938e0681c3907b2771ce6717988416b0ddd2f54)

Reply via email to