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
