https://gcc.gnu.org/g:3461bb8b7148d0cfe1a1505768accef330e88743

commit r17-5521-g3461bb8b7148d0cfe1a1505768accef330e88743
Author: Jerry DeLisle <[email protected]>
Date:   Fri Oct 23 14:26:45 2026 -0400

    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.

Diff:
---
 gcc/fortran/frontend-passes.cc                     |  5 ++-
 gcc/fortran/resolve.cc                             |  3 +-
 .../gfortran.dg/char_pointer_substring_init.f90    | 37 ++++++++++++++++++++++
 3 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/gcc/fortran/frontend-passes.cc b/gcc/fortran/frontend-passes.cc
index 85cf7ff13945..aa590a838de6 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 1167fc2a1a94..d2ee82071189 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 000000000000..8635d76b813a
--- /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

Reply via email to