This fixes PR fortran/116829 by making sure that s->value is always applied to non-allocatable BT_DERIVED intent(out) arguments, no matter if they are finalizable or not.
Tested on x86_64-pc-linux-gnu (Fedora 40), any feedback is welcome. gcc/fortran/ChangeLog: * trans-decl.cc (init_intent_out_dt): Always call gfc_init_default_dt() for BT_DERIVED to apply s->value if the symbol isn't allocatable. Also simplify the logic a bit. gcc/testsuite/ChangeLog: * gfortran.dg/derived_init_7.f90: New test. Signed-off-by: Tomáš Trnka <tr...@scm.com> --- gcc/fortran/trans-decl.cc | 9 +--- gcc/testsuite/gfortran.dg/derived_init_7.f90 | 49 ++++++++++++++++++++ 2 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/derived_init_7.f90 diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc index 8231bd255d6..50e8adcb819 100644 --- a/gcc/fortran/trans-decl.cc +++ b/gcc/fortran/trans-decl.cc @@ -4461,7 +4461,6 @@ init_intent_out_dt (gfc_symbol * proc_sym, gfc_wrapped_block * block) tree tmp; tree present; gfc_symbol *s; - bool dealloc_with_value = false; gfc_init_block (&init); for (f = gfc_sym_get_dummy_args (proc_sym); f; f = f->next) @@ -4496,7 +4495,6 @@ init_intent_out_dt (gfc_symbol * proc_sym, gfc_wrapped_block * block) tmp = gfc_deallocate_alloc_comp (s->ts.u.derived, s->backend_decl, s->as ? s->as->rank : 0); - dealloc_with_value = s->value; } if (tmp != NULL_TREE && (s->attr.optional @@ -4507,13 +4505,10 @@ init_intent_out_dt (gfc_symbol * proc_sym, gfc_wrapped_block * block) present, tmp, build_empty_stmt (input_location)); } - if (tmp != NULL_TREE && !dealloc_with_value) - gfc_add_expr_to_block (&init, tmp); - else if (s->value && !s->attr.allocatable) + gfc_add_expr_to_block (&init, tmp); + if (s->value && !s->attr.allocatable) { - gfc_add_expr_to_block (&init, tmp); gfc_init_default_dt (s, &init, false); - dealloc_with_value = false; } } else if (f->sym && f->sym->attr.intent == INTENT_OUT diff --git a/gcc/testsuite/gfortran.dg/derived_init_7.f90 b/gcc/testsuite/gfortran.dg/derived_init_7.f90 new file mode 100644 index 00000000000..8efb7ba1c77 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/derived_init_7.f90 @@ -0,0 +1,49 @@ +! { dg-do run } +! Check that finalizable intent(out) dummy arguments are first finalized +! and then correctly default-initialized (PR116829) +! +module FinalizableIntentOutTestModule + implicit none + + type :: AapType + integer :: i = 0 + contains + final :: Finalizer + end type + +contains + + subroutine Finalizer(self) + type(AapType), intent(inout) :: self + + ! Fail if Finalizer gets called again on an already finalized object + if (self%i == 42) stop 1 + + self%i = 42 ! Nobody should ever see this value after finalization + end subroutine + +end module + + +program test + use FinalizableIntentOutTestModule + + implicit none + + type(AapType) :: aap + + ! Set "i" to nonzero so that initialization in MakeAap has something to do + aap%i = 1 + + call MakeAap(aap) + +contains + + subroutine MakeAap(a) + type(AapType), intent(out) :: a + + ! Fail if "a" wasn't initialized properly + if (a%i /= 0) stop 2 + end subroutine + +end program -- 2.46.1