[patch,gfortran] PR 24503: Character functions of non-constant length

Erik Edelmann erik.edelmann@iki.fi
Fri Oct 28 14:25:00 GMT 2005


On Thu, Oct 27, 2005 at 03:50:18PM +0300, Erik Edelmann wrote:
> On Wed, Oct 26, 2005 at 01:58:44PM +0300, Erik Edelmann wrote:
> > On Tue, Oct 25, 2005 at 10:44:26AM -0400, Jakub Jelinek wrote:
> > > Please test the same when using ENTRY without RESULT.
> > 
> > Ok. I tried, and it didn't work:
> 
>         <...>
> 
> > Am I doing something wrong, or are ENTRY in functions (of any
> > type) broken in gfortran? (Since this is the first time in my
> > life I use ENTRY, it's not unlikely that I'm doing something
> > wrong.  Both testcases compile and run without trouble in Absoft
> > and Intel compilers, but that does, after all, not prove
> > anything)
> 
> It seems that it's only in modules that ENTRY statements are
> completely broken (PR 24558).  For external functions, ENTRY:s
> work for other cases, but not (yet) for functions of type
> CHARACTER(len=<non-constant>).  If it passes testing, I'll post
> and extended version of my patch to address this problem tonight.

Ok, here it comes.  It's the same as my previous patch, with the
following addition: in trans-expr.c (gfc_conv_variable), if the
charcter length hasn't been set of an ENTRY, the length is taken
from the master function instead.  This is needed because the
character lengths of entries are set from the master function in
trans.decl.c (gfc_generate_function_code) before
gfc_get_fake_result_decl() (where character lengths for fake
result variables of non constant length is set), is called.

I have to admit that I'm not perfectly happy with the approach
taken by this patch.  I would prefer to have the character lentgh
set once and for all at one place, instead of having all these
'if (sym->ts.type == BT_CHARACTER && !sym->ts.cl->backend_decl)'
special cases scattered all over the code.  To achieve that,
however, doesn't seem to be easy (I tried a few different
approaches, but non would work).

Bubblestrapped and tested on Linux/x86.  OK to commit?



        Erik


(The PR number in the ChangeLog entries below has changed,
because PR 24503 was declared a duplicate of PR 18883)


2005-10-28  Erik Edelmann  <eedelman@gcc.gnu.org>

        PR fortran/18883
        * trans-decl.c (gfc_finish_var_decl): Add decl to the
        current function, rather than the parent.  Make
        assertion accept fake result variables.
        * trans-expr.c (gfc_conv_variable): If the character
        length of an ENTRY isn't set, get the length from
        the master function instead.



2005-10-28  Erik Edelmann  <eedelman@gcc.gnu.org>

        PR fortran/18883
        * gfortran.dg/char_result_9.f90: New.
        * gfortran.dg/char_result_10.f90: New.
-------------- next part --------------
Index: gcc/fortran/trans-decl.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/fortran/trans-decl.c,v
retrieving revision 1.74
diff -u -p -r1.74 trans-decl.c
--- gcc/fortran/trans-decl.c	25 Oct 2005 18:43:22 -0000	1.74
+++ gcc/fortran/trans-decl.c	28 Oct 2005 10:20:00 -0000
@@ -469,7 +469,8 @@ gfc_finish_var_decl (tree decl, gfc_symb
      function scope.  */
   if (current_function_decl != NULL_TREE)
     {
-      if (sym->ns->proc_name->backend_decl == current_function_decl)
+      if (sym->ns->proc_name->backend_decl == current_function_decl
+          || sym->result == sym)
 	gfc_add_decl_to_function (decl);
       else
 	gfc_add_decl_to_parent_function (decl);
@@ -487,7 +488,7 @@ gfc_finish_var_decl (tree decl, gfc_symb
   else if (sym->module && !sym->attr.result && !sym->attr.dummy)
     {
       /* TODO: Don't set sym->module for result or dummy variables.  */
-      gcc_assert (current_function_decl == NULL_TREE);
+      gcc_assert (current_function_decl == NULL_TREE || sym->result == sym);
       /* This is the declaration of a module variable.  */
       TREE_PUBLIC (decl) = 1;
       TREE_STATIC (decl) = 1;
Index: gcc/fortran/trans-expr.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/fortran/trans-expr.c,v
retrieving revision 1.68
diff -u -p -r1.68 trans-expr.c
--- gcc/fortran/trans-expr.c	25 Oct 2005 18:43:21 -0000	1.68
+++ gcc/fortran/trans-expr.c	28 Oct 2005 10:20:01 -0000
@@ -403,7 +403,12 @@ gfc_conv_variable (gfc_se * se, gfc_expr
   /* For character variables, also get the length.  */
   if (sym->ts.type == BT_CHARACTER)
     {
-      se->string_length = sym->ts.cl->backend_decl;
+      /* If the character length of an entry isn't set, get the length from
+         the master function instead.  */
+      if (sym->attr.entry && !sym->ts.cl->backend_decl)
+        se->string_length = sym->ns->proc_name->ts.cl->backend_decl;
+      else
+        se->string_length = sym->ts.cl->backend_decl;
       gcc_assert (se->string_length);
     }
 
-------------- next part --------------
! { dg-do compile }
! PR 18883: Fake result variables of non-constant length, in module
module foo
contains
    function s_to_c(chars)
        character, pointer :: chars(:)
        character(len=len(chars)) :: s_to_c
        s_to_c = 'a'
    end function s_to_c
end module foo

program huj

    use foo
    
    implicit none
    character, pointer :: c(:)
    character(3) :: s

    allocate(c(5))
    c = (/"a", "b", "c" /)
    s = s_to_c(c)

end program huj
-------------- next part --------------
! { dg-do compile }
! PR 18883: Fake result variables of non-constant length, with ENTRY
function s_to_c(chars)
    character, pointer :: chars(:)
    character(len=len(chars)) :: s_to_c, s_to_c_2
    s_to_c = 'a'
    return
entry s_to_c_2(chars)
    s_to_c_2 = 'b'
    return
end function s_to_c

program huj
    
    implicit none
    interface
        function s_to_c(chars)
            character, pointer :: chars(:)
            character(len=len(chars)) :: s_to_c
        end function s_to_c

        function s_to_c_2(chars)
            character, pointer :: chars(:)
            character(len=len(chars)) :: s_to_c_2
        end function s_to_c_2
    end interface

    character, pointer :: c(:)
    character(3) :: s

    allocate(c(5))
    c = (/"a", "b", "c" /)
    s = s_to_c(c)
    s = s_to_c_2(c)

end program huj


More information about the Fortran mailing list