blob: a8898fd7abf94a4f02eb5970e14d2e29fefafa07 [file] [log] [blame]
! { dg-do run }
! Tests the fic for PR44582, where gfortran was found to
! produce an incorrect result when the result of a function
! was aliased by a host or use associated variable, to which
! the function is assigned. In these cases a temporary is
! required in the function assignments. The check has to be
! rather restrictive. Whilst the cases marked below might
! not need temporaries, the TODOs are going to be tough.
!
! Reported by Yin Ma <yin@absoft.com> and
! elaborated by Tobias Burnus <burnus@gcc.gnu.org>
!
module foo
INTEGER, PARAMETER :: ONE = 1
INTEGER, PARAMETER :: TEN = 10
INTEGER, PARAMETER :: FIVE = TEN/2
INTEGER, PARAMETER :: TWO = 2
integer :: foo_a(ONE)
integer :: check(ONE) = TEN
LOGICAL :: abort_flag = .false.
contains
function foo_f()
integer :: foo_f(ONE)
foo_f = -FIVE
foo_f = foo_a - foo_f
end function foo_f
subroutine bar
foo_a = FIVE
! This aliases 'foo_a' by host association.
foo_a = foo_f ()
if (any (foo_a .ne. check)) call myabort (0)
end subroutine bar
subroutine myabort(fl)
integer :: fl
print *, fl
abort_flag = .true.
end subroutine myabort
end module foo
function h_ext()
use foo
integer :: h_ext(ONE)
h_ext = -FIVE
h_ext = FIVE - h_ext
end function h_ext
function i_ext() result (h)
use foo
integer :: h(ONE)
h = -FIVE
h = FIVE - h
end function i_ext
subroutine tobias
use foo
integer :: a(ONE)
a = FIVE
call sub1(a)
if (any (a .ne. check)) call myabort (1)
contains
subroutine sub1(x)
integer :: x(ONE)
! 'x' is aliased by host association in 'f'.
x = f()
end subroutine sub1
function f()
integer :: f(ONE)
f = ONE
f = a + FIVE
end function f
end subroutine tobias
program test
use foo
implicit none
common /foo_bar/ c
integer :: a(ONE), b(ONE), c(ONE), d(ONE)
interface
function h_ext()
use foo
integer :: h_ext(ONE)
end function h_ext
end interface
interface
function i_ext() result (h)
use foo
integer :: h(ONE)
end function i_ext
end interface
a = FIVE
! This aliases 'a' by host association
a = f()
if (any (a .ne. check)) call myabort (2)
a = FIVE
if (any (f() .ne. check)) call myabort (3)
call bar
foo_a = FIVE
! This aliases 'foo_a' by host association.
foo_a = g ()
if (any (foo_a .ne. check)) call myabort (4)
a = FIVE
a = h() ! TODO: Needs no temporary
if (any (a .ne. check)) call myabort (5)
a = FIVE
a = i() ! TODO: Needs no temporary
if (any (a .ne. check)) call myabort (6)
a = FIVE
a = h_ext() ! Needs no temporary - was OK
if (any (a .ne. check)) call myabort (15)
a = FIVE
a = i_ext() ! Needs no temporary - was OK
if (any (a .ne. check)) call myabort (16)
c = FIVE
! This aliases 'c' through the common block.
c = j()
if (any (c .ne. check)) call myabort (7)
call aaa
call tobias
if (abort_flag) STOP 1
contains
function f()
integer :: f(ONE)
f = -FIVE
f = a - f
end function f
function g()
integer :: g(ONE)
g = -FIVE
g = foo_a - g
end function g
function h()
integer :: h(ONE)
h = -FIVE
h = FIVE - h
end function h
function i() result (h)
integer :: h(ONE)
h = -FIVE
h = FIVE - h
end function i
function j()
common /foo_bar/ cc
integer :: j(ONE), cc(ONE)
j = -FIVE
j = cc - j
end function j
subroutine aaa()
d = TEN - TWO
! This aliases 'd' through 'get_d'.
d = bbb()
if (any (d .ne. check)) call myabort (8)
end subroutine aaa
function bbb()
integer :: bbb(ONE)
bbb = TWO
bbb = bbb + get_d()
end function bbb
function get_d()
integer :: get_d(ONE)
get_d = d
end function get_d
end program test