https://gcc.gnu.org/g:78d6e3832905ce5e028d8acef21eff08e8b50819
commit r17-5064-g78d6e3832905ce5e028d8acef21eff08e8b50819 Author: Jerry DeLisle <[email protected]> Date: Wed Jun 10 08:36:59 2026 -0700 fortran: [PR125720] ICE assigning an allocatable character to an allocatable component In a structure constructor, copy a value into an explicit-length allocatable character component with gfc_trans_string_copy instead of a scalar fold_convert. Assisted-by: Claude Opus 5.5 PR fortran/125720 gcc/fortran/ChangeLog: * trans-expr.cc (gfc_trans_subcomponent_assign): Use gfc_trans_string_copy for an explicit-length allocatable character component. gcc/testsuite/ChangeLog: * gfortran.dg/structure_constructor_19.f90: New test. Diff: --- gcc/fortran/trans-expr.cc | 8 ++++ .../gfortran.dg/structure_constructor_19.f90 | 43 ++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index 265bc1c02dd2..2d04fd79061c 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -10597,6 +10597,14 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, se.string_length)); } } + else if (cm->ts.type == BT_CHARACTER) + { + /* Copy into the explicit-length allocatable character component. */ + gfc_conv_string_parameter (&se); + gfc_trans_string_copy (&block, cm->ts.u.cl->backend_decl, dest, + cm->ts.kind, se.string_length, se.expr, + expr->ts.kind); + } else { gfc_add_modify (&block, tmp, diff --git a/gcc/testsuite/gfortran.dg/structure_constructor_19.f90 b/gcc/testsuite/gfortran.dg/structure_constructor_19.f90 new file mode 100644 index 000000000000..50008895d9a1 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/structure_constructor_19.f90 @@ -0,0 +1,43 @@ +! { dg-do run } +! +! PR 125720 +! +! A structure constructor that assigns an allocatable or deferred-length +! character expression to an explicit-length allocatable character component +! used to ICE in gfc_trans_subcomponent_assign (fold_convert_loc). Check that +! it now compiles and copies with the correct truncation/padding. + +program p + type t + integer :: i + character(2), allocatable :: c + end type t + type(t) :: x + + character(2), allocatable :: a + character(:), allocatable :: d + + ! Allocatable, explicit-length source. + allocate (a) + a = "cd" + x = t (2, a) + if (x%i /= 2) stop 1 + if (.not. allocated (x%c)) stop 2 + if (len (x%c) /= 2) stop 3 + if (x%c /= "cd") stop 4 + + ! Deferred-length source, exact length. + d = "ef" + x = t (3, d) + if (x%c /= "ef") stop 5 + + ! Deferred-length source, longer than the component -> truncated. + d = "ghij" + x = t (4, d) + if (x%c /= "gh") stop 6 + + ! Deferred-length source, shorter than the component -> blank padded. + d = "k" + x = t (5, d) + if (x%c /= "k ") stop 7 +end program p
