The following code segfaults with gfortran 11.0.0: module a type vs character(len=1), dimension(:), allocatable :: ch contains final :: vsf end type vs type mtd type(vs), dimension(2) :: n end type mtd contains subroutine c() type(mtd) :: m allocate(m%n(1)%ch(1)) m%n(1)%ch(1)="a" allocate(m%n(2)%ch(1)) m%n(2)%ch(1)="b" return end subroutine c subroutine vsf(s) type(vs), intent(inout) :: s if (allocated(s%ch)) deallocate(s%ch) return end subroutine vsf end module a program b use a call c() end program b $ gfortran -v Using built-in specs. COLLECT_GCC=gfortran COLLECT_LTO_WRAPPER=/home/abenson/Galacticus/Tools/libexec/gcc/x86_64-pc-linux-gnu/11.0.0/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: ../gcc-git/configure --prefix=/home/abenson/Galacticus/Tools --enable-languages=c,c++,fortran --disable-multilib Thread model: posix Supported LTO compression algorithms: zlib gcc version 11.0.0 20200705 (experimental) (GCC) $ gfortran tmp.F90 -g $ ./a.out Program received signal SIGSEGV: Segmentation fault - invalid memory reference. Backtrace for this error: #0 0x7f47668d61ef in ??? at /data001/abenson/Galacticus/Tools/glibc-2.12.1/signal/../sysdeps/unix/sysv/linux/x86_64/sigaction.c:0 #1 0x40118f in __a_MOD___final_a_Vs at /home/abenson/Galacticus/Nightlies/galacticus/tmp.F90:30 #2 0x400bfa in __a_MOD___final_a_Mtd at /home/abenson/Galacticus/Nightlies/galacticus/tmp.F90:30 #3 0x401556 in __a_MOD_c at /home/abenson/Galacticus/Nightlies/galacticus/tmp.F90:22 #4 0x401562 in b at /home/abenson/Galacticus/Nightlies/galacticus/tmp.F90:34 #5 0x401599 in main at /home/abenson/Galacticus/Nightlies/galacticus/tmp.F90:33 Segmentation fault The problem doesn't occur if the finalizer for type "vs" isn't used. It also doesn't occur if the "n" component of type "mtd" has dimension(1) or is a scalar. The finalizer in this case is pointless (since it just deallocates an allocatable, which would happen automatically if no finalizer were used), but as far as I can see is legal code. This appears to be a regression (worked in 10.1) but I haven't yet tracked down exactly where the problem was introduced.
Confirmed. For me it segfaults from GCC7 up to GCC11.
(In reply to Dominique d'Humieres from comment #1) > Confirmed. For me it segfaults from GCC7 up to GCC11. Interesting. This started occurring for me when I updated from GCC10.1 to 11. But, the code I posted is a reduced test case that I created - so maybe the original (non-reduced-test-case) code wasn't triggering this previously for some reason.
(In reply to Andrew Benson from comment #2) > (In reply to Dominique d'Humieres from comment #1) > > Confirmed. For me it segfaults from GCC7 up to GCC11. > > Interesting. This started occurring for me when I updated from GCC10.1 to > 11. But, the code I posted is a reduced test case that I created - so maybe > the original (non-reduced-test-case) code wasn't triggering this previously > for some reason. In Gcc 10.1, we did not call the finalizer for all required instances (PR 94109). This has been fixed for gcc11 and the upcoming 10.2 release. It is likely that calling a (required?) finalizer again has led to the segfault reappearing. (Our finalizer handling is a mess, this and PDTs are really the only two really buggy fields for F2003 conformance).
(In reply to Thomas Koenig from comment #3) > (In reply to Andrew Benson from comment #2) > > (In reply to Dominique d'Humieres from comment #1) > > > Confirmed. For me it segfaults from GCC7 up to GCC11. > > > > Interesting. This started occurring for me when I updated from GCC10.1 to > > 11. But, the code I posted is a reduced test case that I created - so maybe > > the original (non-reduced-test-case) code wasn't triggering this previously > > for some reason. > > In Gcc 10.1, we did not call the finalizer for all required instances > (PR 94109). This has been fixed for gcc11 and the upcoming 10.2 release. > > It is likely that calling a (required?) finalizer again has led to > the segfault reappearing. > > (Our finalizer handling is a mess, this and PDTs are really the > only two really buggy fields for F2003 conformance). The segfault is caused by the following: { struct array01_vs parm.6; parm.6.span = 64; parm.6.dtype = {.elem_len=64, .rank=1, .type=5}; parm.6.dim[0].lbound = 1; parm.6.dim[0].ubound = 2; parm.6.dim[0].stride = 1; parm.6.data = (void *) &ptr1->n[0]; parm.6.offset = -1; __final_a_Vs (&parm.6); } whereas the template for __final_a_Vs is: integer(kind=4) __final_a_Vs (struct array15_vs & restrict array, integer(kind=8) byte_stride, logical(kind=1) fini_coarray) at a minimum, 'byte_stride' is required in the call I have a mostly complete patch, for finalizers in general, which includes this and so fixes the segfault. I hope to submit the current version of the patch today because we have started stage 4. Paul
(In reply to Paul Thomas from comment #4) > (In reply to Thomas Koenig from comment #3) > > (In reply to Andrew Benson from comment #2) > > > (In reply to Dominique d'Humieres from comment #1) > > > > Confirmed. For me it segfaults from GCC7 up to GCC11. > > > > > > Interesting. This started occurring for me when I updated from GCC10.1 to > > > 11. But, the code I posted is a reduced test case that I created - so maybe > > > the original (non-reduced-test-case) code wasn't triggering this previously > > > for some reason. > > > > In Gcc 10.1, we did not call the finalizer for all required instances > > (PR 94109). This has been fixed for gcc11 and the upcoming 10.2 release. > > > > It is likely that calling a (required?) finalizer again has led to > > the segfault reappearing. > > > > (Our finalizer handling is a mess, this and PDTs are really the > > only two really buggy fields for F2003 conformance). > > The segfault is caused by the following: > { > struct array01_vs parm.6; > > parm.6.span = 64; > parm.6.dtype = {.elem_len=64, .rank=1, .type=5}; > parm.6.dim[0].lbound = 1; > parm.6.dim[0].ubound = 2; > parm.6.dim[0].stride = 1; > parm.6.data = (void *) &ptr1->n[0]; > parm.6.offset = -1; > __final_a_Vs (&parm.6); > } > > whereas the template for __final_a_Vs is: > > integer(kind=4) __final_a_Vs (struct array15_vs & restrict array, > integer(kind=8) byte_stride, logical(kind=1) fini_coarray) > > at a minimum, 'byte_stride' is required in the call > > I have a mostly complete patch, for finalizers in general, which includes > this and so fixes the segfault. > > I hope to submit the current version of the patch today because we have > started stage 4. > > Paul By the way, in order to trigger some finalization calls, 'vsf' had to declared 'elemental'. Without my patch, it still segfaults in runtime, even with this embellishment. Apart from PR65347 and PR88735, I have now fixed all of the finalization bugs on which PR37336 depends. Thanks for your help and bug reports. Paul
The master branch has been updated by Paul Thomas <pault@gcc.gnu.org>: https://gcc.gnu.org/g:d7caf313525a46f200d7f5db1ba893f853774aee commit r13-6747-gd7caf313525a46f200d7f5db1ba893f853774aee Author: Paul Thomas <pault@gcc.gnu.org> Date: Sat Mar 18 07:56:23 2023 +0000 Fortran: Fix bugs and missing features in finalization [PR37336] 2023-03-18 Paul Thomas <pault@gcc.gnu.org> gcc/fortran PR fortran/103854 PR fortran/96122 PR fortran/37336 * class.cc (finalize_component): Include the missing arguments in the call to the component's finalizer wrapper. (has_finalizer_component): Do not return true for procedure pointer components. (finalizer_insert_packed_call): Remove the redundant argument in the call to the final subroutine. (generate_finalization_wrapper): Add support for assumed rank finalizers. (gfc_may_be_finalized): New helper function. * dump-parse-tree.cc (write_proc): Whitespace. * gfortran.h : Add prototype for gfc_may_be_finalized. * resolve.cc (resolve_function): Correct derived types that have an incomplete namespace. (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. (is_finalizable_type): New function. (generate_component_assignments): Set must_finalize if needed. (gfc_resolve_finalizers): Error if assumed rank finalizer is not the only one. Warning on lack of scalar finalizer modified to account for assumed rank finalizers. (generate_final_call): New function. (generate_component_assignments): Enclose the outermost call in a block to capture automatic deallocation and final calls. Set must_finalize as required to satisfy the standards. Use an explicit pointer assignment for pointer components to capture finalization of the target. Likewise use explicit assignment for allocatable components. Do not use the temporary copy of the lhs in defined assignment if the component is allocatable. Put the temporary in the same namespace as the lhs symbol if the component may be finalized. Remove the leading assignment from the expansion of assignment of components that have their own defined assignment components. Suppress finalization of assignment of temporary components to the lhs. Make an explicit final call for the rhs function temporary if it exists. (gfc_resolve_code): Set must_finalize for assignments with an array constructor on the rhs. (gfc_resolve_finalizers): Ensure that an assumed rank finalizer is the only finalizer for that type and correct the surprising warning for the lack of a scalar finalizer. (check_defined_assignments): Handle allocatable components. (resolve_fl_derived): Set referenced the vtab for use associated symbols. (resolve_symbol): Set referenced an unreferenced symbol that will be finalized. * trans-array.cc (gfc_trans_array_constructor_value): Add code to finalize the constructor result. Warn that this feature was removed in F2018 and that it is suppressed by -std=2018. (trans_array_constructor): Add finalblock, pass to previous and apply to loop->post if filled. (gfc_add_loop_ss_code): Add se finalblock to outer loop post. (gfc_trans_array_cobounds, gfc_trans_array_bounds): Add any generated finalization code to the main block. (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. (gfc_copy_alloc_comp_no_fini): New wrapper for structure_alloc_comps. (gfc_alloc_allocatable_for_assignment): Suppress finalization by setting new arg in call to gfc_deallocate_alloc_comp_no_caf. (gfc_trans_deferred_array): Use gfc_may_be_finalized and do not deallocate the components of entities with a leading '_' in the name that are also marked as artificial. * 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_no_fini. * trans-decl.cc(init_intent_out_dt): Tidy up the code. * trans-expr.cc (gfc_init_se): Initialize finalblock. (gfc_conv_procedure_call): Use gfc_finalize_tree_expr to finalize function results. Replace in-line block for class results with call to new function. (gfc_conv_expr): Finalize structure constructors for F2003 and F2008. Warn that this feature was deleted in F2018 and, unlike array constructors, is not default. Add array constructor finalblock to the post block. (gfc_trans_scalar_assign): Suppress finalization by setting new argument in call to gfc_deallocate_alloc_comp_no_caf. Add the finalization blocks to the main block. (gfc_trans_arrayfunc_assign): Use gfc_assignment_finalizer_call and ensure that finalization occurs after the evaluation of the rhs but using the initial value for the lhs. Finalize rhs function results using gfc_finalize_tree_expr. (trans_class_assignment, gfc_trans_assignment_1): As previous function, taking care to order evaluation, assignment and finalization correctly. * trans-io.cc (gfc_trans_transfer): Add the final block. * trans-stmt.cc (gfc_trans_call, gfc_trans_allocate): likewise. (trans_associate_var): Nullify derived allocatable components and finalize function targets with defined assignment components on leaving the block scope. (trans_allocate): Finalize source expressions, if required, and set init_expr artificial temporarily to suppress the finalization in gfc_trans_assignment. * trans.cc (gfc_add_finalizer_call): Do not finalize the temporaries generated in type assignment with defined assignment components. (gfc_assignment_finalizer_call): New function. (gfc_finalize_tree_expr): New function. * trans.h: Add finalblock to gfc_se. Add the prototypes for gfc_finalize_tree_expr and gfc_assignment_finalizer_call. gcc/testsuite/ PR fortran/64290 * gfortran.dg/finalize_38.f90 : New test. * gfortran.dg/finalize_38a.f90 : New test. * gfortran.dg/allocate_with_source_25.f90 : The number of final calls goes down from 6 to 4. * gfortran.dg/associate_25.f90 : Remove the incorrect comment. * gfortran.dg/auto_dealloc_2.f90 : Change the tree dump expr but the final count remains the same. * gfortran.dg/unlimited_polymorphic_8.f90 : Tree dump reveals foo.1.x rather than foo.0.x PR fortran/67444 * gfortran.dg/finalize_39.f90 : New test. PR fortran/67471 * gfortran.dg/finalize_40.f90 : New test. PR fortran/69298 PR fortran/70863 * gfortran.dg/finalize_41.f90 : New test. PR fortran/71798 * gfortran.dg/finalize_42.f90 : New test. PR fortran/80524 * gfortran.dg/finalize_43.f90 : New test. PR fortran/82996 * gfortran.dg/finalize_44.f90 : New test. PR fortran/84472 * gfortran.dg/finalize_45.f90 : New test. PR fortran/88735 PR fortran/93691 * gfortran.dg/finalize_46.f90 : New test. PR fortran/91316 * gfortran.dg/finalize_47.f90 : New test. PR fortran/106576 * gfortran.dg/finalize_48.f90 : New test. PR fortran/37336 * gfortran.dg/finalize_49.f90 : New test. * gfortran.dg/finalize_50.f90 : New test. * gfortran.dg/finalize_51.f90 : New test.
Hi Andrew, Thank you for all your recent support on PR37336. I will be putting it to the gfortran list that I should backport to 12-branch in the next few weeks. Regards Paul