Re: [Patch, fortran] PR37336 finalization
Hi Paul, I want to get something approaching correct finalization to the distros, which implies 12-branch at present. Hopefully I can do the same with associate in a month or two's time. OK by me then. (I just wanted to be sure that we had this discussion :-) Best regards Thomas
Re: [Patch, fortran] PR37336 finalization
Hi Paul, all, On 6/3/23 15:16, Paul Richard Thomas via Gcc-patches wrote: Hi Thomas, I want to get something approaching correct finalization to the distros, which implies 12-branch at present. Hopefully I can do the same with associate in a month or two's time. IMHO it is not only distros, but also installations at (scientific) computing centers with a larger user base and a large software stack. Migrating to a different major version of gcc/gfortran is not a trivial task for them. I'd fully support the idea of backporting the finalization fixes, as IIUC this on the one hand touches a rather isolated part, and on the other hand already got quite some testing. It is also already in the 13-branch (or only mostly?). Given that 12.3 was released recently and 12.4 is far away, there'd be sufficient time to fix any fallout. Regarding the associate fixes, we could get as much of those into 13.2, which we'd normally expect in just a few months. As long as spare time to work on gfortran is limited, I'd rather prefer to get as much fixed for that release. (This is not a no: I simply expect that real regression testing for the associate changes may take more time.) I am dithering about changing the F2003/08 part of finalization since the default is 2018 compliance. That said, it does need a change since the suppression of constructor finalization is also suppressing finalization of function results within the compilers. I'll do that first, perhaps? That sounds like a good idea. Cheers, Harald Cheers Paul On Sat, 3 Jun 2023 at 06:50, Thomas Koenig wrote: Hi Paul, I propose to backport r13-6747-gd7caf313525a46f200d7f5db1ba893f853774aee to 12-branch very soon. Is this something that we usually do? While finalization was basically broken before, some people still used working subsets (or subsets that were broken, and they adapted or wrote their code accordingly). What is the general opinion on that? I'm undecided. Before that, I propose to remove the F2003/2008 finalization of structure and array constructors in 13- and 14-branches. I can see why it was removed from the standard in a correction to F2008 and think that it is likely to cause endless confusion and maintenance complications. However, finalization of function results within constructors will be retained. That, I agree with. Should it be noted somewhere as an intentional deviation from the standard? Best regards Thomas -- "If you can't explain it simply, you don't understand it well enough" - Albert Einstein
Re: [Patch, fortran] PR37336 finalization
Hi Thomas, I want to get something approaching correct finalization to the distros, which implies 12-branch at present. Hopefully I can do the same with associate in a month or two's time. I am dithering about changing the F2003/08 part of finalization since the default is 2018 compliance. That said, it does need a change since the suppression of constructor finalization is also suppressing finalization of function results within the compilers. I'll do that first, perhaps? Cheers Paul On Sat, 3 Jun 2023 at 06:50, Thomas Koenig wrote: > > Hi Paul, > > > I propose to backport > > r13-6747-gd7caf313525a46f200d7f5db1ba893f853774aee to 12-branch very > > soon. > > Is this something that we usually do? > > While finalization was basically broken before, some people still used > working subsets (or subsets that were broken, and they adapted or > wrote their code accordingly). > > What is the general opinion on that? I'm undecided. > > > Before that, I propose to remove the F2003/2008 finalization of > > structure and array constructors in 13- and 14-branches. I can see why > > it was removed from the standard in a correction to F2008 and think > > that it is likely to cause endless confusion and maintenance > > complications. However, finalization of function results within > > constructors will be retained. > > That, I agree with. Should it be noted somewhere as an intentional > deviation from the standard? > > Best regards > > Thomas > -- "If you can't explain it simply, you don't understand it well enough" - Albert Einstein
Re: [Patch, fortran] PR37336 finalization
On Sat, Jun 03, 2023 at 07:50:19AM +0200, Thomas Koenig via Fortran wrote: > Hi Paul, > > > I propose to backport > > r13-6747-gd7caf313525a46f200d7f5db1ba893f853774aee to 12-branch very > > soon. > > Is this something that we usually do? > > While finalization was basically broken before, some people still used > working subsets (or subsets that were broken, and they adapted or > wrote their code accordingly). > > What is the general opinion on that? I'm undecided. > I think a backport that fixes a bug that is a violation of Fortran standard is always okay. A backport of anything else is up to the discretion of the contributor. If pault or you or harald or ... want to backport a patch, after all these years, I think we should trust their judgement. -- Steve
Re: [Patch, fortran] PR37336 finalization
Hi Paul, I propose to backport r13-6747-gd7caf313525a46f200d7f5db1ba893f853774aee to 12-branch very soon. Is this something that we usually do? While finalization was basically broken before, some people still used working subsets (or subsets that were broken, and they adapted or wrote their code accordingly). What is the general opinion on that? I'm undecided. Before that, I propose to remove the F2003/2008 finalization of structure and array constructors in 13- and 14-branches. I can see why it was removed from the standard in a correction to F2008 and think that it is likely to cause endless confusion and maintenance complications. However, finalization of function results within constructors will be retained. That, I agree with. Should it be noted somewhere as an intentional deviation from the standard? Best regards Thomas
Re: [Patch, fortran] PR37336 finalization
Hi All, I propose to backport r13-6747-gd7caf313525a46f200d7f5db1ba893f853774aee to 12-branch very soon. Before that, I propose to remove the F2003/2008 finalization of structure and array constructors in 13- and 14-branches. I can see why it was removed from the standard in a correction to F2008 and think that it is likely to cause endless confusion and maintenance complications. However, finalization of function results within constructors will be retained. If there are any objections, please let me know. Paul
Re: [Patch, fortran] PR37336 finalization
On Tue, Mar 07, 2023 at 03:58:32PM +0100, Thomas Koenig via Fortran wrote: > Paul, > > first of all, thank you very much indeed for the hard work you put into > this! This is a great step for gfortran. Ditto**2 > > I can hurry this along to get the patch > > into 13-branch or I can wait until 14-branch opens. > > Personally, I think that this fixes so many bugs, and makes > the compiler so much better, that I would prefer having it > in gcc-13. Finalization was only of very limited use before, > and the risk of meaningful regressions (short of a build > failure) is therefore very low. > I agree with Thomas. The main branch is in stage 4, which is regression and documentation fixing mode. I would think the number of bugs fixed by your patch can be argued as fixing regressions. I can set aside some time on Saturday to help with a review (if required). -- Steve
Re: [Patch, fortran] PR37336 finalization
Paul, first of all, thank you very much indeed for the hard work you put into this! This is a great step for gfortran. I can hurry this along to get the patch into 13-branch or I can wait until 14-branch opens. Personally, I think that this fixes so many bugs, and makes the compiler so much better, that I would prefer having it in gcc-13. Finalization was only of very limited use before, and the risk of meaningful regressions (short of a build failure) is therefore very low. Again, thanks a lot! Best regards Thomas
Re: [Patch, fortran] PR37336 (Finalization) - [F03] Finish derived-type finalization
For what it is worth. On 2/10/22 11:49 AM, Harald Anlauf via Fortran wrote: Hi Paul, Am 10.02.22 um 13:25 schrieb Paul Richard Thomas via Fortran: Conclusions on ifort: (i) The agreement between gfortran, with the patch applied, and ifort is strongest of all the other brands; (ii) The disagreements are all down to the treatment of the parent component of arrays of extended types: gfortran finalizes the parent component as an array, whereas ifort does a scalarization. I have a patch ready to do likewise. Overall conclusions: (i) Sort out whether or not derived type constructors are considered to be functions; (ii) Come to a conclusion about scalarization of parent components of extended type arrays; (iii) Check and, if necessary, correct the ordering of finalization in intrinsic assignment of class arrays. (iv) Finalization is difficult to graft on to existing pre-F2003 compilers, as witnessed by the range of implementations. I would be really grateful for thoughts on (i) and (ii). My gut feeling, as remarked in the submission, is that we should aim to be as close as possible, if not identical to, ifort. Happily, that is already the case. I am really sorry to be such a bother, but before we think we should do the same as Intel, we need to understand what Intel does and whether that is actually correct. Or not inconsistent with the standard. And I would really like to understand even the most simple, stupid case. I did reduce testcase finalize_38.f90 to an almost bare minimum, see attached, and changed the main to type(simple), parameter :: ThyType = simple(21) type(simple) :: ThyType2 = simple(22) type(simple), allocatable :: MyType, MyType2 print *, "At start of program: ", final_count MyType = ThyType print *, "After 1st allocation:", final_count MyType2 = ThyType2 print *, "After 2nd allocation:", final_count Note that "ThyType" is now a parameter. - snip Ignore whether Thytype is a Parameter. Regardless Mytype and Mytype2 are allocated upon the assignment. Now if these are never used anywhere, it seems to me the deallocation can be done by the compiler anywhere after the last time it is used. So it can be either after the PRINT statement before the end if the program or right after the assignment before your PRINT statements that examine the value of final_count. I think the result is arbitrary/undefined in your reduced test case I do not have the Intel compiler yet, so I was going to suggest see what it does if your test program prints something from within MyType and MyType2 after all your current print statements at the end. Try this variation of the main program. program test_final use testmode implicit none type(simple), parameter :: ThyType = simple(21) type(simple) :: ThyType2 = simple(22) type(simple), allocatable :: MyType, MyType2 print *, "At start of program: ", final_count MyType = ThyType print *, "After 1st allocation:", final_count MyType2 = ThyType2 print *, "After 2nd allocation:", final_count print *, MyType%ind, MyType2%ind, final_count deallocate(Mytype) print *, MyType%ind, MyType2%ind, final_count deallocate(Mytype2) print *, MyType%ind, MyType2%ind, final_count end program test_final I get with trunk: $ ./a.out At start of program: 0 After 1st allocation: 0 After 2nd allocation: 0 21 22 0 0 22 1 0 0 2 Which makes sense to me. Regards, Jerry
Re: [Patch, fortran] PR37336 (Finalization) - [F03] Finish derived-type finalization
Hi Paul, Am 10.02.22 um 13:25 schrieb Paul Richard Thomas via Fortran: Conclusions on ifort: (i) The agreement between gfortran, with the patch applied, and ifort is strongest of all the other brands; (ii) The disagreements are all down to the treatment of the parent component of arrays of extended types: gfortran finalizes the parent component as an array, whereas ifort does a scalarization. I have a patch ready to do likewise. Overall conclusions: (i) Sort out whether or not derived type constructors are considered to be functions; (ii) Come to a conclusion about scalarization of parent components of extended type arrays; (iii) Check and, if necessary, correct the ordering of finalization in intrinsic assignment of class arrays. (iv) Finalization is difficult to graft on to existing pre-F2003 compilers, as witnessed by the range of implementations. I would be really grateful for thoughts on (i) and (ii). My gut feeling, as remarked in the submission, is that we should aim to be as close as possible, if not identical to, ifort. Happily, that is already the case. I am really sorry to be such a bother, but before we think we should do the same as Intel, we need to understand what Intel does and whether that is actually correct. Or not inconsistent with the standard. And I would really like to understand even the most simple, stupid case. I did reduce testcase finalize_38.f90 to an almost bare minimum, see attached, and changed the main to type(simple), parameter :: ThyType = simple(21) type(simple) :: ThyType2 = simple(22) type(simple), allocatable :: MyType, MyType2 print *, "At start of program: ", final_count MyType = ThyType print *, "After 1st allocation:", final_count MyType2 = ThyType2 print *, "After 2nd allocation:", final_count Note that "ThyType" is now a parameter. I tested the above and found: Intel: At start of program:0 After 1st allocation: 1 After 2nd allocation: 2 NAG 7.0: At start of program: 0 After 1st allocation: 0 After 2nd allocation: 0 Crayftn 12.0.2: At start of program: 2 After 1st allocation: 2 After 2nd allocation: 2 Nvidia 22.1: At start of program: 0 After 1st allocation:0 After 2nd allocation:0 So my stupid questions are: - is ThyType invoking a constructor? It is a parameter, after all. Should using it in an assignment invoke a destructor? If so why? And why does Intel then increment the final_count? - is the initialization of ThyType2 invoking a constructor? It might, if that is the implementation in the compiler, but should there be a finalization? Then ThyType2 is used in an intrinsic assignment, basically the same as the other one before. Now what is the difference? Are all compilers correct, but I do not see it? Someone please help! Best regards Paul Cheers, Harald module testmode implicit none type :: simple integer :: ind contains final :: destructor1 end type simple integer :: final_count = 0 contains subroutine destructor1(self) type(simple), intent(inout) :: self final_count = final_count + 1 end subroutine destructor1 end module testmode program test_final use testmode implicit none type(simple), parameter :: ThyType = simple(21) type(simple) :: ThyType2 = simple(22) type(simple), allocatable :: MyType, MyType2 print *, "At start of program: ", final_count MyType = ThyType print *, "After 1st allocation:", final_count MyType2 = ThyType2 print *, "After 2nd allocation:", final_count end program test_final
Re: [Patch, fortran] PR37336 (Finalization) - [F03] Finish derived-type finalization
Hi Harald, 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 > It appears that Cray interpret a derived type constructor as being a function call and so "6 If a specification expression in a scoping unit references a function, the result is finalized before execution of the executable constructs in the scoping unit." A call to 'test' as the first statement might be useful to diagnose: call test(2, 0, [0,0], -10) > 2, 21, 0 > 21 is presumably the value left over from simple(21) but quite why it should happen in this order is not apparent to me. > 11, 3, 2 > I am mystified as to why the finalization of 'var' is not occurring because "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." Note the double negative! 'var' has been allocated and should return 1 to 'scalar' > 12, 21, 1 > 21, 4, 3 > This is a residue of earlier differences in the final count. > 23, 21, 22 | 42, 43 > The value is inexplicable to me. 31, 6, 4 > 41, 7, 5 > 51, 9, 7 > 61, 10, 8 > 71, 13, 10 > 101, 2, 1 > One again, a function 'expr' finalization has been added after intrinsic assignment; ie. derived type constructor == function. > 102, 4, 3 > > 111, 3, 2 > 121, 4, 2 > 122, 0, 4 > 123, 5, 6 | 2*0 > >From the value of 'array', I would devine that the source in the allocation is being finalized as an array, whereas I would expect each invocation of 'simple' to generate a scalar final call. > 131, 5, 2 > 132, 0, 4 > 133, 7, 8 | 2*0 > The final count has increased by 1, as expected. The value of 'scalar' is stuck at 0, so the second line is explicable. The array value is explicable if the finalization is of 'expr' and that 'var' is not finalized or the finalization of 'var' is occuring after assignment; ie. wrong order. ***I notice from the code that even with the patch, gfortran is finalizing before evaluation of 'expr', which is incorrect. It should be after evaluation of 'expr' and before the assignment.*** 141, 6, 3 > Final count offset - OK 151, 10, 5 > The two extra calls come, I presume from the source in the allocation. Since the type is extended, we see two finalizations each for the allocation and the deallocation. 161, 16, 9 > I think that the extra two finalizations come from the evaluation of 'src' in 'constructor2'. 171, 18, 11 > Final count offset - OK 175, 0., 20. | 10., 20. > The value of 'rarray' is mystifying. Conclusions from Cray: (i) Determine if derived type constructors should be interpreted as function calls. (ii) The order of finalization in class array assignment needs to be checked and fixed if necessary. > > nagfor 7.0: > > 1 0 1 > "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." So I think that NAG has this wrong, either because the timing is right and an unallocatable allocatable is being finalized or because the timing is wrong. 11 1 2 > 23 21 22 | 42 43 > It seems that the finalization is occurring after assignment. 71 9 10 > 72 11 99 > It seems that the finalization of the function 'expr' after assignment is not happening. 131 3 2 > 132 5 4 > I am not sure that I know where the extra final call is nor where the scalar value of 5 comes from. 141 4 3 > 151 6 5 > 161 10 9 > 171 12 11 > The above are OK since there is an offset in the final count, starting at 131. Conclusions from NAG: (i) Some minor nits but pretty close to my interpretation. 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 > [...] > ifort (IFORT) 2021.1 Beta 20201112 manages to carry on to the end. 161 13 9 162 20 0 163 0 0 | 10 20 171 14 11 Conclusions on ifort: (i) The agreement between gfortran, with the patch applied, and ifort is strongest of all the other brands; (ii) The disagreements are all down to the treatment of the parent component of arrays of extended types: gfortran finalizes the parent component as an array, whereas ifort does a scalarization. I have a patch ready to do likewise. Overall conclusions: (i) Sort out whether or not derived type constructors are
Re: [Patch, fortran] PR37336 (Finalization) - [F03] Finish derived-type finalization
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? 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
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? 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
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 ::
Re: [Patch, fortran] PR37336 (Finalization) - [F03] Finish derived-type finalization
Hi Paul, thanks for attacking this. I haven't looked at the actual patch, only tried to check the new testcases with other compilers. Am 03.02.22 um 18:14 schrieb Paul Richard Thomas via Fortran: I have tried to interpret F2018 7.5.6.2 and 7.5.6.3 as well as possible. This is not always straightforward and has involved a lot of head scratching! I have used the Intel compiler as a litmus test for the outcomes. This was largely motivated by the observation that, in the user survey conducted by Steve Lionel, gfortran and ifort are often used together . Therefore, quite aside from wishing to comply with the standard as far as possible, it is more than reasonable that the two compilers comply. On application of this patch, only exception to this is the treatment of finalization of arrays of extended types, where the Intel takes "If the entity is of extended type and the parent type is finalizable, the parent component is finalized" such that the parent component is finalized one element at a time, whereas gfortran finalises 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? 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. (Also finalize_45.f90 fails with that version with something that looks like memory corruption, but that might be just a compiler bug.) Thanks, Harald
[Patch, fortran] PR37336 (Finalization) - [F03] Finish derived-type finalization
This patch has been an excessively long time in coming. Please accept my apologies for that. All but two of the PR37336 dependencies are fixed, The two exceptions are PRs 59694 and 65347. The former involves lack of finalization of an unreferenced entity declared in a block, which I am sure is trivial but I cannot see where the missing trigger is, and the latter involves finalization of function results within an array constructor, for which I will submit an additional patch shortly. PR104272 also remains, in which finalization is occurring during allocation. I fixed this in one place but it seems to have crept out in another :-) Beyond this patch and ones for the three lagging PRs above, a thorough tidy up and unification of finalization is needed. However, I will concentrate on functionality in the first instance. I have tried to interpret F2018 7.5.6.2 and 7.5.6.3 as well as possible. This is not always straightforward and has involved a lot of head scratching! I have used the Intel compiler as a litmus test for the outcomes. This was largely motivated by the observation that, in the user survey conducted by Steve Lionel, gfortran and ifort are often used together . Therefore, quite aside from wishing to comply with the standard as far as possible, it is more than reasonable that the two compilers comply. On application of this patch, only exception to this is the treatment of finalization of arrays of extended types, where the Intel takes "If the entity is of extended type and the parent type is finalizable, the parent component is finalized" such that the parent component is finalized one element at a time, whereas gfortran finalises 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. The work centred on three areas: (i) Finalization on assignment: This was required because finalization of the lhs was occurring at the wrong time relative to evaluation of the rhs expression and was taking the finalization of entities with finalizable components in the wrong order. The changes in trans-array.cc (structure_alloc_comps) allow gfc_deallocate_alloc_comp_no_caf to occur without finalization so that it can be preceded by calls to the finalization wrapper. The other key change in this area is the addition of trans-expr.cc (gfc_assignment_finalizer_call), which manages the ordering of finalization and deallocation. (ii) Finalization of derived type function results. Previously, finalization was not occuring at all for derived type results but it did for class results. The former is now implemented in trans-expr.cc (finalize_function_result), into which the treatment of class finalization has been included. In order to handled complex expressions correctly, an extra block has been included in gfc_se and is initialized in gfc_init_se. This block accumulates the finalizations so that they can be added at the right time. It is the way in which I will fix PR65347 (I have already tested the principle). (iii) Minor fixes These include the changes in class.cc and the exclusion of artificial entities from finalization. There are some missing testcases (sorry Andrew and Sandro!), which might not be necessary because the broken/missing features are already fixed. The fact that the work correctly now is a strong indication that this is the case. Regtests OK on FC33/x86_64 - OK for mainline (and 11-branch)? Best regards Paul Fortran:Implement missing finalization features [PR37336] 2022-02-02 Paul Thomas gcc/fortran PR fortran/103854 * class.cc (has_finalizer_component): Do not return true for procedure pointer components. PR fortran/96122 * class.cc (finalize_component): Include the missing arguments in the call to the component's finalizer wrapper. PR fortran/37336 * class.cc (finalizer_insert_packed_call): Remove the redundant argument in the call to the final subroutine. * resolve.cc (resolve_where, gfc_resolve_where_code_in_forall, gfc_resolve_forall_body, gfc_resolve_code): Check that the op code is still EXEC_ASSIGN. If it is set lhs to must finalize. * trans-array.cc (structure_alloc_comps): Add boolean argument to suppress finalization and use it for calls from gfc_deallocate_alloc_comp_no_caf. Otherwise it defaults to false. Add a second, additional boolean argument to nullify pointer components and use it in gfc_copy_alloc_comp_del_ptrs. (gfc_alloc_allocatable_for_assignment): Suppress finalization by setting new arg in call to gfc_deallocate_alloc_comp_no_caf. (gfc_copy_alloc_comp_del_ptrs): New function. * trans-array.h : Add the new boolean argument to the prototype of gfc_deallocate_alloc_comp_no_caf with a default of false. Add prototype for gfc_copy_alloc_comp_del_ptrs. * trans-expr.cc (gfc_init_se): Initialize finalblock. (finalize_function_result): New function that finalizes function results in the correct order. (gfc_conv_procedure_call): Use