Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Finalization: what is the status in Intel Fortran?

FortranFan
Honored Contributor II
742 Views

I was hoping to post a comment on topic #516177 (see link below) with the question on the subject line, but I see that topic is closed; hence this new thread:

https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/516177

In that topic from June 2014, Steve mentions in post #4 the changes to finalization in Fortran 2008.  It appears quite a few aspects have been updated/modified/deleted as part of combined corrigenda (1 thru' 3) for Fortran 2008.  Is it possible to get a status summary on finalization in Intel Fortran, specifically with respect to "section 4.5.6.3 When finalization occurs" from Fortran 2008 standard?  That is, what all changes which are part of the Fortran 2008 corrigenda have been implemented in Intel Fortran, if any?

Thanks,

0 Kudos
14 Replies
Steven_L_Intel1
Employee
742 Views

Do you have a specific change you want investigated? Otherwise your question is so broad it will take me a long time to research.

0 Kudos
FortranFan
Honored Contributor II
742 Views

Steve,

Thanks.  I need to provide some input for an internal discussion on memory leaks with derived types in Fortran and toward this, I would like to turn in a table as shown below.  If you or the Intel development team can fill it out by the time of 17.0 official release or within a few weeks thereafter, it will help greatly.  That is, just yes/no status of what development thinks has been implemented from Fortran 2008 based on combined corrigenda.

final.png

Note in the above table, by the row corresponding to "Deleted", I mean if Intel Fortran had the feature implemented per Fortran 2003 (also, initial Fortran 2008) but later removed it based on F08 corrigenda, we would like yes/no confirmation of it.

Thanks much,

0 Kudos
Steven_L_Intel1
Employee
742 Views

Ok, I'll start work on this when I get back to the office next week.

0 Kudos
Steven_L_Intel1
Employee
742 Views

Here is what the current Fortran 2015 draft says about finalization. As best as I can tell, the current compiler does all of these.

16 4.5.6.3 When finalization occurs

17 1 When an intrinsic assignment statement is executed (7.2.1.3), if the variable is not an unallocated allocatable
18 variable, it is finalized after evaluation of expr and before the definition of the variable. If the variable is an
19 allocated allocatable variable that would be deallocated by intrinsic assignment, the finalization occurs before the
20 deallocation.

21 2 When a pointer is deallocated its target is finalized. When an allocatable entity is deallocated, it is finalized
22 unless it is the variable in an intrinsic assignment statement or a component thereof. If an error condition occurs
23 during deallocation, it is processor dependent whether finalization occurs.

24 3 A nonpointer, nonallocatable object that is not a dummy argument or function result is finalized immediately
25 before it would become undefined due to execution of a RETURN or END statement (16.6.6, item (3)).

26 4 A nonpointer nonallocatable local variable of a BLOCK construct is finalized immediately before it would become
27 undefined due to termination of the BLOCK construct (16.6.6, item (23)).

28 5 If an executable construct references a nonpointer function, the result is finalized after execution of the innermost
29 executable construct containing the reference.

30 6 If a specification expression in a scoping unit references a function, the result is finalized before execution of the
31 executable constructs in the scoping unit.

32 7 When a procedure is invoked, a nonpointer, nonallocatable, INTENT (OUT) dummy argument of that procedure
33 is finalized before it becomes undefined. The finalization caused by INTENT (OUT) is considered to occur within
34 the invoked procedure; so for elemental procedures, an INTENT (OUT) argument will be finalized only if a scalar
35 or elemental final subroutine is available, regardless of the rank of the actual argument.

36 8 If an object is allocated via pointer allocation and later becomes unreachable due to all pointers associated with
1  that object having their pointer association status changed, it is processor dependent whether it is finalized. If it
2 is finalized, it is processor dependent as to when the final subroutines are called.

It is important to note that temporary objects created by the compiler - such as copies made for a VALUE argument - are never finalized. In other words, if you didn't have the chance to "construct" the value, it can't be finalized.

0 Kudos
FortranFan
Honored Contributor II
741 Views

Steve Lionel (Intel) wrote:

Here is what the current Fortran 2015 draft says about finalization. As best as I can tell, the current compiler does all of these.

16 4.5.6.3 When finalization occurs

17 1 When an intrinsic assignment statement is executed (7.2.1.3), if the variable is not an unallocated allocatable
18 variable, it is finalized after evaluation of expr and before the definition of the variable. If the variable is an
19 allocated allocatable variable that would be deallocated by intrinsic assignment, the finalization occurs before the
20 deallocation.

21 2 When a pointer is deallocated its target is finalized. When an allocatable entity is deallocated, it is finalized
22 unless it is the variable in an intrinsic assignment statement or a component thereof. If an error condition occurs
23 during deallocation, it is processor dependent whether finalization occurs.

24 3 A nonpointer, nonallocatable object that is not a dummy argument or function result is finalized immediately
25 before it would become undefined due to execution of a RETURN or END statement (16.6.6, item (3)).

26 4 A nonpointer nonallocatable local variable of a BLOCK construct is finalized immediately before it would become
27 undefined due to termination of the BLOCK construct (16.6.6, item (23)).

28 5 If an executable construct references a nonpointer function, the result is finalized after execution of the innermost
29 executable construct containing the reference.

30 6 If a specification expression in a scoping unit references a function, the result is finalized before execution of the
31 executable constructs in the scoping unit.

32 7 When a procedure is invoked, a nonpointer, nonallocatable, INTENT (OUT) dummy argument of that procedure
33 is finalized before it becomes undefined. The finalization caused by INTENT (OUT) is considered to occur within
34 the invoked procedure; so for elemental procedures, an INTENT (OUT) argument will be finalized only if a scalar
35 or elemental final subroutine is available, regardless of the rank of the actual argument.

36 8 If an object is allocated via pointer allocation and later becomes unreachable due to all pointers associated with
1  that object having their pointer association status changed, it is processor dependent whether it is finalized. If it
2 is finalized, it is processor dependent as to when the final subroutines are called.

It is important to note that temporary objects created by the compiler - such as copies made for a VALUE argument - are never finalized. In other words, if you didn't have the chance to "construct" the value, it can't be finalized.

Thanks, Steve, for your feedback.  A few questions:

  1. This one only if you remember readily: is the draft text you refer to from WD 1539-1 J3-16-007r1 document dated 1 May 2016 for Fortran 2015, or an even more recent draft?
  2. If you look at the table in Message #3, in particular the four "deleted" items pertaining to Corrigenda for Fortran 2008, have they made it into Intel Fortran as well?  My understanding is the Fortran 2003 standard said things one way, Fortran 2008 first publication had the same text, and changes then came about following interps as Corrigendum 1 thru' 3, and Fortran 2015 retains the same as Combined Corrigenda as Fortran 2008.  What impact did this have on Intel Fortran, meaning the implementation matched straight away with current draft, or did it initially follow Fortran 2003 and was later modified to agree with the current draft?
  3. Most importantly a question on what happens when one constructs a 'finalizable' type using module procedure in a generic interface that has the same as the type as in foo = my_type(..): is a temporary object created that gets assigned to the variable (foo) in an intrinsic assignment?  And if yes, what do you think the standard says about finalization here about the temporary object?  In other words, does the text from para 5 or 6 regarding function reference from the draft come into play since =my_type(..) invokes a module procedure with matching argument in the generic interface for my_type?  Or what the text says about structure constructors and/or your comments about temporary objects apply here?

Thanks again,

0 Kudos
IanH
Honored Contributor II
742 Views

A function that is referenced instead of a structure constructor is still a function - if the function result is finalizable, then it will be finalized after the assignment statement (or other relevant construct) concludes.

Structure constructor "overloading" is really just represents some exceptions around the name and name resolution rules - if two things have the same name in an expression context then those rules let you figure out what the code is referring to.  Once it has been resolved what the code references, then things proceed as if the code had been referencing that thing all along.

0 Kudos
Steven_L_Intel1
Employee
742 Views

1. That's the one I used - there is not yet a more recent one (probably not until September.)

2. Sorry, that would take me more time to research than I have cycles for at present.

3. In your example, that function result gets finalized before it becomes undefined. I believe this is covered by paragraph 5. (p6 is for specification expressions.) Your function created the object, it is not a compiler temp.

0 Kudos
FortranFan
Honored Contributor II
742 Views

Thanks IanH and Steve.

Steve, will it be possible to answer question #2 in Message #6 in a few months, say by October?  As I mentioned earlier, I am hoping to participate in an internal meeting during late Fall where features toward memory management, garbage collection, etc. are up for discussion in connection with technical computing and am striving to get some attention toward Fortran capabilities as well (I don't know if they will oblige but I thought I'll prepare something nonetheless).  I can probably create some tests and run some checks, but I worry about being misled either by unimplemented aspects in Intel Fortran from 2008 corrigenda and/or bugs.  Hence I would like to understand what the 'expected' position is on ifort on this matter.

Given IanH's comment, "A function that is referenced instead of a structure constructor is still a function" and Steve's comment, "In your example, that function result gets finalized before it becomes undefined, "

  • I take it to mean Note 4.48 from the standard where it says "If finalization is used for storage management, it often needs to be combined with defined assignment" becomes particularly relevant if one wants to use functions (as in a generic interface with the same name as the type) to construct derived types that have POINTER components and which are finalizable.  Any thoughts/comments on this?
0 Kudos
IanH
Honored Contributor II
742 Views

I think that note stands on its own.  It describes the practical requirement for correct handling of objects, once an object has been validly constructed (general term) in whatever way.  You can't stop client programmers from writing assignment statements that involve your objects in Fortran, so it is a good idea to provide meaningful behaviour for those assignment statements.  If you could stop programmers writing assignment statements involving your objects, then you wouldn't need to provide defined assignment, because it would never be invoked.

An overloaded structure constructor is just a naming convenience for an encapsulated way of validly constructing an object that might be exposed to client code - it is convenient because the name to use is the same as the name of the type, so you only have to remember one name.  But there is no need to name a function that validly constructs an object the same as the name of the type, nor is there a need to use a function - the thing that does the construction of a valid object could be a subroutine (which might be preferred if you want to return something other than just a validly constructed object - such as a construction success/failure flag or similar).

(I haven't checked in the last two months or so, but certainly prior to that, overloading structure constructors with ifort was problematic - the compiler would get rather confused with examples involving host association of a use associated name and go on to do silly things.  The workaround is to just rename the generic name for the constructing function to be something other than the type name, because that's all the overloading is - a naming convenience.)

Typically storage management would involve a pointer component or similar.  A structure constructor (proper) for an object with a pointer component cannot allocate a target for that component - it can only associate it with an existing target, and, if you are in a scope where the type is being use associated, it can only do that for PUBLIC components.  Those aspects tend to prevent use of proper structure constructors to validly construct an object for this use case - typically valid construction does the allocation of the relevant storage, and typically the component referencing the storage is PRIVATE.

(Splitting hairs a little about Steve's other words, only because I think this is a problematic gap in the language - but if you have an allocatable object, and a client programmer defines that allocatable object using ALLOCATE(allocatable_object, SOURCE=something_else), then, from the perspective of a library writer providing types for use by clients, there is no opportunity to "construct" the value of the allocatable object - it just gets the value of something_else.  However the allocatable object will still be finalized.  This will break types that are used for storage management, in the same way as if the library programmer did not provide defined assignment and client programmers continued to write assignment statements involving the relevant objects.)

0 Kudos
Steven_L_Intel1
Employee
742 Views

In the case Ian describes, if your type depends on maintaining internal counters, etc., you don't want to let users do arbitrary allocations. Provide helper routines/constructors that do the allocation and make the necessary components of the type private.

0 Kudos
IanH
Honored Contributor II
741 Views

Steve Lionel (Intel) wrote:

In the case Ian describes, if your type depends on maintaining internal counters, etc., you don't want to let users do arbitrary allocations. Provide helper routines/constructors that do the allocation and make the necessary components of the type private.

If that's referring to the issues with ALLOCATE(xxx, SOURCE=other), you can't stop users doing arbitrary allocations, you can only ask them not to, via library documentation or similar.

0 Kudos
Steven_L_Intel1
Employee
741 Views

Yes, you're right, Ian. Thanks for the correction.

0 Kudos
Steven_L_Intel1
Employee
741 Views

I did some experiments with version 12.1 - the oldest I have available. That version did not finalize structure constructors or array constructors, so I would take the position that we never finalized the things that the standard now says we shouldn't finalize.

0 Kudos
FortranFan
Honored Contributor II
741 Views

Steve Lionel (Intel) wrote:

I did some experiments with version 12.1 - the oldest I have available. That version did not finalize structure constructors or array constructors, so I would take the position that we never finalized the things that the standard now says we shouldn't finalize.

Thanks, Steve, for your follow-up.  I'll proceed assuming above.

Also, thanks IanH and Steve for comments on structure construction, assignments, and allocation.  My understanding and views on such matters are still primitive, but presently I'm inclined toward hoping the next Fortran standard (the one following the current draft 2015) includes mechanisms that facilitate a library designer (of a class/derived type in Fortran) to have somewhat better control over what the consumers can do re: construction, assignment, and allocation of objects, at least in line with how other programming languages with such facilities are utilized in technical computing.  Ultimately, there is no other way to prevent the users from doing things that are specifically unintended with respect to a library's design.  Documentation, training, etc.are important but, as you all know, users of the library are best assisted by compile-time diagnosis as much as possible, or at the very least structured exception handling during run-time.  The more the language standard can help in this regard, the better.  Understandably it would have been rather difficult to include all such details in Fortran 2003 when object-oriented facilities were first introduced or even in 2008 or 2015 given the varied levels of compiler support for such features resulting in limited use of these features.  But hopefully the next major revision will follow a good review and contemplation on such matters. 

0 Kudos
Reply