Hi all,

attached patch fixes the bug reported in pr 60334. The issue here was that the
function's result being (a pointer to) a deferred length char array. The string
length for the result value was wrapped in a local variable, whose value was
never written back to the string length of the result. This lead the calling
routine to take the length of the result to be random leading to a crash. 

This patch addresses the issue by preventing the instantiation of the local
var and instead using a reference to the parameter. This not only saves one
value on the stack, but also because for small functions the compiler will hold
all parameters in registers for a significant level of optimization, all the
overhead of memory access (I hope :-).

Bootstraps and regtests ok on x86_64-linux-gnu.

- Andre
-- 
Andre Vehreschild * Kreuzherrenstr. 8 * 52062 Aachen
Tel.: +49 241 9291018 * Email: ve...@gmx.de 

Attachment: pr60334_1.clog
Description: Binary data

diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 1e74125..86873f7 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -1333,12 +1333,30 @@ gfc_get_symbol_decl (gfc_symbol * sym)
 	     (sym->ts.u.cl->passed_length == sym->ts.u.cl->backend_decl))
 	    sym->ts.u.cl->backend_decl = NULL_TREE;
 
-	  if (sym->ts.deferred && fun_or_res
-		&& sym->ts.u.cl->passed_length == NULL
-		&& sym->ts.u.cl->backend_decl)
+	  if (sym->ts.deferred && byref)
 	    {
-	      sym->ts.u.cl->passed_length = sym->ts.u.cl->backend_decl;
-	      sym->ts.u.cl->backend_decl = NULL_TREE;
+	      /* The string length of a deferred char array is stored in the
+		 parameter at sym->ts.u.cl->backend_decl as a reference and
+		 marked as a result.  Exempt this variable from generating a
+		 temporary for it.  */
+	      if (sym->attr.result)
+		{
+		  /* We need to insert a indirect ref for param decls.  */
+		  if (sym->ts.u.cl->backend_decl
+		      && TREE_CODE (sym->ts.u.cl->backend_decl) == PARM_DECL)
+		    sym->ts.u.cl->backend_decl =
+			build_fold_indirect_ref (sym->ts.u.cl->backend_decl);
+		}
+	      /* For all other parameters make sure, that they are copied so
+		 that the value and any modifications are local to the routine
+		 by generating a temporary variable.  */
+	      else if (sym->attr.function
+		       && sym->ts.u.cl->passed_length == NULL
+		       && sym->ts.u.cl->backend_decl)
+		{
+		  sym->ts.u.cl->passed_length = sym->ts.u.cl->backend_decl;
+		  sym->ts.u.cl->backend_decl = NULL_TREE;
+		}
 	    }
 
 	  if (sym->ts.u.cl->backend_decl == NULL_TREE)
diff --git a/gcc/testsuite/gfortran.dg/deferred_type_param_6.f90 b/gcc/testsuite/gfortran.dg/deferred_type_param_6.f90
index eb00778..7016070 100644
--- a/gcc/testsuite/gfortran.dg/deferred_type_param_6.f90
+++ b/gcc/testsuite/gfortran.dg/deferred_type_param_6.f90
@@ -2,15 +2,20 @@
 !
 ! PR fortran/51055
 ! PR fortran/49110
-!
+! PR fortran/60334
 
 subroutine test()
   implicit none
   integer :: i = 5
   character(len=:), allocatable :: s1
+  character(len=:), pointer :: s2
+  character(len=5), target :: fifeC = 'FIVEC'
   call sub(s1, i)
   if (len(s1) /= 5) call abort()
   if (s1 /= "ZZZZZ") call abort()
+  s2 => subfunc()
+  if (len(s2) /= 5) call abort()
+  if (s2 /= "FIVEC") call abort()
 contains
   subroutine sub(str,j)
     character(len=:), allocatable :: str
@@ -19,6 +24,12 @@ contains
     if (len(str) /= 5) call abort()
     if (str /= "ZZZZZ") call abort()
   end subroutine sub
+  function subfunc() result(res)
+    character(len=:), pointer :: res
+    res => fifec
+    if (len(res) /= 5) call abort()
+    if (res /= "FIVEC") call abort()
+  end function subfunc
 end subroutine test
 
 program a

Reply via email to