Follow-up to PR 46174 (comment #2). Test case: implicit none type t end type t type, extends(t) :: t2 integer, allocatable :: all(:) end type t2 class(t), allocatable :: a allocate(t2 :: a) select type(a) type is (t2) allocate(a%all(1000000)) end select deallocate(a) end The deallocation occurs according to the declared type (not the dynamic type), i.e. the allocatable components of t2 are not being deallocated. Solution: Add a $free component to the vtab, which points to a deallocation procedure.
Note: There are four cases where a polymorphic deallocate is needed - though some might end up in the same code path: - explicit DEALLOCATE (cf. comment 0) - implicit deallocate at the end of the scope - implicit deallocate via INTENT(OUT) (cf. PR 47637) - implicit deallocate when doing polymorphic reallocate on assignment (PR 43366)
(In reply to comment #1) > Note: There are four cases where a polymorphic deallocate is needed - though > some might end up in the same code path: > > - explicit DEALLOCATE (cf. comment 0) > - implicit deallocate at the end of the scope > - implicit deallocate via INTENT(OUT) (cf. PR 47637) > - implicit deallocate when doing polymorphic reallocate on assignment (PR > 43366) Some more things we need to consider: * explicit deallocation with STAT or ERRMSG * deallocation of allocatable components (explicit/implicit)
For MOVE_ALLOC one also needs to do a polymorphic deallocation.
Remember also to update the component handling, cf. PR 51972 comment 3.
(In reply to comment #1) > Note: There are four cases where a polymorphic deallocate is needed - though > some might end up in the same code path: > > - explicit DEALLOCATE (cf. comment 0) > - implicit deallocate at the end of the scope > - implicit deallocate via INTENT(OUT) (cf. PR 47637) > - implicit deallocate when doing polymorphic reallocate on assignment (PR > 43366) Looks to me like work on FINAL needs to be interfaced here anyway. Naive view is that $free points to a FINAL if there is one, or to a default when there's no FINAL, but the hookup work is the same..
(In reply to comment #5) > Looks to me like work on FINAL needs to be interfaced here anyway. Naive view > is that $free points to a FINAL if there is one, or to a default when there's > no FINAL, but the hookup work is the same.. Yes, in principle I would agree with this view. Therefore implementing 'plain' polymorphic deallocation would be the logical fist step to FINAL.
Comment 0 has apparently been fixed by r199643. One should check whether the remaining items are also handled correctly already (in particular comments 1 - 3).
Indeed all the items from comment 1 to 3 seems to be handled. Below is a test case, whose dump shows a _final call being created for all of them. The only exception is realloc-on-assignment, which is not implemented yet for CLASS variables, but there is PR 43366 to track that. Therefore this PR can be closed, I think. program p type t end type t type u class(t), allocatable :: c end type class(t), allocatable :: a,b type(u), allocatable :: uu integer :: i character(len=100) :: str allocate(a,b,uu) ! (1) explicit deallocation deallocate(a) ! (4) STAT and ERRMSG deallocate(a,stat=i,errmsg=str) if (i/=0) print *,i,str ! (5) dealloc of comp. deallocate(uu) ! (6) move_alloc call move_alloc(b,a) contains subroutine out (x) ! (2) intent(out) class(t), intent(out) :: x end subroutine subroutine sub () ! (3) out of scope class(t), allocatable :: local allocate(local) end subroutine end