[Bug libstdc++/68350] std::uninitialized_copy overly restrictive for trivially_copyable types

barry.revzin at gmail dot com gcc-bugzilla@gcc.gnu.org
Wed Feb 23 22:03:38 GMT 2022


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

Barry Revzin <barry.revzin at gmail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |barry.revzin at gmail dot com

--- Comment #8 from Barry Revzin <barry.revzin at gmail dot com> ---
Here's an example:

struct A { int i; };
struct B { int i{}; };

Both are trivially copyable, A is additionally trivially default constructible
while B is not. This distinction is irrelevant in this case - we're copying,
and that does not involve default constructing an A or B (trivial or
otherwise).

But this means that __is_trivial(B) is false, so we don't go into std::copy, so
these do different things:

#include <memory>

struct A { int i; };
struct B { int i{}; };

void copy_a(A* f, A* l, A* out) {
    std::uninitialized_copy(f, l, out);
}

void copy_b(B* f, B* l, B* out) {
    std::uninitialized_copy(f, l, out);
}

emits (with g++ 11.2, -std=c++20 -O3, https://godbolt.org/z/eG9hsbcTE):

copy_a(A*, A*, A*):
        mov     r8, rdi
        mov     rdi, rdx
        cmp     r8, rsi
        je      .L1
        mov     rdx, rsi
        mov     rsi, r8
        sub     rdx, r8
        jmp     memmove
.L1:
        ret
copy_b(B*, B*, B*):
        cmp     rdi, rsi
        je      .L4
        sub     rsi, rdi
        xor     eax, eax
.L6:
        mov     ecx, DWORD PTR [rdi+rax]
        mov     DWORD PTR [rdx+rax], ecx
        add     rax, 4
        cmp     rax, rsi
        jne     .L6
.L4:
        ret

Whereas the copy_b case could also use memmove.


More information about the Gcc-bugs mailing list