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