This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug fortran/34199] segfault for TRANSFER integer to TYPE(C_PTR)



------- Comment #3 from fxcoudert at gcc dot gnu dot org  2008-02-24 14:04 -------
The ICE itself can be gotten rid of by setting the offset of the private field
of our ISO_C derived types:

Index: trans-types.c
===================================================================
--- trans-types.c       (revision 132578)
+++ trans-types.c       (working copy)
@@ -1731,6 +1731,7 @@
                                 get_identifier (derived->components->name),
                                 gfc_typenode_for_spec (
                                   &(derived->components->ts)));
+      DECL_FIELD_OFFSET (derived->components->backend_decl) = size_int (0);

       derived->ts.kind = gfc_index_integer_kind;
       derived->ts.type = BT_INTEGER;


(Independently of the rest, I think that fix is desirable.) However, with that
fix, we now error out:

   C_NULL_PTR1 = transfer(0_C_INTPTR_T, C_NULL_PTR1)
                1
Error: Can't convert INTEGER(4) to TYPE(c_ptr) at (1)

The reason for that is that gfc_typenode_for_spec(), which is called from
gfc_interpret_derived(), modifies the symbol itself to make it an integer:

      /* If we're dealing with either C_PTR or C_FUNPTR, we modified the
         type and kind to fit a (void *) and the basetype returned was a
         ptr_type_node.  We need to pass up this new information to the
         symbol that was declared of type C_PTR or C_FUNPTR.  */

I have always been wary of this course of actions (magically making the
ISO_C_BINDING derived types into scalar integer variables), and in that case it
is biting us hard. I have tried to work around this in target-memory.c by a
custom-tailored fix:

Index: target-memory.c
===================================================================
--- target-memory.c     (revision 132578)
+++ target-memory.c     (working copy)
@@ -379,7 +379,21 @@
   /* The attributes of the derived type need to be bolted to the floor.  */
   result->expr_type = EXPR_STRUCTURE;

-  type = gfc_typenode_for_spec (&result->ts);
+  /* FIXME -- This is more of a workaround than a real fix, please see
+     PR34199 for details.
+     For ISO_C_BINDING derived types, gfc_typenode_for_spec() will change
+     the symbol under our feet into an integer, which we don't want, so
+     we restore it.  */
+  if (result->ts.type == BT_DERIVED && result->ts.derived->attr.is_iso_c)
+    {
+      gfc_typespec ts;
+      ts = result->ts;
+      type = gfc_typenode_for_spec (&result->ts);
+      result->ts = ts;
+    }
+  else
+    type = gfc_typenode_for_spec (&result->ts);
+
   cmp = result->ts.derived->components;

   /* Run through the derived type components.  */


This in turn makes the derived type constructors go into trans-expr.c's
gfc_conv_expr(), which does not deal with them. This is fixed with the
following patchlet:

Index: trans-expr.c
===================================================================
--- trans-expr.c        (revision 132578)
+++ trans-expr.c        (working copy)
@@ -3517,14 +3517,19 @@
     }

   /* We need to convert the expressions for the iso_c_binding derived types.
-     C_NULL_PTR and C_NULL_FUNPTR will be made EXPR_NULL, which evaluates to
-     null_pointer_node.  C_PTR and C_FUNPTR are converted to match the
-     typespec for the C_PTR and C_FUNPTR symbols, which has already been
-     updated to be an integer with a kind equal to the size of a (void *).  */
+     C_NULL_PTR, C_NULL_FUNPTR and constants (coming, for example, from the
+     simplification of TRANSFER expressions) will be made EXPR_NULL,
+     which evaluates to null_pointer_node.  C_PTR and C_FUNPTR are converted
+     to match the typespec for the C_PTR and C_FUNPTR symbols, which has
+     already been updated to be an integer with a kind equal to the size of
+     a (void *).  */
   if (expr->ts.type == BT_DERIVED && expr->ts.derived
       && expr->ts.derived->attr.is_iso_c)
     {
-      if (expr->symtree->n.sym->intmod_sym_id == ISOCBINDING_NULL_PTR
+      /* expr->expr_type == EXPR_STRUCTURE matches the constant derived
+         types.  */
+      if (expr->expr_type == EXPR_STRUCTURE
+         || expr->symtree->n.sym->intmod_sym_id == ISOCBINDING_NULL_PTR
           || expr->symtree->n.sym->intmod_sym_id == ISOCBINDING_NULL_FUNPTR)
         {
          /* Set expr_type to EXPR_NULL, which will result in


Now, with all three patches, we can compile the testcase and run it fine. I'm
not really satisfied with the patch to target-memory.c, as it is more a
workaround than a patch. For that reason, I'm not assigning this to myself and
will let the ISO_C_BINDING experts decide what course is most appropriate.


-- 

fxcoudert at gcc dot gnu dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |fxcoudert at gcc dot gnu dot
                   |                            |org
           Keywords|                            |patch
   Last reconfirmed|2007-11-25 03:11:32         |2008-02-24 14:04:05
               date|                            |


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34199


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]