aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorChristopher D. Rickett <crickett@lanl.gov>2007-08-07 00:27:25 +0000
committerSteven G. Kargl <kargl@gcc.gnu.org>2007-08-07 00:27:25 +0000
commite032c2a16e87f7e1a3d00be8c0f962104038b088 (patch)
tree9c712a82e188eac02acefd1674eeebba1a691c46 /gcc
parent55eece47212d1846d59de07dfeb762692614265a (diff)
downloadgcc-e032c2a16e87f7e1a3d00be8c0f962104038b088.zip
gcc-e032c2a16e87f7e1a3d00be8c0f962104038b088.tar.gz
gcc-e032c2a16e87f7e1a3d00be8c0f962104038b088.tar.bz2
re PR fortran/32732 ([Bind C] Character scalars are passed as arrays)
2007-08-06 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. From-SVN: r127265
Diffstat (limited to 'gcc')
-rw-r--r--gcc/fortran/ChangeLog12
-rw-r--r--gcc/fortran/trans-decl.c2
-rw-r--r--gcc/fortran/trans-expr.c71
-rw-r--r--gcc/fortran/trans.h3
4 files changed, 86 insertions, 2 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index dc5a09e..438fde0 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,15 @@
+2007-08-06 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.
+
2007-08-06 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
PR fortran/30947
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index c9a195f..845bbf1 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -3055,7 +3055,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
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 17cf734..674448b 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -1209,6 +1209,64 @@ gfc_to_single_character (tree len, tree str)
return NULL_TREE;
}
+
+void
+gfc_conv_scalar_char_value (gfc_symbol *sym, gfc_se *se, gfc_expr **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)
+ {
+ gfc_typespec ts;
+
+ *expr = gfc_int_expr ((int)(*expr)->value.character.string[0]);
+ if ((*expr)->ts.kind != gfc_c_int_kind)
+ {
+ /* The expr needs to be compatible with a C int. If the
+ conversion fails, then the 2 causes an ICE. */
+ ts.type = BT_INTEGER;
+ ts.kind = gfc_c_int_kind;
+ gfc_convert_type (*expr, &ts, 2);
+ }
+ }
+ else if (se != NULL && (*expr)->expr_type == EXPR_VARIABLE)
+ {
+ if ((*expr)->ref == NULL)
+ {
+ 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));
+ }
+ }
+ }
+}
+
+
/* Compare two strings. If they are all single characters, the result is the
subtraction of them. Otherwise, we build a library call. */
@@ -2166,7 +2224,18 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
{
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
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 8226187..645f9a3 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -295,6 +295,9 @@ void gfc_conv_expr_lhs (gfc_se * se, gfc_expr * expr);
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. */