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