-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Finalization of class arrays; interpretation of standards #231
Comments
Hi @abensonca thanks for your work on gfortran and for asking here. Is your question the same as #146, or different? |
Hi @certik - I read through #146 and I don't think my question here is the same issue. In this case I'm not concerned about the order of the finalization. Instead my concern is whether it is ever correct to call a non |
I think Intel's behavior is incorrect as well. The process described in paragraph 7.5.6.2 (3) essentially recurses to (1), and I'm not aware of any other place in the standard that speaks to this. I compiled your example with the NAG 7.0 compiler and it behaves like you've described for gfortran. |
@abensonca (repeating what I wrote to you on Discourse) - the answer is that no, a non-ELEMENTAL final subroutine with a scalar argument should not be called elementally, and so ifort is broken. (And an ELEMENTAL final subroutine should be called only when there's no other final subroutine with a matching rank.) This applies at each level of typing, so if a parent type has (say) a rank-1 final subroutine, and an extension of that derived type has only an ELEMENTAL final subroutine, then a vector of the extended type will be finalized by calling the extended type's final subroutine for each element, and then the parent's final procedure will be called (once) for the parent component of the vector. |
Thanks @nncarlson and @klausler for your help on this. |
@abensonca wrote Sep 27, 2021 4:33 PM EDT:
For whatever it's worth and I'm open to being proved wrong on this: I think Intel Fortran's finalization process toward the code in the original post vis-a-vis the standard is entirely acceptable. Note the standard is (purposefully I think) not prescriptive when it comes to the finalization process, there is a desired end state of a finalized entity in the standard even as it is not clearly spelled out. Nonetheless the standard effectively permits the processors multiple pathways to arrive at that end state. Comparison of those pathways, which is what the original post attempts, is not particularly meaningful in this context, at least as the standard is currently written. Section 7.5.6.2 The finalization process in 18-007r1 document toward the 2018 standard by and large gives a lot of leeway to the processor and there are no numbered rules or constraints in this section enforcing the program or processor behavior. Taking into consideration the first paragraph in section 7.5.6.2 and the numbered bullets therein in conjunction with section 7.5.7 on type extension, a fair argument can be made the finalization process in the following code is analogous to the one in the original post: module m
type :: a_t
contains
final :: f_a_r0
end type
type :: b_t
type(a_t) :: a
contains
final :: f_b_r0, f_b_r1
end type
contains
subroutine f_a_r0( a )
type(a_t), intent(inout) :: a
print *, "finalizer rank-0 a_t"
end subroutine
subroutine f_b_r0( b )
type(b_t), intent(inout) :: b
print *, "finalizer rank-0 b_t"
end subroutine
subroutine f_b_r1( b )
type(b_t), intent(inout) :: b(:)
print *, "finalizer rank-1 b_t"
end subroutine
end module
use m
block
type(b_t) :: foo(3)
end block
end And for this, a standard-conforming processor can be expected to yield the following program behavior:
as does Intel Fortran and NAG Fortran (though not gfortran**). Ostensibly the 2 processors in this case simply follow the steps in section 7.5.6.2 and there is no argument to be made about any processor nonconformance with the simple code here. The key sentences in the standard are "If the entity being finalized is an array, each finalizable component of each element of that entity is finalized separately" followed by "If the entity is of extended type and the parent type is finalizable, the parent component is finalized" And what Intel Fortran does with the code in the original post is consistent with this and I think it is conformant with the standard. ** gfortran has gaps when it comes to finalization of nonallocatable but finalizable objects, the code here is an example of this. |
@FortranFan That does seem like a reasonable interpretation of the standard. And thanks for pointing out the limitation of gfortran with finalizing non-allocatable objects - I'll add this to my test cases and see if it's possible to fix this behavior. |
A follow-on to the above case:
The modified gfortran I'm working on outputs:
while ifort outputs:
The last statement in this example assigns to ifort's behavior seems broken here, but I'd be interested and grateful if anyone can show results for this code with NAG or other compilers for comparison. |
I'm working (with much help from Paul Thomas) on adding finalization on intrinsic assignment to gfortran. There are a few instances where I'm unclear on precisely what is required by the standard, so would be very grateful for any insight any one here can offer.
This example considers finalization of a class array:
With gfortran (including the patches for finalization on intrinsic assignment that I'm working on), this results in:
which shows that, when deallocating '
MyClassArray
', the rank-1 finalizer for the extended type 'complicated
' is called, and then the rank-1 finalizer for the parent type 'simple
' is called.But, under ifort I get:
showing that the rank-1 finalizer is called for the extended type, but then the scalar finalizer of the parent type is called twice, once for each element in the array.
ifort's behavior seems incorrect here (based on my reading of the F2018 standards), but I'd be interested to hear anyone's opinion on this.
Thanks,
Andrew
The text was updated successfully, but these errors were encountered: