Attached is the patch I re-discovered while cleaning up worktrees.

Regression tested on x86_64.

OK for mainline?

Regards,

Jerry

---
fortran: [PR95542] Fix ICE for deferred-length CHARACTER


gfc_get_symbol_decl has an assert meant to verify that a deferred-length
string's length variable lives in the same scope as the symbol it
belongs to.  This is wrong when sym->backend_decl is itself the enclosing
function's FUNCTION_DECL.  The correct comparison is
DECL_CONTEXT (length) == sym->backend_decl directly.

This was hit when a deferred-length CHARACTER function's own result
was assigned to or read from a CONTAINED subprocedure via host
association.

        PR fortran/95542

gcc/fortran/ChangeLog:

        * trans-decl.cc (gfc_get_symbol_decl): When checking that a
        deferred-length string's length variable shares the symbol's
        scope, special-case sym->backend_decl being a FUNCTION_DECL
        (an implicit function-result variable): compare against
        sym->backend_decl directly instead of its own DECL_CONTEXT.

gcc/testsuite/ChangeLog:

        * gfortran.dg/pr95542.f90: New test.
---
From 8516d48a71043b08ba56bcd60f5d23ebce213ff3 Mon Sep 17 00:00:00 2001
From: Jerry DeLisle <[email protected]>
Date: Sun, 12 Jul 2026 15:25:18 -0700
Subject: [PATCH] fortran: [PR95542] Fix ICE for deferred-length CHARACTER
 result via host association

gfc_get_symbol_decl has an assert meant to verify that a deferred-length
string's length variable lives in the same scope as the symbol it
belongs to.  This is wrong when sym->backend_decl is itself the enclosing
function's FUNCTION_DECL.  The correct comparison is
DECL_CONTEXT (length) == sym->backend_decl directly.

This was hit when a deferred-length CHARACTER function's own result
was assigned to or read from a CONTAINED subprocedure via host
association.

	PR fortran/95542

gcc/fortran/ChangeLog:

	* trans-decl.cc (gfc_get_symbol_decl): When checking that a
	deferred-length string's length variable shares the symbol's
	scope, special-case sym->backend_decl being a FUNCTION_DECL
	(an implicit function-result variable): compare against
	sym->backend_decl directly instead of its own DECL_CONTEXT.

gcc/testsuite/ChangeLog:

	* gfortran.dg/pr95542.f90: New test.
---
 gcc/fortran/trans-decl.cc             |  9 +++++++--
 gcc/testsuite/gfortran.dg/pr95542.f90 | 21 +++++++++++++++++++++
 2 files changed, 28 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/pr95542.f90

diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc
index 47b28c1d003..df5aef2fd86 100644
--- a/gcc/fortran/trans-decl.cc
+++ b/gcc/fortran/trans-decl.cc
@@ -1848,10 +1848,15 @@ gfc_get_symbol_decl (gfc_symbol * sym)
 		    gfc_add_decl_to_parent_function (length);
 		}
 
+	      /* When the symbol's own backend_decl is a FUNCTION_DECL, its
+		 DECL_CONTEXT is where that function itself is declared, not
+		 where its locals live.  */
 	      gcc_assert (sym->backend_decl == current_function_decl
 			  ? DECL_CONTEXT (length) == current_function_decl
-			  : (DECL_CONTEXT (sym->backend_decl)
-			     == DECL_CONTEXT (length)));
+			  : (TREE_CODE (sym->backend_decl) == FUNCTION_DECL
+			     ? DECL_CONTEXT (length) == sym->backend_decl
+			     : (DECL_CONTEXT (sym->backend_decl)
+				== DECL_CONTEXT (length))));
 
 	      gfc_defer_symbol_init (sym);
 	    }
diff --git a/gcc/testsuite/gfortran.dg/pr95542.f90 b/gcc/testsuite/gfortran.dg/pr95542.f90
new file mode 100644
index 00000000000..7bb541e7cba
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr95542.f90
@@ -0,0 +1,21 @@
+! { dg-do run }
+! PR95542 - ICE in gfc_get_symbol_decl, at fortran/trans-decl.cc:1851
+!
+function f()
+  character(:), allocatable :: f
+  f = 'xyz'
+  call s
+contains
+  subroutine s
+    if (f /= 'xyz') stop 1
+  end subroutine s
+end function f
+
+program pr95542
+  interface
+    function f()
+      character(:), allocatable :: f
+    end function f
+  end interface
+  if (f() /= 'xyz') stop 2
+end program pr95542
-- 
2.55.0

Reply via email to