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

            Bug ID: 82910
           Summary: marking data members private affects code generation
                    of copying
           Product: gcc
           Version: 7.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: vanyacpp at gmail dot com
  Target Milestone: ---

Consider the following piece of code:

struct pair
{
private:
    void* first;
    unsigned second;
};

struct other
{
    pair get() const;
};

struct my
{
    pair get(other const& other);

    pair current;
    pair* target;
};

pair my::get(other const& other)
{
    *target = other.get();
    return current;
}

For the function my::get() GCC generates the following (quite inefficient)
code:

my::get(other const&):
  pushq %rbx
  movq %rdi, %rbx
  movq %rsi, %rdi
  subq $16, %rsp
  call other::get() const
  movq 16(%rbx), %rcx
  movq %rax, (%rsp)
  movq %rdx, 8(%rsp)
  movq %rax, (%rcx)
  movl 8(%rsp), %eax
  movl %eax, 8(%rcx)
  movq (%rbx), %rax
  movq 8(%rbx), %rdx
  addq $16, %rsp
  popq %rbx
  ret

The expected generated code is:

my::get(other const&):
  pushq %rbp
  pushq %rbx
  movq %rdi, %rbx
  subq $8, %rsp
  movq 16(%rdi), %rbp
  movq %rsi, %rdi
  call other::get() const
  movq %rax, 0(%rbp) # just storing to *my::target...
  movq %rdx, 8(%rbp)
  movq (%rbx), %rax  # ... and then loading my::current
  movq 8(%rbx), %rdx
  addq $8, %rsp
  popq %rbx
  popq %rbp
  ret

The issue can be worked around. One way to do this is to make the data members
of pair public. Another way is changing pair::second type to unsigned long (to
match the size of pointer).

It would be great is GCC generates the second code irrespectively of
private-ness or the size of pair::second.

Reply via email to