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

Christopher D. Rickett crickett@lanl.gov
Wed Aug 1 23:27:00 GMT 2007


hi Steve,

i've attached another attempt at this patch.  it should promote the type 
of character args to bind(c) routines and should convert the expressions 
for the actuals.  i haven't finished the expression handling done in 
gfc_conv_scalar_char_value yet; i wanted to see if this patch works for 
you first.  based on the tree dump, it should at least be an improvement 
over what happens now.

bootstrapped and regtested on x86 and x86_64 linux, and ppc64 darwin8 with 
no new failures.

please give it a try and let me know.  thanks.
Chris

On Mon, 30 Jul 2007, Steve Ellcey wrote:

>> thanks for trying it out.  i'm quite at a loss now as to why it's failing;
>> i thought that fixing the array_type still being seen in
>> gfc_conv_function_call would do it.  now i'm not even sure where to start
>> looking...  the only thing i could think to do now is to run cc1 through
>> gdb and figure out what the C frontend is doing with characters that isn't
>> happening on the fortran side.  it would be good to see the debug_tree
>> output for the tree created by cc1, but that would be a bit more work for
>> you.  i'll see if i can figure out where to put the call to debug_tree and
>> maybe pass it on to you.
>>
>> thanks again for all of the help.
>> Chris
>
> I wonder if we have to do more than change the type.  If I understand
> the code correctly we have converted the type of the formal parameter in
> the call from an array of char to just a char.  But the actual argument
> to the call (the variable or constant being passed) is still an array of
> char.  Do we need code to change the actual argument so we wind up
> passing "array[1]" instead of "array", i.e.  to pass in just the first
> element of the array instead of the entire array.
>
> In C, if I have
>
> 	char s[10];
> 	call foo(s);
>
> That is different then
>
> 	char s[10];
> 	call foo(s[0]);
>
> Regardless of what prototype foo has and what type we claim the argument
> to foo is.
>
> Steve Ellcey
> sje@cup.hp.com
>
-------------- 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,58 @@ gfc_to_single_character (tree len, tree 
   return NULL_TREE;
 }
 
+
+void
+gfc_conv_scalar_char_value (gfc_symbol *sym, gfc_se *se, gfc_expr **expr)
+{
+  gfc_expr *tmp_expr;
+  
+  /* This becomes the nominal_type in
+     function.c:assign_parm_find_data_types.  */
+  TREE_TYPE (sym->backend_decl) = unsigned_char_type_node;
+  /* This becomes the passed_type in
+     function.c:assign_parm_find_data_types.  C promotes char to integer for
+     argument passing.  */
+  DECL_ARG_TYPE (sym->backend_decl) = unsigned_type_node;
+
+  DECL_BY_REFERENCE (sym->backend_decl) = 0;
+
+  if (expr != NULL)
+    {
+      /* If we have a constant character expression, make it into an
+	 integer.  */
+      if ((*expr)->expr_type == EXPR_CONSTANT)
+        {
+	  tmp_expr = *expr;
+	  *expr = gfc_int_expr ((int)tmp_expr->value.character.string[0]);
+	  gfc_free_expr (tmp_expr);
+	}
+      else if (se != NULL && (*expr)->expr_type == EXPR_VARIABLE)
+        {
+	  if ((*expr)->ref == NULL)
+	    {
+	      tmp_expr = *expr;
+	      se->expr = gfc_to_single_character
+		(build_int_cst (integer_type_node, 1),
+		 gfc_build_addr_expr (pchar_type_node,
+				      gfc_get_symbol_decl
+				      ((*expr)->symtree->n.sym)));
+	      gfc_free_expr (tmp_expr);
+	    }
+	  else
+	    {
+	      gfc_conv_variable (se, *expr);
+	      se->expr = gfc_to_single_character
+		(build_int_cst (integer_type_node, 1),
+		 gfc_build_addr_expr (pchar_type_node, se->expr));
+	    }
+	}
+    }
+  
+  return;
+}
+
+
 /* Compare two strings. If they are all single characters, the result is the
    subtraction of them. Otherwise, we build a library call.  */
 
@@ -2167,7 +2219,19 @@ gfc_conv_function_call (gfc_se * se, gfc
             {
 	      if (fsym && fsym->attr.value)
 		{
-		  gfc_conv_expr (&parmse, e);
+		  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)
+		    {
+		      parmse.expr = NULL;
+		      gfc_conv_scalar_char_value (fsym, &parmse, &e);
+		      if (parmse.expr == NULL)
+			gfc_conv_expr (&parmse, e);
+		    }
+		  else
+		    gfc_conv_expr (&parmse, e);
 		}
 	      else if (arg->name && arg->name[0] == '%')
 		/* Argument list functions %VAL, %LOC and %REF are signalled
Index: gcc/fortran/trans.h
===================================================================
--- gcc/fortran/trans.h	(revision 127065)
+++ gcc/fortran/trans.h	(working copy)
@@ -296,6 +296,9 @@ void gfc_conv_expr_lhs (gfc_se * se, gfc
 void gfc_conv_expr_reference (gfc_se * se, gfc_expr *);
 void gfc_conv_expr_type (gfc_se * se, gfc_expr *, tree);
 
+/* trans-expr.c */
+void gfc_conv_scalar_char_value (gfc_symbol *sym, gfc_se *se, gfc_expr **expr);
+
 /* Find the decl containing the auxiliary variables for assigned variables.  */
 void gfc_conv_label_variable (gfc_se * se, gfc_expr * expr);
 /* If the value is not constant, Create a temporary and copy the value.  */
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, NULL, NULL);
     }
 
   /* Make sure we convert the types of the derived types from iso_c_binding


More information about the Fortran mailing list