[Bug fortran/32732] [Bind C] Character scalars are passed as arrays

Christopher D. Rickett crickett@lanl.gov
Mon Jul 30 19:54:00 GMT 2007


hi Steve,

first, a comment on the code snippet you gave: the reason you have to add 
-fno-underscoring is because your main program forgets to say 'use 
c_char_tests', so sub0 gets implicitly declared.

second, i think i've tracked down what was causing the problem with the 
code snippet.  the call to sub0 gets converted (gfc_conv_function_call) 
before the generate_local_decls runs for param_test.  this means that the 
symbols for the dummy args in the call still say they're an array_type, so 
the actuals given by sub0() are converted to array_type.  i think this 
means that the fixup done for by-value character dummies in 
generate_local_decl must also be done when mapping actuals to formals in 
gfc_conv_function_call.  i've attached a patch that does this.  it's been 
bootstrapped and regtested on x86 and x86_64 linux with no new failures, 
but the real test is whether they'll work for you.  :-)

thanks for all of your help in tracking down this bug.

Chris

PS: the tree dump did not change with this patch, but the output from 
debug_tree does and seems as i'd expect.

On Fri, 27 Jul 2007, Steve Ellcey wrote:

> So, I looked at gfortran.dg/c_char_tests.f03 to see why it still fails
> on IA64 HP-UX.  It looks like the previous patch handles functions that
> are called with C bindings but it doesn't handle one Fortran routine
> calling another Fortran routine with C bindings.  The caller is using
> Fortran semantics while the callee is expecting C semantics.  If you
> look at the tree dump below and the call to param_test from sub0, you
> see strings intead of just characters and I think that is the problem.
>
> I cut down the original test case to create a fortran only testcase
> (requires -fno-underscoring) which is the following:
>
> module c_char_tests
>  use, intrinsic :: iso_c_binding, only: c_char
>  implicit none
> contains
>  subroutine param_test(my_char, my_char_2) bind(c)
>    character(c_char), value :: my_char
>    character(c_char), value :: my_char_2
>    if(my_char /= c_char_'y') call abort()
>    if(my_char_2 /= c_char_'z') call abort()
>  end subroutine param_test
>
>  subroutine sub0() bind(c)
>    call param_test('y', 'z')
>  end subroutine sub0
> end module c_char_tests
>
> program main
>  call sub0()
> end program main
>
> ---------
>
> When I dump the tree (x.f03.003t.original), I see:
>
> sub0 ()
> {
>  param_test ("y", "z", 1, 1);
>
>
> param_test (my_char, my_char_2, _my_char, _my_char_2)
> {
>  if (my_char != 121)
>    {
>      _gfortran_abort ();
>    }
>  if (my_char_2 != 122)
>    {
>      _gfortran_abort ();
>    }
>
> MAIN__ ()
> {
>  static int4 options.2[7] = {68, 127, 0, 0, 0, 1, 0};
>
>  _gfortran_set_options (7, (void *) &options.2);
>  sub0 ();
> }
>
-------------- next part --------------
Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c	(revision 127065)
+++ gcc/fortran/trans-expr.c	(working copy)
@@ -1210,6 +1210,24 @@ gfc_to_single_character (tree len, tree 
   return NULL_TREE;
 }
 
+
+void
+gfc_conv_scalar_char_value (gfc_symbol *sym)
+{
+  TREE_TYPE (sym->backend_decl) = unsigned_char_type_node;
+
+  /* Next 3 lines taken from old set_tree_decl_type_code (...).
+     Need to be done for characters by-value in bind(c) routines so
+     the expected arg-type isn't an array_type.  */
+  DECL_BY_REFERENCE (sym->backend_decl) = 0;
+  DECL_ARG_TYPE (sym->backend_decl) = TREE_TYPE (sym->backend_decl);
+  DECL_MODE (sym->backend_decl) =
+    TYPE_MODE (TREE_TYPE (sym->backend_decl));
+
+  return;
+}
+
+
 /* Compare two strings. If they are all single characters, the result is the
    subtraction of them. Otherwise, we build a library call.  */
 
@@ -2167,6 +2185,13 @@ gfc_conv_function_call (gfc_se * se, gfc
             {
 	      if (fsym && fsym->attr.value)
 		{
+		  if (fsym->ts.type == BT_CHARACTER
+		      && fsym->backend_decl != NULL
+		      && fsym->ts.is_c_interop
+		      && fsym->ns->proc_name != NULL
+		      && fsym->ns->proc_name->attr.is_bind_c)
+		    gfc_conv_scalar_char_value (fsym);
+
 		  gfc_conv_expr (&parmse, e);
 		}
 	      else if (arg->name && arg->name[0] == '%')
Index: gcc/fortran/gfortran.h
===================================================================
--- gcc/fortran/gfortran.h	(revision 127065)
+++ gcc/fortran/gfortran.h	(working copy)
@@ -2048,6 +2048,9 @@ extern int gfc_charlen_int_kind;
 extern int gfc_numeric_storage_size;
 extern int gfc_character_storage_size;
 
+/* trans-expr.c */
+void gfc_conv_scalar_char_value (gfc_symbol *sym);
+
 /* symbol.c */
 void gfc_clear_new_implicit (void);
 try gfc_add_new_implicit_range (int, int);
Index: gcc/fortran/trans-decl.c
===================================================================
--- gcc/fortran/trans-decl.c	(revision 127065)
+++ gcc/fortran/trans-decl.c	(working copy)
@@ -3048,7 +3048,7 @@ generate_local_decl (gfc_symbol * sym)
       if (sym->attr.value == 1 && sym->backend_decl != NULL
 	  && sym->ts.type == BT_CHARACTER && sym->ts.is_c_interop
 	  && sym->ns->proc_name != NULL && sym->ns->proc_name->attr.is_bind_c)
-	TREE_TYPE (sym->backend_decl) = unsigned_char_type_node;
+	gfc_conv_scalar_char_value (sym);
     }
 
   /* Make sure we convert the types of the derived types from iso_c_binding


More information about the Fortran mailing list