https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82224
--- Comment #8 from Alexander Cherepanov <ch3root at openwall dot com> --- On 2017-10-27 12:41, rguenth at gcc dot gnu.org wrote: >> And with allocated memory (C; add placement new's for C++): >> >> ---------------------------------------------------------------------- >> #include <stdlib.h> >> #include <string.h> >> #include <stdio.h> >> >> static long test(long *px, long long *py, void *pu) >> { >> *px = 0; >> *py = 1; >> >> // change effective type from long long to long >> long tmp; >> memcpy(&tmp, pu, sizeof(tmp)); >> memcpy(pu, &tmp, sizeof(tmp)); > > I believe this one is invalid - memcpy transfers the dynamic > type and *pu is currently 'long long'. So it's either not > changing the dynamic type because, well, the type transfers > through 'tmp' or you are accessing 'tmp' with declared type > long as 'long long'. AIUI memcpy is always valid if there is enough space, no matter what types its source and destination have. It accesses both of them as arrays of chars -- C11, 7.24.1p1: "The header <string.h> declares one type and several functions, and defines one macro useful for manipulating arrays of character type and other objects treated as arrays of character type." OTOH memcpy transfers effective type from the source to the destination but only if the destination has no declared type -- C11, 6.5p6: "If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one." Placement new in C++ can change dynamic types of objects with declared type but I don't think there are such facilities in C. So in this example the first memcpy copies the value of *pu to tmp but drops its effective type (long long) and the second memcpy copies the value and passes the effective type of 'tmp' (long) along.