two layer where work ok, why single where work error? example one: program test real :: x(3) = 1, y(3) = 2 logical :: m(3) = .true., m2(3) = .false. where (m) x = f1() !where (m2) ! y = f2() !end where end where if (any(x/=3)) then print *, 'FAIL', x !if (any(x/=3 .or. y/=3)) then ! print *,'FAIL',x,y else print *,'ok' end if contains function f1() m = .false. !m2 = .true. f1 = 3 end function !function f2() ! m2 = .false. ! f2 = 3 !end function end gfortran-12: ASM generation compiler returned: 0 Execution build compiler returned: 0 Program returned: 0 FAIL 3.00000000 1.00000000 1.00000000 example two: program test real :: x(3) = 1, y(3) = 2 logical :: m(3) = .true., m2(3) = .false. where (m) x = f1() where (m2) y = f2() end where end where if (any(x/=3 .or. y/=3)) then print *,'FAIL',x,y else print *,'ok' end if contains function f1() m = .false. m2 = .true. f1 = 3 end function function f2() m2 = .false. f2 = 3 end function end ASM generation compiler returned: 0 Execution build compiler returned: 0 Program returned: 0 ok Looking forward to hearing from you!
(In reply to han.wu from comment #0) > two layer where work ok, why single where work error? > Clearly a bug due to calling a function with side effects. While valid, it is a questionable programming style.
(In reply to han.wu from comment #0) > two layer where work ok, why single where work error? > > example one: > > program test > real :: x(3) = 1, y(3) = 2 > logical :: m(3) = .true., m2(3) = .false. > where (m) > x = f1() > end where > if (any(x/=3)) then > print *, 'FAIL', x > else > print *,'ok' > end if > contains > function f1() > m = .false. > !m2 = .true. > f1 = 3 > end function > end > > gfortran-12: > ASM generation compiler returned: 0 > Execution build compiler returned: 0 > Program returned: 0 > FAIL 3.00000000 1.00000000 1.00000000 > Well, this is simple to understand. The WHERE is eventually translated by gfc_trans_where_3() from trans-stmt.cc. What is essentially happening is that (in pseudo-code) the WHERE is converted to do i = 1, size(m) if (m(i)) then m = .false. ! This resets all elements of m! x(i) = 3 end if end do where I have in-lined the function f1. Looking in gfc_trans_where_3() we see that gfortran should create a temporary when scalarizing the mask. I don't know how to do that. When you come up with a patch, can you submit it?