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