Re: [Patch, fortran] PR37336 (Finalization) - [F03] Finish derived-type finalization

2022-02-08 Thread Paul Richard Thomas via Fortran
Hi Harald,

Thanks for giving the patch a whirl.


> the parent components as an array. I strongly suspect that, from reading
> > 7.5.6.2 paragraphs 2 and 3 closely, that ifort has it right. However,
> this
> > is another issue to come back to in the future.
>
> Could you specify which version of Intel you tried?
>

ifort (IFORT) 2021.1 Beta 20201112

>
> Testcase finalize_38.f90 fails for me with ifort 2021.5.0 with:
>
> 131
>

That's the point where the interpretation of the standard diverges. Ifort
uses the scalar finalization for the parent component, whereas gfortran
uses the rank 1. Thus the final count is different by one. I have a version
of the patch, where gfortran behaves in the same way as ifort.


> This test also fails with crayftn 11 & 12 and nagfor 7.0,
> but in a different place.
>



>
> (Also finalize_45.f90 fails with that version with something that
> looks like memory corruption, but that might be just a compiler bug.)
>

I take it 'that version' is of ifort? Mine does the same. I suspect that it
is one of the perils of using pointer components in such circumstances! You
will notice that I had to nullify pointer components when doing the copy.

>
> Thanks,
> Harald
>

Could you use the attached version of finalize_38.f90 with crayftn and NAG?
All the stop statements are replaced with prints. Ifort gives:
 131   3   2
 132   0   4
 133   5   6 |   0   0
 141   4   3
 151   7   5
 152   3   0
 153   0   0 |   1   3
 161  13   9
 162  20   0
 163   0   0 |  10  20
 171  14  11

Best regards

Paul
! { dg-do run }
!
! Test finalization on intrinsic assignment (F2018 (7.5.6.3))
!
module testmode
  implicit none

  type :: simple
integer :: ind
  contains
final :: destructor1, destructor2
  end type simple

  type, extends(simple) :: complicated
real :: rind
  contains
final :: destructor3, destructor4
  end type complicated

  integer :: check_scalar
  integer :: check_array(4)
  real :: check_real
  real :: check_rarray(4)
  integer :: final_count = 0

contains

  subroutine destructor1(self)
type(simple), intent(inout) :: self
check_scalar = self%ind
check_array = 0
final_count = final_count + 1
  end subroutine destructor1

  subroutine destructor2(self)
type(simple), intent(inout) :: self(:)
check_scalar = 0
check_array(1:size(self, 1)) = self%ind
final_count = final_count + 1
  end subroutine destructor2

  subroutine destructor3(self)
type(complicated), intent(inout) :: self
check_real = self%rind
check_array = 0.0
final_count = final_count + 1
  end subroutine destructor3

  subroutine destructor4(self)
type(complicated), intent(inout) :: self(:)
check_real = 0.0
check_rarray(1:size(self, 1)) = self%rind
final_count = final_count + 1
  end subroutine destructor4

  function constructor1(ind) result(res)
type(simple), allocatable :: res
integer, intent(in) :: ind
allocate (res, source = simple (ind))
  end function constructor1

  function constructor2(ind, rind) result(res)
class(simple), allocatable :: res(:)
integer, intent(in) :: ind(:)
real, intent(in), optional :: rind(:)
type(complicated), allocatable :: src(:)
integer :: sz
integer :: i
if (present (rind)) then
  sz = min (size (ind, 1), size (rind, 1))
  src  = [(complicated (ind(i), rind(i)), i = 1, sz)]
  allocate (res, source = src)
else
  sz = size (ind, 1)
  allocate (res, source = [(simple (ind(i)), i = 1, sz)])
end if
  end function constructor2

  subroutine test (cnt, scalar, array, off, rind, rarray)
integer :: cnt
integer :: scalar
integer :: array(:)
integer :: off
real, optional :: rind
real, optional :: rarray(:)
if (final_count .ne. cnt)  print *, 1 + off, final_count, cnt
if (check_scalar .ne. scalar) print *, 2 + off, check_scalar, scalar
if (any (check_array(1:size (array, 1)) .ne. array)) print *,  3 + off, &
   check_array(1:size (array, 1)), "|", array
if (present (rind)) then
  if (check_real .ne. rind)  print *,  4+off, check_real, rind
end if
if (present (rarray)) then
  if (any (check_rarray(1:size (rarray, 1)) .ne. rarray)) print *,  5 + off, &
   check_rarray(1:size (rarray, 1)), "|", rarray
end if
  end subroutine test

end module testmode

program test_final
  use testmode
  implicit none

  type(simple), allocatable :: MyType, MyType2
  type(simple), allocatable :: MyTypeArray(:)
  type(simple) :: ThyType = simple(21), ThyType2 = simple(22)
  class(simple), allocatable :: MyClass
  class(simple), allocatable :: MyCl

Re: [Patch, fortran] PR37336 (Finalization) - [F03] Finish derived-type finalization

2022-02-08 Thread Harald Anlauf via Fortran

Hi Paul,

Am 08.02.22 um 12:22 schrieb Paul Richard Thomas via Fortran:

Hi Harald,

Thanks for giving the patch a whirl.



the parent components as an array. I strongly suspect that, from reading

7.5.6.2 paragraphs 2 and 3 closely, that ifort has it right. However,

this

is another issue to come back to in the future.


Could you specify which version of Intel you tried?



ifort (IFORT) 2021.1 Beta 20201112


ok, that's good to know.



Testcase finalize_38.f90 fails for me with ifort 2021.5.0 with:

131

This test also fails with crayftn 11 & 12 and nagfor 7.0,
but in a different place.



I have run your modified version of finalize_38.f90, and now I see
that you can get a bloody head just from scratching too much...

crayftn 12.0.2:

 1,  3,  1
 2,  21,  0
 11,  3,  2
 12,  21,  1
 21,  4,  3
 23,  21,  22 | 42,  43
 31,  6,  4
 41,  7,  5
 51,  9,  7
 61,  10,  8
 71,  13,  10
 101,  2,  1
 102,  4,  3
 111,  3,  2
 121,  4,  2
 122,  0,  4
 123,  5,  6 | 2*0
 131,  5,  2
 132,  0,  4
 133,  7,  8 | 2*0
 141,  6,  3
 151,  10,  5
 161,  16,  9
 171,  18,  11
 175,  0.,  20. | 10.,  20.

nagfor 7.0:

 1 0 1
 11 1 2
 23 21 22 | 42 43
 71 9 10
 72 11 99
 131 3 2
 132 5 4
 141 4 3
 151 6 5
 161 10 9
 171 12 11

Intel 2021.5.0:

 131   3   2
 132   0   4
 133   5   6 |   0   0
 141   4   3
 151   7   5
 152   3   0
 153   0   0 |   1   3
forrtl: severe (174): SIGSEGV, segmentation fault occurred
[...]


That got me reading 7.5.6.3, where is says in paragraph 1:

"When an intrinsic assignment statement is executed (10.2.1.3), if the
variable is not an unallocated allocatable variable, it is finalized
after evaluation of expr and before the definition of the variable.
..."

Looking at the beginning of the testcase code (abridged):

  type(simple), allocatable :: MyType, MyType2
  type(simple) :: ThyType = simple(21), ThyType2 = simple(22)

! The original PR - one finalization of 'var' before (re)allocation.
  MyType = ThyType
  call test(1, 0, [0,0], 0)


This is an intrinsic assignment.

Naively I would expect MyType to be initially unallocated.

ThyType is not allocatable and non-pointer and cannot become
undefined here and would not play any role in finalization.

I am probably too blind-sighted to see why there should be
a finalization here.  What am I missing?


Could you use the attached version of finalize_38.f90 with crayftn and NAG?
All the stop statements are replaced with prints. Ifort gives:
  131   3   2
  132   0   4
  133   5   6 |   0   0
  141   4   3
  151   7   5
  152   3   0
  153   0   0 |   1   3
  161  13   9
  162  20   0
  163   0   0 |  10  20
  171  14  11


I think it is a good idea to have these prints in the testcase
whenever there is a departure from expectations.  So print&stop?

Furthermore, for the sake of health of people reading the testcases
later, I think it would not harm to add more explanations why we
expect a certain behavior... ;-)


Best regards

Paul


Best regards,
Harald


Re: [Patch, fortran] PR37336 (Finalization) - [F03] Finish derived-type finalization

2022-02-08 Thread Jerry D via Fortran
Remember the days when reading very old cryptic Fortran code? Remember 
the fixed line lengths and cryptic variable names!


I fear the Standards committee has achieved history with the Standard 
itself it is so difficult to understand sometimes.


Cheers to Paul and Harald for digging on this.

Jerry

On 2/8/22 11:29 AM, Harald Anlauf via Fortran wrote:

Hi Paul,

Am 08.02.22 um 12:22 schrieb Paul Richard Thomas via Fortran:

Hi Harald,

Thanks for giving the patch a whirl.


the parent components as an array. I strongly suspect that, from 
reading

7.5.6.2 paragraphs 2 and 3 closely, that ifort has it right. However,

this

is another issue to come back to in the future.


Could you specify which version of Intel you tried?



ifort (IFORT) 2021.1 Beta 20201112


ok, that's good to know.



Testcase finalize_38.f90 fails for me with ifort 2021.5.0 with:

131

This test also fails with crayftn 11 & 12 and nagfor 7.0,
but in a different place.



I have run your modified version of finalize_38.f90, and now I see
that you can get a bloody head just from scratching too much...

crayftn 12.0.2:

 1,  3,  1
 2,  21,  0
 11,  3,  2
 12,  21,  1
 21,  4,  3
 23,  21,  22 | 42,  43
 31,  6,  4
 41,  7,  5
 51,  9,  7
 61,  10,  8
 71,  13,  10
 101,  2,  1
 102,  4,  3
 111,  3,  2
 121,  4,  2
 122,  0,  4
 123,  5,  6 | 2*0
 131,  5,  2
 132,  0,  4
 133,  7,  8 | 2*0
 141,  6,  3
 151,  10,  5
 161,  16,  9
 171,  18,  11
 175,  0.,  20. | 10.,  20.

nagfor 7.0:

 1 0 1
 11 1 2
 23 21 22 | 42 43
 71 9 10
 72 11 99
 131 3 2
 132 5 4
 141 4 3
 151 6 5
 161 10 9
 171 12 11

Intel 2021.5.0:

 131   3   2
 132   0   4
 133   5   6 |   0   0
 141   4   3
 151   7   5
 152   3   0
 153   0   0 |   1   3
forrtl: severe (174): SIGSEGV, segmentation fault occurred
[...]


That got me reading 7.5.6.3, where is says in paragraph 1:

"When an intrinsic assignment statement is executed (10.2.1.3), if the
variable is not an unallocated allocatable variable, it is finalized
after evaluation of expr and before the definition of the variable.
..."

Looking at the beginning of the testcase code (abridged):

  type(simple), allocatable :: MyType, MyType2
  type(simple) :: ThyType = simple(21), ThyType2 = simple(22)

! The original PR - one finalization of 'var' before (re)allocation.
  MyType = ThyType
  call test(1, 0, [0,0], 0)


This is an intrinsic assignment.

Naively I would expect MyType to be initially unallocated.

ThyType is not allocatable and non-pointer and cannot become
undefined here and would not play any role in finalization.

I am probably too blind-sighted to see why there should be
a finalization here.  What am I missing?

Could you use the attached version of finalize_38.f90 with crayftn 
and NAG?

All the stop statements are replaced with prints. Ifort gives:
  131   3   2
  132   0   4
  133   5   6 |   0   0
  141   4   3
  151   7   5
  152   3   0
  153   0   0 |   1   3
  161  13   9
  162  20   0
  163   0   0 |  10  20
  171  14  11


I think it is a good idea to have these prints in the testcase
whenever there is a departure from expectations.  So print&stop?

Furthermore, for the sake of health of people reading the testcases
later, I think it would not harm to add more explanations why we
expect a certain behavior... ;-)


Best regards

Paul


Best regards,
Harald