- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I don't know if Fortran is expected to behave this way, but when I compile and run the folllowing program,
module object_type_module
implicit none
type :: object_type
logical :: variable = .true.
contains
final :: finalize_object
end type object_type
interface object_type
procedure return_object
end interface object_type
contains
function return_object() result(object)
implicit none
type(object_type) :: object
print *, 'Inside return_object:', object%variable
object%variable = .true.
end function return_object
subroutine finalize_object(object)
implicit none
type(object_type) :: object
print *, 'Inside finalize_object:', object%variable
end subroutine finalize_object
end module object_type_module
program allocation_finalization
implicit none
call allocate_object_automatically()
contains
subroutine allocate_object_automatically()
use object_type_module, only : object_type
implicit none
type(object_type), allocatable :: object
print *, 'Before automatic allocation.'
object = object_type()
print *, 'After automatic allocation.'
end subroutine allocate_object_automatically
end program allocation_finalization
on my Ubuntu 20.10 with ifort version 2021.1, the result is
Before automatic allocation.
Inside return_object: T
Inside finalize_object: F
Inside finalize_object: T
After automatic allocation.
Inside finalize_object: T
The results lead me to think that the deallocated object on the left-hand-side of object = object_type() gets finalized during the function call. This since finalization is done three times, with object%variable evaluating as false once (non-allocatable object%variable is deallocated because object is deallocated?).
The behavior seems to go against the description of the FINAL Statement in the Developer Guide and Reference , which includes the statement:
"If the variable of an intrinsic assignment is not an unallocated allocatable array when the statement is executed, the variable is finalized after the expression on the right-hand side (RHS) is evaluated and before the variable is defined."
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, reported cases were not fixed yet. I have added this report as well.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think what is happening instead is that the finalizer is being called twice for the type constructor (which calls your return_object function). I recently reported a similar bug (CMPLRIL0-33567) for a "normal" type constructor. The first time the finalizer is called, it is passed uninitialized storage. The following modification to your program demonstrates this:
module object_type_module
implicit none
type :: object_type
integer :: variable = 314159
contains
final :: finalize_object
end type object_type
interface object_type
procedure return_object
end interface object_type
contains
function return_object() result(object)
implicit none
type(object_type) :: object
print *, 'Inside return_object:', object%variable
object%variable = 271828
end function return_object
subroutine finalize_object(object)
implicit none
type(object_type) :: object
print *, 'Inside finalize_object:', object%variable
end subroutine finalize_object
end module object_type_module
program allocation_finalization
implicit none
call allocate_object_automatically()
contains
subroutine allocate_object_automatically()
use object_type_module, only : object_type
implicit none
type(object_type), allocatable :: object
print *, 'Before automatic allocation.'
object = object_type()
print *, 'After automatic allocation.'
end subroutine allocate_object_automatically
end program allocation_finalization
Before automatic allocation.
Inside return_object: 314159
Inside finalize_object: 1869762652
Inside finalize_object: 271828
After automatic allocation.
Inside finalize_object: 271828
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I don't have access to the Fortran standard, but was led to think that the left-hand-side should be be finalized during assignment by this StackOverflow answer , which quotes from page 282 in the Modern Fortran Explained book:
"When a finalizable object is about to cease to exist (for example, by being deallocated or from execution of a return
statement), the final subroutine is invoked with the object as its actual argument. This also occurs when the object is passed to an intent out
dummy argument, or is the variable on the left-hand side of an intrinsic assignment statement. In the latter case, the final subroutine is invoked after the expression on the right-hand side has been evaluated, but before it is assigned to the variable."
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
https://j3-fortran.org/doc/year/18/18-007r1.pdf can be considered a proxy for the standard document.
Per Section 7.5.6.3 "When finalization occurs" on page 80, paragraph 1 with the line starting at 17, the finalization is not indicated for an unallocated allocatable variable. 'Object' you show in the original post. is as an unallocated allocatable variable.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@FortranFan Ok, I agree that the standard is clear on this – unallocated allocatable objects should not be finalized. I suppose your example acts according to the standard (the LHS variable is not an unallocatable allocatable anymore, and should thus be finalized). I find it easier to imagine that our two examples behave similarly, and that the "check" for the allocation status of LHS has been overlooked before finalization, than the case where double finalization somehow occurs on the RHS only for allocatable objects.
Anyway, it seems like an extra incorrect finalization happens in the example I gave, regardless of whether it happens on the LHS or RHS. I submitted a support request to Intel, will update this thread if I get any response.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In case you're unaware, you may also want to keep in mind the Fortran Discourse site for general language discussions:
https://fortran-lang.discourse.group/
There is a thread on this site also on finalization in relation to GCC/gfortran compiler:
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, reported cases were not fixed yet. I have added this report as well.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Per my interpretation of the Fortran standard, Intel Fortran invocation of the finalizer for the 'object' on LHS - an unallocated allocatable variable - is not called for. This leads to the 3 invocations you notice
I have submitted support requests with Intel Fortran team at the Intel Online Service Center (https://supporttickets.intel.com/servicecenter?lang=en-US) to look into this. I did so recently and have also done so previously (a couple of times I think) but which appear to have gotten overlooked in all the shuffles with Intel toolsets.
If you have support, you may consider the same.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It's the RHS, not LHS, that is being incorrectly finalized.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Steve_Lionel wrote:
It's the RHS, not LHS, that is being incorrectly finalized.
Looking at the disassembly (albeit my knowledge here is poorer than a novice) and my prior analysis using code variations, I felt otherwise. Say with this change:
subroutine allocate_object_automatically()
use object_type_module, only : object_type
implicit none
type(object_type) :: object !<-- nonallocatable
The program output changes to the following:
Before automatic allocation.
Inside return_object: 314159
Inside finalize_object: 314159
Inside finalize_object: 271828
After automatic allocation.
Inside finalize_object: 271828
Note the 3rd line in output: 'Inside finalize_object: 314159' instead of some arbitrary output based on of '1869762652' as you reported earlier. Per disassembly and inference, this appears to me to correspond to the variable 'object' i.e., the LHS. That is, with ALLOCATABLE attribute of 'object', the output is arbitrary likely due to its undefined state. When the ALLOCATABLE attribute is removed for the 'object', it comes into existence using the default initialized value of the component 'variable' and the program output is consistently '314159'.
If it was RHS that was getting finalized twice, I don't think this will be the case. But I'm open to be proven wrong.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page