[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