This bug report has its origins in a post by Alfredo Buttari "passing float _Complex from C to Fortran" with a C main calling a Fortran subroutine and passing a complex argument by value. Here is a program, entirely in Fortran, that reproduces the bug.
program xplx complex :: x x=cmplx(0.0,1.0) write(*,*)' Before call, x = ',x call func(x) contains subroutine func(x) complex, value :: x write(*,*)' Inside subr, x = ',x return end subroutine func end program xplxThe result from the 32-bit compiler:
$ ./a.out Before call, x = (0.0000000E+00,1.000000) Inside subr, x = (0.0000000E+00,1.000000)and, from the 64-bit compiler:
$ ./a.out Before call, x = (0.0000000E+00,1.000000) Inside subr, x = (0.0000000E+00,0.0000000E+00)
There is a mismatch in the argument passing scheme at the assembler/machine level in x64 mode. The caller passes the real and imaginary parts of the single argument in the two halves of xmm0, loading xmm0 from the stack with one movsd. The subroutine expects the two parts in xmm0 and xmm1, which it moves onto the subroutine's stack with two movss instructions. At this point, however, xmm1 contains junk.
The bug is not seen when the argument is passed by reference.