------- Comment #18 from mikael at gcc dot gnu dot org 2008-11-17 19:43 ------- The problem is in ByteToString. The assignment of the transfer result is changed to a memmove. The memmove is controlled by the size of both the lhs and the rhs. The size of the rhs (actually the charlen=3 in this case) is not the same as that of the actual data, as the charlen was copied from string's typespec in transfer. Thus, we are copying 3 bytes, instead of 2.
I think the code is still a valid program and a wrong-code, as while the standard allow to have a result (partially) undefined/processor-dependent, it doesn't allow to read unallocated memory. module TransferBug type ByteType integer(kind=1) :: singleByte end type type(ByteType) :: BytesPrototype(2) contains function StringToBytes(v) result (bytes) character(len=2) :: v type (ByteType) :: bytes(2)!size(transfer(v, BytesPrototype))) bytes = transfer('Hi', BytesPrototype) end function subroutine BytesToString(bytes, string) type (ByteType) :: bytes(2) character(len=*) :: string string = transfer(bytes, string) end subroutine end module program main use TransferBug character(len=3) :: str type(ByteType) :: i(1) call BytesToString( StringToBytes('Hi'), str ) end program Valgrind doesn't complain on this testcase, but I strongly suspect that the bug is still there. Using the commented array size forces the creation of temporaries, and then valgrind catches the error. Now, how to fix this? We could unconditionally create a temporary in transfer, so that we have both the original data size and the target data size at the time of the memmove. That would probably mean a lot of regressions, and not only speed ones. We could keep track of the original data size. I must admit I'm not satisfied with this one either. What else? -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34955