Alternative for deferred length character arrays in common blocks? (crashes gfortran)

104 Views Asked by At

My goal is to call a C function to allocate Fortran dynamic arrays (which works fine for integer, real, logical already). But I'm having trouble with the gfortran compiler, character strings and common blocks. Here's a distillation of my roadblock:

      subroutine sub1()
      character(len=:), pointer :: local
      character(len=:), pointer :: comm
      common /commie/ comm
      comm = local
      return
      end

For some reason placing such a pointer into a common block confuses gfortran:

ghart@el9$ gfortran sub1.f
sub1.f:6:72:
    6 |       comm = local
      |                                                                        
1
internal compiler error: in gfc_conv_variable, at fortran/trans-expr.c:3036
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://bugzilla.redhat.com/bugzilla> for instructions.
ghart@el9$ gfortran --version
GNU Fortran (GCC) **11.3.1** 20220421 (Red Hat 11.3.1-2)

for years...

ghart@el8$ gfortran sub1.f
sub1.f:6:0:
       comm = local
internal compiler error: in gfc_conv_variable, at fortran/trans-expr.c:2726
....
ghart@el8$ gfortran --version
GNU Fortran (GCC) **8.5.0** 20210514 (Red Hat 8.5.0-10)

ghart@el7$ gfortran sub1.f
sub1.f: In function ?sub1?:
sub1.f:6:0: internal compiler error: in gfc_conv_variable, at fortran/trans-expr.c:1796
       comm = local
 ^
ghart@el7$ gfortran --version
GNU Fortran (GCC) **4.8.5** 20150623 (Red Hat 4.8.5-44)

(could be this: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55735)

But my real question: is there an alternative definition for a dynamically sized character string array (that I can put in a common block)? All I need is the declaration, which would allow existing Fortran code that uses something like:

  character(kind=ucs4, len=xxx) stringarray1(yyy)

to work as is, but is not this one:

  character(kind=ucs4, len=:) stringarray1(:)

To add some more context, here's the working code for integers:

        SUBROUTINE shob_arrI(ptr, decl, sz, grp)
          USE ISO_C_BINDING
          integer, pointer :: ptr(:)
          character*(*) decl
          integer*8 sz
          integer, pointer :: grp
        END SUBROUTINE shob_arrI
....
      integer, pointer :: grpX
      integer, pointer :: i1(:)
      common /grpX/ i1

      call shob_arrI(i1, 'integer i1(7)', 0_8, grpX)

shob_arrI is a C function which parses the definition ("integer i1(7)"), builds the gfortran GFC_ARRAY_DESCRIPTOR structure, and maps the actual array data area to a shared memory file (this is for multi-process access to shared arrays).

So what I'm looking for is the corresponding "integer, pointer :: ptr(:)" declaration for a character string array.

1

There are 1 best solutions below

7
steve On

Don't use common blocks.

module str
   character(len=:), pointer :: local
   character(len=:), pointer :: comm
end module str

subroutine sub1()
   use str
   local = 'abc'
   comm => local
   ! comm = local    ! Copy data into anonymous memory
   return
end

Edited: This allows your code to compile. Have no idea if the result is correct. Don't care.

diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index f052d6b9440..52d55322b04 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -2989,7 +2989,8 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
   sym = expr->symtree->n.sym;
   is_classarray = IS_CLASS_ARRAY (sym);
   ss = se->ss;
-  if (ss != NULL)
+
+  if (ss != NULL && ss->info)
     {
       gfc_ss_info *ss_info = ss->info;
 
@@ -3091,7 +3092,8 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
         se->string_length = sym->ns->proc_name->ts.u.cl->backend_decl;
       else
         se->string_length = sym->ts.u.cl->backend_decl;
-      gcc_assert (se->string_length);
+      if (!sym->ts.deferred)
+        gcc_assert (se->string_length);
     }
 
   gfc_typespec *ts = &sym->ts;

Edit**2: While the patch allows the example provided here to compile, a complete program leads to ICEs elsewhere.