[gcc r17-3339] fortran: [PR95542] Fix ICE for deferred-length CHARACTER result via host association

Jerry DeLisle via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:47ec169c00cd1da6a9b0cecf871ccfb2a26fd63c

commit r17-3339-g47ec169c00cd1da6a9b0cecf871ccfb2a26fd63c
Author: Jerry DeLisle <[email protected]>
Date:   Sun Jul 12 15:25:18 2026 -0700

    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.

Diff:
---
 gcc/fortran/trans-decl.cc             |  7 +++++--
 gcc/testsuite/gfortran.dg/pr95542.f90 | 21 +++++++++++++++++++++
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc
index e277f2b2ccc6..5678f69df9ca 100644
--- a/gcc/fortran/trans-decl.cc
+++ b/gcc/fortran/trans-decl.cc
@@ -1846,8 +1846,11 @@ gfc_get_symbol_decl (gfc_symbol * sym)
 		    gfc_add_decl_to_parent_function (length);
 		}
 
-	      gcc_assert (sym->backend_decl == current_function_decl
-			  ? DECL_CONTEXT (length) == current_function_decl
+	      /* 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 (TREE_CODE (sym->backend_decl) == FUNCTION_DECL
+			  ? DECL_CONTEXT (length) == sym->backend_decl
 			  : (DECL_CONTEXT (sym->backend_decl)
 			     == DECL_CONTEXT (length)));
 
diff --git a/gcc/testsuite/gfortran.dg/pr95542.f90 b/gcc/testsuite/gfortran.dg/pr95542.f90
new file mode 100644
index 000000000000..7bb541e7cba1
--- /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
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.