See attached patch. This fixes an ICE with %LEN of a deferred-length
character variable in ASSOCIATE.

Regression tested on x86_64.

OK for mainline?

Regards,

Jerry

---

fortran: [PR127187] ICE with %LEN of deferred-length character in ASSOCIATE

A %LEN or %KIND inquiry of a deferred-length character variable gives
an INTEGER expression that still carried the deferred flag of the
character typespec.  An associate-name with such a selector inherited
it, and gfc_get_symbol_decl then segfaulted looking for its string
length.

A related bug: for an associate-name whose selector is deferred-length
character, resolve_variable reset the typespec of the expression to
that of the associate-name unless a substring reference was present.
An inquiry reference of the associate-name, e.g. q%len, thus reverted
to CHARACTER, giving an ICE in conv_inquiry or a spurious error on
comparison with an INTEGER.

        PR fortran/127187

gcc/fortran/ChangeLog:

        PR fortran/127187
        * primary.cc (gfc_match_varspec): Clear the deferred flag, and
        for KIND the charlen, of the INTEGER result of a LEN or KIND
        inquiry.
        * resolve.cc (resolve_variable): Do not reset the typespec of a
        deferred-length character associate-name expression that has an
        inquiry reference.

gcc/testsuite/ChangeLog:

        PR fortran/127187
        * gfortran.dg/associate_90.f90: New test.
>From 6a780eef6cda472d69810104eb789e075c7186e7 Mon Sep 17 00:00:00 2001
From: Jerry DeLisle <[email protected]>
Date: Wed, 23 Sep 2026 10:26:50 -0700
Subject: [PATCH] fortran: [PR127187] ICE with %LEN of deferred-length
 character in ASSOCIATE

A %LEN or %KIND inquiry of a deferred-length character variable gives
an INTEGER expression that still carried the deferred flag of the
character typespec.  An associate-name with such a selector inherited
it, and gfc_get_symbol_decl then segfaulted looking for its string
length.

A related bug: for an associate-name whose selector is deferred-length
character, resolve_variable reset the typespec of the expression to
that of the associate-name unless a substring reference was present.
An inquiry reference of the associate-name, e.g. q%len, thus reverted
to CHARACTER, giving an ICE in conv_inquiry or a spurious error on
comparison with an INTEGER.

	PR fortran/127187

gcc/fortran/ChangeLog:

	PR fortran/127187
	* primary.cc (gfc_match_varspec): Clear the deferred flag, and
	for KIND the charlen, of the INTEGER result of a LEN or KIND
	inquiry.
	* resolve.cc (resolve_variable): Do not reset the typespec of a
	deferred-length character associate-name expression that has an
	inquiry reference.

gcc/testsuite/ChangeLog:

	PR fortran/127187
	* gfortran.dg/associate_90.f90: New test.
---
 gcc/fortran/primary.cc                     |  6 ++
 gcc/fortran/resolve.cc                     |  2 +-
 gcc/testsuite/gfortran.dg/associate_90.f90 | 69 ++++++++++++++++++++++
 3 files changed, 76 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gfortran.dg/associate_90.f90

diff --git a/gcc/fortran/primary.cc b/gcc/fortran/primary.cc
index 4f4638f1296..c6811def4ff 100644
--- a/gcc/fortran/primary.cc
+++ b/gcc/fortran/primary.cc
@@ -2836,6 +2836,7 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag,
 		  return MATCH_ERROR;
 		}
 	      primary->ts.u.cl = NULL;
+	      primary->ts.deferred = false;
 	      primary->ts.type = BT_INTEGER;
 	      primary->ts.kind = gfc_default_integer_kind;
 	      break;
@@ -2851,6 +2852,11 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag,
 			     "to an expression of intrinsic type");
 		  return MATCH_ERROR;
 		}
+	      if (primary->ts.type == BT_CHARACTER)
+		{
+		  primary->ts.u.cl = NULL;
+		  primary->ts.deferred = false;
+		}
 	      primary->ts.type = BT_INTEGER;
 	      primary->ts.kind = gfc_default_integer_kind;
 	      break;
diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index b5eeb4cfde3..7ad9eeb2db5 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -6739,7 +6739,7 @@ resolve_variable (gfc_expr *e)
     {
       gfc_ref *ref;
       for (ref = e->ref; ref; ref = ref->next)
-	if (ref->type == REF_SUBSTRING)
+	if (ref->type == REF_SUBSTRING || ref->type == REF_INQUIRY)
 	  break;
       if (ref == NULL)
 	e->ts = sym->ts;
diff --git a/gcc/testsuite/gfortran.dg/associate_90.f90 b/gcc/testsuite/gfortran.dg/associate_90.f90
new file mode 100644
index 00000000000..2190aa83693
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/associate_90.f90
@@ -0,0 +1,69 @@
+! { dg-do run }
+!
+! PR 127187
+! %LEN and %KIND inquiries of deferred-length character in ASSOCIATE.
+!
+! Contributed by Ivan Pribec
+!
+program assoc_len_kind
+  implicit none
+  character(:), allocatable :: s, a(:)
+  character(:), pointer :: p
+  character(kind=4,len=:), allocatable :: w
+  character(7) :: f = 'seven07'
+  complex :: z = (1., 2.)
+  s = 'hello'
+  a = ['ab', 'cd', 'ef']
+  w = 4_'wxyz'
+  allocate (p, source='ptr')
+
+  ! Selector contains an inquiry of a deferred-length variable
+  associate (n => s%len)
+    if (n /= 5) error stop 1
+  end associate
+  associate (n => (s%len))
+    if (n /= 5) error stop 2
+  end associate
+  associate (n => f%len)
+    if (n /= 7) error stop 3
+  end associate
+  associate (n => s%len + 0)
+    if (n /= 5) error stop 4
+  end associate
+  associate (k => z%kind)
+    if (k /= kind(z)) error stop 5
+  end associate
+  associate (k => z%kind, n => s%len)
+    if (k /= kind(z)) error stop 6
+    if (n /= 5) error stop 7
+  end associate
+  associate (n => s%len)
+    s = 'longer_string'
+    if (n /= 5) error stop 8
+  end associate
+  s = 'hello'
+  associate (n => s%kind, m => p%len, k => w%kind)
+    if (n /= 1 .or. m /= 3 .or. k /= 4) error stop 9
+  end associate
+
+  ! Inquiry of an associate-name with a deferred-length selector
+  associate (q => s)
+    if (q%len /= 5 .or. q%kind /= 1) error stop 10
+    if (q(2:3)%len /= 2) error stop 11
+    associate (n => q%len + q%kind)
+      if (n /= 6) error stop 12
+    end associate
+  end associate
+  associate (q => a)
+    if (q%len /= 2 .or. size (q) /= 3) error stop 13
+  end associate
+  associate (q => p, r => w)
+    if (q%len /= 3 .or. r%len /= 4 .or. r%kind /= 4) error stop 14
+  end associate
+  associate (q => s)
+    associate (r => q)
+      if (r%len /= 5) error stop 15
+    end associate
+  end associate
+  deallocate (p)
+end program
-- 
2.55.0

Reply via email to