https://gcc.gnu.org/g:53b64337ef325c4e47ae96ea8dea86031a3a0602

commit r16-2453-g53b64337ef325c4e47ae96ea8dea86031a3a0602
Author: Harald Anlauf <anl...@gmx.de>
Date:   Tue Jul 22 20:16:16 2025 +0200

    Fortran: fix passing of character length of function to procedure [PR121203]
    
            PR fortran/121203
    
    gcc/fortran/ChangeLog:
    
            * trans-expr.cc (gfc_conv_procedure_call): Obtain the character
            length of an assumed character length procedure from the typespec
            of the actual argument even if there is no explicit interface.
    
    gcc/testsuite/ChangeLog:
    
            * gfortran.dg/function_charlen_4.f90: New test.

Diff:
---
 gcc/fortran/trans-expr.cc                        | 26 +++++++++---------
 gcc/testsuite/gfortran.dg/function_charlen_4.f90 | 34 ++++++++++++++++++++++++
 2 files changed, 47 insertions(+), 13 deletions(-)

diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 6fa52d0ffef3..7c7621571ad0 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -7909,21 +7909,21 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
          se->ss->info->class_container = arg1_cntnr;
        }
 
-      if (fsym && e)
+      /* Obtain the character length of an assumed character length procedure
+        from the typespec of the actual argument.  */
+      if (e
+         && parmse.string_length == NULL_TREE
+         && e->ts.type == BT_PROCEDURE
+         && e->symtree->n.sym->ts.type == BT_CHARACTER
+         && e->symtree->n.sym->ts.u.cl->length != NULL
+         && e->symtree->n.sym->ts.u.cl->length->expr_type == EXPR_CONSTANT)
        {
-         /* Obtain the character length of an assumed character length
-            length procedure from the typespec.  */
-         if (fsym->ts.type == BT_CHARACTER
-             && parmse.string_length == NULL_TREE
-             && e->ts.type == BT_PROCEDURE
-             && e->symtree->n.sym->ts.type == BT_CHARACTER
-             && e->symtree->n.sym->ts.u.cl->length != NULL
-             && e->symtree->n.sym->ts.u.cl->length->expr_type == EXPR_CONSTANT)
-           {
-             gfc_conv_const_charlen (e->symtree->n.sym->ts.u.cl);
-             parmse.string_length = e->symtree->n.sym->ts.u.cl->backend_decl;
-           }
+         gfc_conv_const_charlen (e->symtree->n.sym->ts.u.cl);
+         parmse.string_length = e->symtree->n.sym->ts.u.cl->backend_decl;
+       }
 
+      if (fsym && e)
+       {
          /* Obtain the character length for a NULL() actual with a character
             MOLD argument.  Otherwise substitute a suitable dummy length.
             Here we handle non-optional dummies of non-bind(c) procedures.  */
diff --git a/gcc/testsuite/gfortran.dg/function_charlen_4.f90 
b/gcc/testsuite/gfortran.dg/function_charlen_4.f90
new file mode 100644
index 000000000000..ed39aca4f42f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/function_charlen_4.f90
@@ -0,0 +1,34 @@
+! { dg-do run }
+! { dg-options "-O2 -std=legacy -fdump-tree-optimized" }
+!
+! PR fortran/121203 - fix passing of character length of function to procedure
+
+program p
+  character(10), external :: f
+  call eval (f,"abc")
+  call eval2(f,"abc")
+contains
+  subroutine eval2(func,c_arg)
+    character(*) c_arg
+    character(*) func
+    external func
+    ! These tests should get optimized:
+    if (len      (c_arg)  /=  3) stop 1
+    if (len (func(c_arg)) /= 10) stop 2
+  end subroutine
+end
+
+character(10) function f(arg)
+  character(*) arg
+  f=arg
+end
+
+subroutine eval(func,c_arg)
+  character(*) c_arg
+  character(*) func
+  external func
+  if (len      (c_arg)  /=  3) error stop 3
+  if (len (func(c_arg)) /= 10) error stop 4
+end subroutine
+
+! { dg-final { scan-tree-dump-not "_gfortran_stop_numeric" "optimized" } }

Reply via email to