I have attached a patch for the subject PR. Mikael's comment in the PR prompted me to look elsewhere. This fix turns out simple and obvious,

I plan to commit later today.

Regression tested on x86_64.

Regards,

Jerry

---

fortran: [PR125763] Fix ICE for character pointer initialized
 to a substring

A character pointer initialized to a substring in its declaration, e.g.

  character(len=:), pointer :: p => t(2:4)

ICE'd in gfc_get_symbol_decl because the substring's character length
was never set.  gfc_resolve_expr did not resolve the substring length
when the first reference of the variable is the substring itself, as
for a scalar variable, so fixup_charlen gave the expression a charlen
with no length.  Resolve the substring length in that case too.

With that change, the frontend temporary that create_var makes for a
deferred-length assignment such as a = a(m:n) gets an explicit LEN()
length but kept the deferred flag of the variable, which tripped an
assertion in gfc_trans_deferred_vars.  Clear the deferred flag when the
temporary is given an explicit length.

        PR fortran/125763

gcc/fortran/ChangeLog:

        * frontend-passes.cc (create_var): Clear ts.deferred when the
        temporary gets an explicit length from LEN().
        * resolve.cc (gfc_resolve_expr): Resolve the substring length
        also when the first reference is the substring.

gcc/testsuite/ChangeLog:

        * gfortran.dg/char_pointer_substring_init.f90: New test.
---




From 14134a9adae8e3336aea2ad393f1b869e5679364 Mon Sep 17 00:00:00 2001
From: Jerry DeLisle <[email protected]>
Date: Fri, 23 Oct 2026 14:26:45 -0400
Subject: [PATCH] fortran: [PR125763] Fix ICE for character pointer initialized
 to a substring

A character pointer initialized to a substring in its declaration, e.g.

  character(len=:), pointer :: p => t(2:4)

ICE'd in gfc_get_symbol_decl because the substring's character length
was never set.  gfc_resolve_expr did not resolve the substring length
when the first reference of the variable is the substring itself, as
for a scalar variable, so fixup_charlen gave the expression a charlen
with no length.  Resolve the substring length in that case too.

With that change, the frontend temporary that create_var makes for a
deferred-length assignment such as a = a(m:n) gets an explicit LEN()
length but kept the deferred flag of the variable, which tripped an
assertion in gfc_trans_deferred_vars.  Clear the deferred flag when the
temporary is given an explicit length.

	PR fortran/125763

gcc/fortran/ChangeLog:

	* frontend-passes.cc (create_var): Clear ts.deferred when the
	temporary gets an explicit length from LEN().
	* resolve.cc (gfc_resolve_expr): Resolve the substring length
	also when the first reference is the substring.

gcc/testsuite/ChangeLog:

	* gfortran.dg/char_pointer_substring_init.f90: New test.
---
 gcc/fortran/frontend-passes.cc                |  5 ++-
 gcc/fortran/resolve.cc                        |  3 +-
 .../char_pointer_substring_init.f90           | 37 +++++++++++++++++++
 3 files changed, 42 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/char_pointer_substring_init.f90

diff --git a/gcc/fortran/frontend-passes.cc b/gcc/fortran/frontend-passes.cc
index 85cf7ff1394..aa590a838de 100644
--- a/gcc/fortran/frontend-passes.cc
+++ b/gcc/fortran/frontend-passes.cc
@@ -835,7 +835,10 @@ create_var (gfc_expr * e, const char *vname)
       else if (e->expr_type == EXPR_VARIABLE
 	       && e->symtree->n.sym->ts.type == BT_CHARACTER
 	       && e->ts.u.cl->length)
-	symbol->ts.u.cl->length = get_len_call (gfc_copy_expr (e));
+	{
+	  symbol->ts.u.cl->length = get_len_call (gfc_copy_expr (e));
+	  symbol->ts.deferred = 0;
+	}
       else
 	{
 	  symbol->attr.allocatable = 1;
diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index 1167fc2a1a9..d2ee8207118 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -8377,8 +8377,7 @@ gfc_resolve_expr (gfc_expr *e)
       else
 	t = resolve_variable (e);
 
-      if (e->ts.type == BT_CHARACTER && e->ts.u.cl == NULL && e->ref
-	  && e->ref->type != REF_SUBSTRING)
+      if (e->ts.type == BT_CHARACTER && e->ts.u.cl == NULL && e->ref)
 	gfc_resolve_substring_charlen (e);
 
       break;
diff --git a/gcc/testsuite/gfortran.dg/char_pointer_substring_init.f90 b/gcc/testsuite/gfortran.dg/char_pointer_substring_init.f90
new file mode 100644
index 00000000000..8635d76b813
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/char_pointer_substring_init.f90
@@ -0,0 +1,37 @@
+! { dg-do run }
+!
+! PR fortran/125763
+!
+! A scalar character pointer initialized to a substring of a target at
+! declaration used to ICE in gfc_get_symbol_decl because the substring's
+! character length was never resolved.
+
+module m
+  implicit none
+  character(len=5), target :: t = "abcde"
+  character(kind=4,len=5), target :: w = 4_"abcde"
+contains
+  subroutine check ()
+    ! Deferred-length pointers to substrings.
+    character(len=:), pointer :: pd1 => t(2:4)
+    character(len=:), pointer :: pd2 => t(1:5)
+    character(len=:), pointer :: pd3 => t(4:3)   ! zero length
+    ! Explicit-length pointers to substrings.
+    character(len=3), pointer :: pe1 => t(2:4)
+    ! Wide-character pointers to substrings.
+    character(kind=4,len=:), pointer :: pw1 => w(2:4)
+    character(kind=4,len=3), pointer :: pw2 => w(3:5)
+
+    if (len (pd1) /= 3 .or. pd1 /= "bcd") stop 1
+    if (len (pd2) /= 5 .or. pd2 /= "abcde") stop 2
+    if (len (pd3) /= 0) stop 3
+    if (len (pe1) /= 3 .or. pe1 /= "bcd") stop 4
+    if (len (pw1) /= 3 .or. pw1 /= 4_"bcd") stop 5
+    if (len (pw2) /= 3 .or. pw2 /= 4_"cde") stop 6
+  end subroutine
+end module
+
+program p
+  use m
+  call check ()
+end program p
-- 
2.56.0

Reply via email to