| ! { dg-do run } |
| ! |
| ! Test the fix for all three variants of PR82996, which used to |
| ! segfault in the original testcase and ICE in the testcases of |
| ! comments 1 and 2. |
| ! |
| ! Contributed by Neil Carlson <neil.n.carlson@gmail.com> |
| ! |
| module mod0 |
| integer :: final_count_foo = 0 |
| integer :: final_count_bar = 0 |
| end module mod0 |
| ! |
| ! This is the original testcase, with a final routine 'foo' but |
| ! but not in the container type 'bar1'. |
| ! |
| module mod1 |
| use mod0 |
| private foo, foo_destroy |
| type foo |
| integer, pointer :: f(:) => null() |
| contains |
| final :: foo_destroy |
| end type |
| type bar1 |
| type(foo) :: b(2) |
| end type |
| contains |
| impure elemental subroutine foo_destroy(this) |
| type(foo), intent(inout) :: this |
| final_count_foo = final_count_foo + 1 |
| if (associated(this%f)) deallocate(this%f) |
| end subroutine |
| end module mod1 |
| ! |
| ! Comment 1 was the same as original, except that the |
| ! 'foo' finalizer is elemental and a 'bar' finalizer is added.. |
| ! |
| module mod2 |
| use mod0 |
| private foo, foo_destroy, bar_destroy |
| type foo |
| integer, pointer :: f(:) => null() |
| contains |
| final :: foo_destroy |
| end type |
| type bar2 |
| type(foo) :: b(2) |
| contains |
| final :: bar_destroy |
| end type |
| contains |
| impure elemental subroutine foo_destroy(this) |
| type(foo), intent(inout) :: this |
| final_count_foo = final_count_foo + 1 |
| if (associated(this%f)) deallocate(this%f) |
| end subroutine |
| subroutine bar_destroy(this) |
| type(bar2), intent(inout) :: this |
| final_count_bar = final_count_bar + 1 |
| call foo_destroy(this%b) |
| end subroutine |
| end module mod2 |
| ! |
| ! Comment 2 was the same as comment 1, except that the 'foo' |
| ! finalizer is no longer elemental. |
| ! |
| module mod3 |
| use mod0 |
| private foo, foo_destroy, bar_destroy |
| type foo |
| integer, pointer :: f(:) => null() |
| contains |
| final :: foo_destroy |
| end type |
| type bar3 |
| type(foo) :: b(2) |
| contains |
| final :: bar_destroy |
| end type |
| contains |
| subroutine foo_destroy(this) |
| type(foo), intent(inout) :: this |
| final_count_foo = final_count_foo + 1 |
| if (associated(this%f)) deallocate(this%f) |
| end subroutine |
| subroutine bar_destroy(this) |
| type(bar3), intent(inout) :: this |
| final_count_bar = final_count_bar + 1 |
| do j = 1, size(this%b) |
| call foo_destroy(this%b(j)) |
| end do |
| end subroutine |
| end module mod3 |
| |
| program main |
| use mod0 |
| use mod1 |
| use mod2 |
| use mod3 |
| type(bar1) :: x |
| type(bar2) :: y |
| type(bar3) :: z |
| call sub1(x) |
| if (final_count_foo /= 2) stop 1 |
| if (final_count_bar /= 0) stop 2 |
| call sub2(y) |
| if (final_count_foo /= 6) stop 3 |
| if (final_count_bar /= 1) stop 4 |
| call sub3(z) |
| if (final_count_foo /= 8) stop 5 |
| if (final_count_bar /= 2) stop 6 |
| contains |
| subroutine sub1(x) |
| type(bar1), intent(out) :: x |
| end subroutine |
| subroutine sub2(x) |
| type(bar2), intent(out) :: x |
| end subroutine |
| subroutine sub3(x) |
| type(bar3), intent(out) :: x |
| end subroutine |
| end program |