! { dg-do run } ! ! Test the fix for pr88735. ! ! Contributed by Martin Stein ! ! NOTE: Is incorrectly finalizing 'var' in a defined assignment (IMHO) to comply with ! behaviour of another brand. Will consult with vendor to come to an agreement as to ! the correct interpretation. ! F2018 7.5.6.3 paragraph 1 is explicit that it is only 'var' in intrinsic assignments ! that are finalized. The only finalization that occurs in the two assignments, a=b, ! is to the INTENT(OUT) dummy in 'set'. module mod implicit none type, public :: t integer, pointer :: i => NULL () character :: myname = 'z' character :: alloc = 'n' contains procedure, public :: set generic, public :: assignment(=) => set final :: finalise end type t integer, public :: assoc_in_final = 0 integer, public :: calls_to_final = 0 character, public :: myname1, myname2 contains subroutine set(self, x) class(t), intent(out) :: self class(t), intent(in) :: x if (associated(self%i)) then stop 1 ! Default init for INTENT(OUT) endif if (associated(x%i)) then myname2 = self%myname self%i => x%i self%i = self%i + 1 end if end subroutine set subroutine finalise(self) type(t), intent(inout) :: self calls_to_final = calls_to_final + 1 myname1 = self%myname if (associated(self%i)) then assoc_in_final = assoc_in_final + 1 if (self%alloc .eq. 'y') deallocate (self%i) end if end subroutine finalise end module mod program finalise_assign use mod implicit none type :: s integer :: i = 0 type(t) :: x end type s type(s) :: a, b type(t) :: c a%x%myname = 'a' b%x%myname = 'b' c%myname = 'c' allocate (a%x%i) a%x%i = 123 a%x%alloc = 'y' b = a if (assoc_in_final /= 0) stop 2 ! b%x%i not associated before finalization if (calls_to_final /= 2) stop 3 ! Two finalization calls (Should be one?) if (myname1 .ne. 'b') stop 4 ! Finalization before intent out become undefined if (myname2 .ne. 'z') stop 5 ! Intent out now default initialized if (.not.associated (b%x%i, a%x%i)) stop 6 allocate (c%i, source = 789) c%alloc = 'y' c = a%x if (assoc_in_final /= 1) stop 6 ! c%i is allocated prior to the assignment if (calls_to_final /= 3) stop 7 ! One finalization call for the assignment if (myname1 .ne. 'c') stop 8 ! Finalization before intent out become undefined if (myname2 .ne. 'z') stop 9 ! Intent out now default initialized b = a if (assoc_in_final /= 3) stop 10 ! b%i is associated by earlier assignment if (calls_to_final /= 5) stop 11 ! Two finalization calls for the assignment (Should be one?) if (myname1 .ne. 'z') stop 12 ! b%x%myname was default initialized in earlier assignment if (myname2 .ne. 'z') stop 13 ! Intent out now default initialized if (b%x%i .ne. 126) stop 14 ! Three assignments with self%x%i pointing to same target deallocate (a%x%i) if (.not.associated (b%x%i, c%i)) then stop 15 ! ditto b%x%i =>NULL () ! Although not needed here, clean up c%i => NULL () endif end program finalise_assign