See attached patch. A structure constructor that gives an explicit-length
allocatable character component an allocatable or deferred-length value
ICEs in fold_convert_loc. gfc_trans_subcomponent_assign falls through to
its final branch, which fold_converts the value, a pointer to the
string, to the component's character type. The patch copies the string
with gfc_trans_string_copy instead, which also truncates or blank-pads
it to the declared length.

The fix is the new BT_CHARACTER branch in gfc_trans_subcomponent_assign
in trans-expr.cc; the rest is the new test. The bug was found with the
Fujitsu compiler test suite; the test is new.

Regression tested on x86_64.

OK for mainline?

Regards,

Jerry

---

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.
>From 7bb0d7926c4b722159e6a69e79b42aab703fb269 Mon Sep 17 00:00:00 2001
From: Jerry DeLisle <[email protected]>
Date: Wed, 10 Jun 2026 08:36:59 -0700
Subject: [PATCH] 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.
---
 gcc/fortran/trans-expr.cc                     |  8 ++++
 .../gfortran.dg/structure_constructor_19.f90  | 43 +++++++++++++++++++
 2 files changed, 51 insertions(+)
 create mode 100644 gcc/testsuite/gfortran.dg/structure_constructor_19.f90

diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 265bc1c02dd..2d04fd79061 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 00000000000..50008895d9a
--- /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
-- 
2.56.0

Reply via email to