aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gfortran.dg/finalize_45.f90
blob: 0819cf6e1681d569da3a62adefd32779ded9373d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
! { dg-do run }
!
! Test the fix for PR84472 in which the finalizations around the
! assignment in 'mymain' were not happening.
!
! Contributed by Vipul Parekh  <fortranfan@outlook.com>
!
module m

   use, intrinsic :: iso_fortran_env, only : output_unit

   implicit none

!   private

   integer, public :: final_counts = 0
   integer, public :: assoc_counts = 0

   type :: t
      private
      character(len=:), pointer :: m_s => null()
   contains
      private
      final :: final_t
      procedure, pass(this), public :: clean => clean_t
      procedure, pass(this), public :: init => init_t
      procedure, public :: assign_t
      generic, public :: ASSIGNMENT(=) => assign_t
   end type

   interface t
      module procedure :: construct_t
   end interface

   public :: t, assign_t

contains

   impure elemental subroutine assign_t (to, from)
     class(t), intent(out) :: to
     class(t), intent(in) :: from
     if (associated (from%m_s)) then
        allocate(to%m_s, source = from%m_s)
     else
        allocate(to%m_s, source = "new")
     endif
   end subroutine assign_t

   function construct_t( name ) result(new_t)

      ! argument list
      character(len=*), intent(in), optional :: name
      ! function result
      type(t) :: new_t

      if ( present(name) ) then
         call new_t%init( name )
      end if

   end function

   subroutine final_t( this )

      ! argument list
      type(t), intent(inout) :: this

      final_counts = final_counts + 1
      if ( associated(this%m_s) ) then
         assoc_counts = assoc_counts + 1
      endif
      call clean_t( this )

   end subroutine

   subroutine clean_t( this )

      ! argument list
      class(t), intent(inout) :: this

      if ( associated(this%m_s) ) then
         print *, this%m_s
         deallocate( this%m_s )
      end if
      this%m_s => null()

   end subroutine

   subroutine init_t( this, mname )

      ! argument list
      class(t), intent(inout)      :: this
      character(len=*), intent(in) :: mname

      call this%clean()
      allocate(character(len(mname)) :: this%m_s)
      this%m_s = mname

   end subroutine

end module
   use m, only : final_counts, assoc_counts
   call mymain
! See comment below.
   if (final_counts /= 3) stop 1
   if (assoc_counts /= 2) stop 2

contains
   subroutine mymain

   use m, only : t

   implicit none

   character(3), allocatable, target :: myname

   type(t) :: foo

   call foo%init( mname="123" )

   myname = "foo"
   foo = t( myname )

   call foo%clean()

! NAGFOR has assoc_counts =2, which is probably correct. If nullification
! of the pointer component is not done in gfortran, function finalization
! results in a double free. TODO fix this.
   if (final_counts /= 2) stop 3
   if (assoc_counts /= 2) stop 4
   end
end