[Bug fortran/32732] [Bind C] Character scalars are passed as arrays
Christopher D. Rickett
crickett@lanl.gov
Thu Aug 2 20:57:00 GMT 2007
hi Steve,
i think it's safe to ignore the fsym->backend_decl if it's null, because,
in the case of main, it won't have been processed yet. the
gfc_conv_scalar_char_value should still be able to at least modify the
expression for the actual arg in this case. i've attached a new patch for
trans-expr.c that now generates the following dump for MAIN__ in value_6:
MAIN__ ()
{
static int4 options.3[7] = {68, 127, 0, 0, 0, 1, 0};
_gfortran_set_options (7, (void *) &options.3);
test (97);
}
please give the attached patch a try. i have NOT regtested it, but plan
to now. the new patch may conflict with the previous one, so it may be
simpler to modify the few lines by hand, or revert the other.
thanks.
Chris
On Thu, 2 Aug 2007, Christopher D. Rickett wrote:
> hi Steve,
>
> thanks for looking into this. i'm seeing the same problem. the following is
> what -fdump-tree-original gives for MAIN__ for value_6:
>
> MAIN__ ()
> {
> static int4 options.3[7] = {68, 127, 0, 0, 0, 1, 0};
>
> _gfortran_set_options (7, (void *) &options.3);
> test ("a", 1);
> }
>
> i'll see if i can find a way around this.
> Chris
>
> On Thu, 2 Aug 2007, Steve Ellcey wrote:
>
>> So I did some investigating into why this patch didn't fix value_6.f03.
>> It looks like the problem is with the call from main to test. Main is
>> still passing 'a' as an array of char instead of just a char.
>>
>> It looks like gfc_conv_function_call is not calling
>> gfc_conv_scalar_char_value at the call to test in this test case.
>> Looking at the if statement protecting that call, I see:
>>
>> if (fsym->ts.type == BT_CHARACTER /* TRUE */
>> && fsym->backend_decl != NULL /* FALSE */
>> && fsym->ts.is_c_interop /* TRUE */
>> && fsym->ns->proc_name != NULL /* TRUE */
>> && fsym->ns->proc_name->attr.is_bind_c) /* TRUE */
>>
>> So the problem is that fsym->backend_decl is NULL. I am not sure how
>> to address this.
>>
>> Steve Ellcey
>> sje@cup.hp.com
>>
>
-------------- next part --------------
Index: trans-expr.c
===================================================================
--- trans-expr.c (revision 127065)
+++ trans-expr.c (working copy)
@@ -1210,6 +1210,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. */
@@ -2167,6 +2220,17 @@ gfc_conv_function_call (gfc_se * se, gfc
{
if (fsym && fsym->attr.value)
{
+ 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] == '%')
More information about the Fortran
mailing list