[PATCH] fortran PR95542 Fix ICE for deferred-length CHARACTER, result via host association

Jerry D <[email protected]>
Newsgroups gmane.comp.gcc.patches,gmane.comp.gcc.fortran
Message-ID <[email protected]>
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.
---
PR95542.patch (text/x-patch, 2.8 KB)
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.