We fold memcpy to direct assignments based on types of the pointed-to types
of its arguments.  This is completely wrong for C++ and wrong for C if
neither source nor destination has a declared type.  memcpy transfers the
dynamic type of objects.

int main()
{
  int i = 0;
  float f = 1.0;
  int *p = (int *)&f;
  __builtin_memcpy (&i, p, 4);
  if (*(float *)&i != 1.0)
    __builtin_abort ();
  return 0;
}

we already fold the memcpy to

  i = *(int * {ref-all})p;

but that creates an access to i via an lvalue of type int.  It needs to
be all done via a ref-all access, thus

*(<type-large-enough> * {ref-all})&i = *(<type-large-enough> * {ref-all})p;

In C the testcase would invoke undefined behavior as i has a declared type
but it is valid C++.

The issue arises fixing std::tr1::functional::swap wrt its accesses to
_Any_data.

      void swap(function& __x)
      {
        _Any_data __old_functor;
        __builtin_memcpy (&__old_functor, &_M_functor, sizeof (_Any_data));
        __builtin_memcpy (&_M_functor, &__x._M_functor, sizeof (_Any_data));
        __builtin_memcpy (&__x._M_functor, &__old_functor, sizeof (_Any_data));
        _Manager_type __old_manager = _M_manager;

is folded back to

  __old_functor = D.13016.D.8817._M_functor;
  D.13016.D.8817._M_functor = f.D.8817._M_functor;
  f.D.8817._M_functor = __old_functor;

which wasn't the point of the whole excercise.


-- 
           Summary: memcpy folding overeager
           Product: gcc
           Version: 4.5.0
            Status: UNCONFIRMED
          Keywords: wrong-code, alias
          Severity: normal
          Priority: P3
         Component: middle-end
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: rguenth at gcc dot gnu dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42834

Reply via email to