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

Christopher D. Rickett crickett@lanl.gov
Fri Aug 3 19:55:00 GMT 2007


:ADDPATCH fortran:

the patch is attached.  bootstrapped and regtested on x86 and x86_64 linux 
with no new failures.

ChangeLog entry:
2007-08-03  Christopher D. Rickett  <crickett@lanl.gov>

 	PR fortran/32732
 	* trans-expr.c (gfc_conv_scalar_char_value): Convert the tree and
 	actual arg expressions for scalar characters passed by-value to
 	bind(c) routines.
 	(gfc_conv_function_call): Call gfc_conv_scalar_char_value.
 	* trans.h: Add prototype for gfc_conv_scalar_char_value.
 	* trans-decl.c (generate_local_decl): Convert by-value character
 	dummy args of bind(c) procedures using
 	gfc_conv_scalar_char_value.


Chris

On Fri, 3 Aug 2007, Christopher D. Rickett wrote:

>
>
>> My IA64 HP-UX and Linux runs look good too.  c_kind_params.f90 fails to
>> compile on my HPPA HP-UX platforms but that is probably due to HPPA's
>> incomplete support for C99 and not defining the __int64_t type.  I will
>> look into how to fix that, but I don't see any runtime problems or
>> regressions so I think the patch should be checked in.
>> 
>> Thanks a lot for for all your work in coming up with this fix.
>> 
>
> thanks for all of your testing and debugging help.  i'll submit a patch later 
> today.
>
> Chris
>
-------------- next part --------------
Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c	(revision 127182)
+++ gcc/fortran/trans-expr.c	(working copy)
@@ -1209,6 +1209,59 @@ 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;
+
+  if (sym->backend_decl)
+    {
+      /* 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]);
+	}
+      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)));
+	    }
+	  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.  */
 
@@ -2166,7 +2219,18 @@ 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->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 127182)
+++ gcc/fortran/trans.h	(working copy)
@@ -295,6 +295,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 127182)
+++ gcc/fortran/trans-decl.c	(working copy)
@@ -3047,7 +3047,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