Dear all, the initialization of allocatable non-deferred character with NULL when being a component of a derived type used a wrong path instead of properly initializing with a null pointer and produced really weird code.
Regtested on x86_64-pc-linux-gnu. OK for mainline? While it is a really old bug but wrong code, I'd like to backport this also at least to 14-branch. Any reservations? Thanks, Harald
From f90b21d89c206507c4383e349db12546b793ce31 Mon Sep 17 00:00:00 2001 From: Harald Anlauf <anl...@gmx.de> Date: Fri, 7 Feb 2025 21:21:10 +0100 Subject: [PATCH] Fortran: fix initialization of allocatable non-deferred character [PR59252] PR fortran/59252 gcc/fortran/ChangeLog: * trans-expr.cc (gfc_trans_subcomponent_assign): Initialize allocatable non-deferred character with NULL properly. gcc/testsuite/ChangeLog: * gfortran.dg/allocatable_char_1.f90: New test. --- gcc/fortran/trans-expr.cc | 8 +++- .../gfortran.dg/allocatable_char_1.f90 | 47 +++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/allocatable_char_1.f90 diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index f923aeb9460..a7af67cb441 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -9836,9 +9836,13 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, tmp = gfc_trans_alloc_subarray_assign (tmp, cm, expr); gfc_add_expr_to_block (&block, tmp); } - else if (init && cm->attr.allocatable && expr->expr_type == EXPR_NULL) + else if (cm->attr.allocatable && expr->expr_type == EXPR_NULL + && (init + || (cm->ts.type == BT_CHARACTER + && !(cm->ts.deferred || cm->attr.pdt_string)))) { - /* NULL initialization for allocatable components. */ + /* NULL initialization for allocatable components. + Deferred-length character is dealth with later. */ gfc_add_modify (&block, dest, fold_convert (TREE_TYPE (dest), null_pointer_node)); } diff --git a/gcc/testsuite/gfortran.dg/allocatable_char_1.f90 b/gcc/testsuite/gfortran.dg/allocatable_char_1.f90 new file mode 100644 index 00000000000..1d6c25c4942 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/allocatable_char_1.f90 @@ -0,0 +1,47 @@ +! { dg-do run } +! { dg-additional-options "-fdump-tree-original" } +! +! PR fortran/59252 + +module mod + implicit none + + type t1 + character(256), allocatable :: label + end type t1 + + type t2 + type(t1), allocatable :: appv(:) + end type t2 + +contains + subroutine construct(res) + type(t2), allocatable, intent(inout) :: res + if (.not. allocated(res)) allocate(res) + end subroutine construct + + subroutine construct_appv(appv) + type(t1), allocatable, intent(inout) :: appv(:) + if (.not. allocated(appv)) allocate(appv(20)) + end subroutine construct_appv + + type(t1) function foo () result (res) + end function foo +end module mod + +program testy + use mod + implicit none + type(t2), allocatable :: res + type(t1) :: s + + ! original test from pr59252 + call construct (res) + call construct_appv(res%appv) + deallocate (res) + + ! related test from pr118747 comment 2: + s = foo () +end program testy + +! { dg-final { scan-tree-dump-not "__builtin_memmove" "original" } } -- 2.43.0