A very interesting read on some subtle issues. Used to keep a large list of things to avoid that included something like this and resurrected a little piece of it to try to break a few things; and ifort and gfortran worked great numerically, as you mentioned; and nvfortran failed on a scoping issue, not the parenthesis; although everyone but ifort got some intentionally troublesome formats wrong. gfortran(1) just put out a little whitespace I think it technically should not; nvfortran lost it on some non-advancing I/O issues but that was really not part of the core test here. Things have come a long way. A devilish simple test like this used to quickly segfault a lot of compilers. I still will tend to avoid this even though it is elegant and “should work” because of some of the same misgivings as described in that discussion, as dated as it might seem at first glance. So without really expecting anyone to care about the code, a little tweek of an old “dusty corners” test only showed one numeric problem over what I would expect (in nvfortran) and it is quite a combination of bad ideas that it takes to trigger it. Ignoring the I/O issues (ifort had none, and gfortran had a relatively trivial one on a real dusty corner) I used this and everyone passed on the parenthesis issues, so I can’t point to anywhere it did not work (although trying to figure out what the answer “should be” even with such simple logic shows why to avoid some of the things done here!). I was actually pleased at how well the compilers produced what I would hope they would “under the circumstances”: …
! Travel the well-worn road ...
!
! If the same variable is used as an argument more than once in the same
! statement, beware.
!
! If a function changes any argument values passed to it beware.
!
! beware of scope in contained procedures if using a variable also passed in
! WARNING: THIS CODE IS MEANT TO BREAK THINGS, NOT SHOW HOW TO DO ! THINGS
program puzzling
character(len=*),parameter :: gen_nvbug1='(g0.8,1x)'
character(len=*),parameter :: gen_nvbug2='(*(g0.8,1x),"never get here ")'
character(len=*),parameter :: gen_nvbug3='(*(g0.8,1x),/)'
character(len=*),parameter :: gfortran_bug='(":",2(g0.8,1x),/)'
character(len=*),parameter :: gen='(":",*(g0.8,1x))'
real,target :: x
pointer :: xxx
!!write(*,gen,advance='no') 'parenthesis '
x=2; write(*,gen,advance='no') change(change(x,x),x),x
x=2; write(*,gen,advance='no') change(change((x),x),x),x
x=2; write(*,gen,advance='no') change(change((x),(x)),x),x
x=2; write(*,gen,advance='no') change(change((x),(x)),(x)),x
x=2; write(*,gen,advance='no') change(change((x),(x)),(x)),(x)
write(*,*)
!!write(*,gen,advance='no') 'associate '
associate (xx => x)
x=2; write(*,gen,advance='no') change(change(x,x),x),x
x=2; write(*,gen,advance='no') change(change(xx,x),x),x
x=2; write(*,gen,advance='no') change(change(xx,xx),x),x
x=2; write(*,gen,advance='no') change(change(xx,xx),xx),x
x=2; write(*,gen,advance='no') change(change(xx,xx),xx),xx
end associate
write(*,*)
!!write(*,gen,advance='no') 'pointer '
xxx => x
x=2; write(*,gen,advance='no') change(change(x,x),x),x
x=2; write(*,gen,advance='no') change(change(xxx,x),x),x
x=2; write(*,gen,advance='no') change(change(xxx,xxx),x),x
x=2; write(*,gen,advance='no') change(change(xxx,xxx),xxx),x
x=2; write(*,gen,advance='no') change(change(xxx,xxx),xxx),xxx
write(*,*)
contains
function change(a,b) result(c)
real :: a,b,c
b=a+b
c=b**2
x=x+2
end function change
end program puzzling
gfortran
:484.00000 24.000000 :484.00000 24.000000 :400.00000 22.000000 :400.00000 6.0000000 :400.00000 6.0000000
:484.00000 24.000000 :484.00000 24.000000 :484.00000 24.000000 :484.00000 24.000000 :484.00000 24.000000
:484.00000 24.000000 :484.00000 24.000000 :484.00000 24.000000 :484.00000 24.000000 :484.00000 24.000000
ifort
:484.00000 24.000000 :484.00000 24.000000 :400.00000 22.000000 :400.00000 6.0000000 :400.00000 6.0000000
:484.00000 24.000000 :484.00000 24.000000 :484.00000 24.000000 :484.00000 24.000000 :484.00000 24.000000
:484.00000 24.000000 :484.00000 24.000000 :484.00000 24.000000 :484.00000 24.000000 :484.00000 24.000000
nvfortran
:484.00000 24.000000 :484.00000 24.000000 :400.00000 22.000000 :324.00000 6.0000000 :324.00000 6.0000000
:484.00000 24.000000 :484.00000 24.000000 :484.00000 24.000000 :484.00000 24.000000 :484.00000 24.000000
:484.00000 24.000000 :484.00000 24.000000 :484.00000 24.000000 :484.00000 24.000000 :484.00000 24.000000
Really only posted this in case anyone else wants to run it on another compiler. It would be nice to get the same answers as gfortran(1) and ifort(1).