Bug 80524 - [F03] Problematic behaviour with a finalization subroutine in gfortran
Summary: [F03] Problematic behaviour with a finalization subroutine in gfortran
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 6.3.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks: Finalization
  Show dependency treegraph
 
Reported: 2017-04-26 09:59 UTC by Andrew Wood
Modified: 2019-03-28 20:34 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2017-04-26 00:00:00


Attachments
Fortran code with a finalize subroutine (217 bytes, text/plain)
2017-04-26 09:59 UTC, Andrew Wood
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Wood 2017-04-26 09:59:34 UTC
Created attachment 41268 [details]
Fortran code with a finalize subroutine

When I compile and run the attached code, the subroutine 't_final' gets called once.

> gfortran prog.f90 && ./a.out
 In SUBROUTINE t_final

The PGI compiler gives the same behaviour.

However, 't_final' is called three times when the Intel (v17.0.1) compiler is used:
> ifort prog.f90 && ./a.out
 In SUBROUTINE t_final
 In SUBROUTINE t_final
 In SUBROUTINE t_final

I initially assumed that Intel was wrong and sent them a bug report. (It's out-voted and the behaviour is unintuitive.) However, Intel claim that their behaviour is correct. I shall post Intel's response in a follow-up message.
Comment 1 Andrew Wood 2017-04-26 10:00:49 UTC
Intel's response:


Hello Andrew,

 

Our development team investigated the issue and determined the following:

 

---------------

Finalization is a tricky thing - there are many different events that trigger a call to a finalizer. Although it may not seem so at first, this program *should* call the finalizer 3 times, not once.

 

The first finalization occurs as a result of this line of code: u = new_t() Here, 'u' is finalized as a result of the following text from the F2008 standard:

   "When an intrinsic assignment statement is executed, the variable is finalized after evaluation of expr and before the definition of the variable."

'Variable' in this line of code is 'u'. Since this is an intrinsic assignment statement, 'u' is the first object to be finalized.

 

The second finalization occurs because of the same line of user code, but this time it's the result of 'new_t' that is finalized according to the following text:

 " If an executable construct references a function, the result is finalized after execution of the innermost executable construct containing the reference." 

Because of this rule, the result of the call to 'new_t' is finalized next.

 

The third finalization occurs at the end of routine 's'. The standard says:

"A nonpointer, nonallocatable object that is not a dummy argument or function result is finalized immediately before it would become undefined due to execution of a RETURN or END statement"  

 

The variable 'u' is a nonpointer, nonallocatable object that is not a dummy argument or function result, so it is finalized at the end of the routine 's'.

 

So the three calls to the finalizer are correct and the results from PGI Fortran are incorrect.

-------------------

 

Since this is not a Intel Fortran Compiler defect, I am closing this case. 

Do not hesitate to contact me if you have any other questions or need further assistance with Intel® Software Development Products. 

 

Thank you for contacting Intel® Online Service Center,

 

Devorah

Intel® Developer Support
Comment 2 Dominique d'Humieres 2017-04-26 13:18:35 UTC
Confirmed from 4.9 up to trunk (8.0).
Comment 3 Jerry DeLisle 2017-04-26 19:53:14 UTC
I think this depends a lot on the compiler implementation. Declaring a type does not define an instance of it. I can see that since new_t is returning a function result which could be a pointer, the compiler could end up only creating one instance.
Comment 4 janus 2017-05-01 12:42:44 UTC
(In reply to Jerry DeLisle from comment #3)
> I think this depends a lot on the compiler implementation.

I don't actually think the calling of finalization routines is supposed to depend on the compiler implementation. F08 is rather clear on where it should happen, I guess.

For the missing cases, see also:
* PR 64290 (No finalization at deallocation of LHS)
* PR 65347 (Final subroutine not called for function result)

and PR 37336 comment 27 which includes both of them.
Comment 5 Jerry DeLisle 2017-05-01 18:45:21 UTC
(In reply to janus from comment #4)
> (In reply to Jerry DeLisle from comment #3)
> > I think this depends a lot on the compiler implementation.
> 
> I don't actually think the calling of finalization routines is supposed to
> depend on the compiler implementation. F08 is rather clear on where it
> should happen, I guess.
> 
> For the missing cases, see also:
> * PR 64290 (No finalization at deallocation of LHS)
> * PR 65347 (Final subroutine not called for function result)
> 
> and PR 37336 comment 27 which includes both of them.

My only thought here is that those conditions may be A or B or C vs A and B and C

If the finalization is to for example deallocate something, would we end up trying to deallocate more than once? It seems to me that it depends on how many actual instances of the object were created.
Comment 6 Andrew Wood 2017-08-28 09:20:17 UTC
For info, the actual code I was developing did use the finalization subroutine to deallocate pointers, which resulted in seg faults when compiled with ifort. This was how I discovered the problem.

I also reported the problem to PGI. The latest version of pgfortran (17.7) now produces the same behaviour as ifort:

> pgfortran -V

pgfortran 17.5-0 64-bit target on x86-64 Linux -tp haswell 
PGI Compilers and Tools
Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved.

> pgfortran prog.f90 && ./a.out 
 In SUBROUTINE t_final




> pgfortran -V

pgfortran 17.7-0 64-bit target on x86-64 Linux -tp haswell 
PGI Compilers and Tools
Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved.

> pgfortran prog.f90 && ./a.out 
 In SUBROUTINE t_final
 In SUBROUTINE t_final
 In SUBROUTINE t_final
Comment 7 Jürgen Reuter 2018-10-05 09:26:29 UTC
This is still present in the actual trunk.