Commit 72caba17 by Paul Thomas

re PR fortran/16939 (Pointers not passed as subroutine arguments)

2005-05-29 Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/16939
	PR fortran/17192
	PR fortran/17193
	PR fortran/17202
	PR fortran/18689
	PR fortran/18890
	PR fortran/21297
	* fortran/trans-array.c (gfc_conv_resolve_dependencies): Add string
	length to temp_ss for character pointer array assignments.
	* fortran/trans-expr.c (gfc_conv_variable): Correct errors in
	dereferencing of characters and character pointers.
	* fortran/trans-expr.c (gfc_conv_function_call): Provide string
	length as return argument for various kinds of handling of return.
	Return a char[]* temporary for character pointer functions and
	dereference the temporary upon return.

From-SVN: r100324
parent 0ac2a27a
...@@ -2342,7 +2342,7 @@ gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest, ...@@ -2342,7 +2342,7 @@ gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
loop->temp_ss->type = GFC_SS_TEMP; loop->temp_ss->type = GFC_SS_TEMP;
loop->temp_ss->data.temp.type = loop->temp_ss->data.temp.type =
gfc_get_element_type (TREE_TYPE (dest->data.info.descriptor)); gfc_get_element_type (TREE_TYPE (dest->data.info.descriptor));
loop->temp_ss->string_length = NULL_TREE; loop->temp_ss->string_length = dest->string_length;
loop->temp_ss->data.temp.dimen = loop->dimen; loop->temp_ss->data.temp.dimen = loop->dimen;
loop->temp_ss->next = gfc_ss_terminator; loop->temp_ss->next = gfc_ss_terminator;
gfc_add_ss_to_loop (loop, loop->temp_ss); gfc_add_ss_to_loop (loop, loop->temp_ss);
...@@ -3617,6 +3617,7 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss) ...@@ -3617,6 +3617,7 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
loop.temp_ss->type = GFC_SS_TEMP; loop.temp_ss->type = GFC_SS_TEMP;
loop.temp_ss->next = gfc_ss_terminator; loop.temp_ss->next = gfc_ss_terminator;
loop.temp_ss->data.temp.type = gfc_typenode_for_spec (&expr->ts); loop.temp_ss->data.temp.type = gfc_typenode_for_spec (&expr->ts);
/* ... which can hold our string, if present. */ /* ... which can hold our string, if present. */
if (expr->ts.type == BT_CHARACTER) if (expr->ts.type == BT_CHARACTER)
se->string_length = loop.temp_ss->string_length se->string_length = loop.temp_ss->string_length
......
...@@ -356,27 +356,40 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr) ...@@ -356,27 +356,40 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
return; return;
} }
/* Dereference scalar dummy variables. */
if (sym->attr.dummy /* Dereference the expression, where needed. Since characters
&& sym->ts.type != BT_CHARACTER are entirely different from other types, they are treated
&& !sym->attr.dimension) separately. */
if (sym->ts.type == BT_CHARACTER)
{
/* Dereference character pointer dummy arguments
or results. */
if ((sym->attr.pointer || sym->attr.allocatable)
&& ((sym->attr.dummy)
|| (sym->attr.function
|| sym->attr.result)))
se->expr = gfc_build_indirect_ref (se->expr);
}
else
{
/* Dereference non-charcter scalar dummy arguments. */
if ((sym->attr.dummy) && (!sym->attr.dimension))
se->expr = gfc_build_indirect_ref (se->expr); se->expr = gfc_build_indirect_ref (se->expr);
/* Dereference scalar hidden result. */ /* Dereference scalar hidden result. */
if (gfc_option.flag_f2c if ((gfc_option.flag_f2c && sym->ts.type == BT_COMPLEX)
&& (sym->attr.function || sym->attr.result) && (sym->attr.function || sym->attr.result)
&& sym->ts.type == BT_COMPLEX && (!sym->attr.dimension))
&& !sym->attr.dimension)
se->expr = gfc_build_indirect_ref (se->expr); se->expr = gfc_build_indirect_ref (se->expr);
/* Dereference pointer variables. */ /* Dereference non-character pointer variables.
These must be dummys or results or scalars. */
if ((sym->attr.pointer || sym->attr.allocatable) if ((sym->attr.pointer || sym->attr.allocatable)
&& (sym->attr.dummy && ((sym->attr.dummy)
|| sym->attr.result || (sym->attr.function || sym->attr.result)
|| sym->attr.function || (!sym->attr.dimension)))
|| !sym->attr.dimension)
&& sym->ts.type != BT_CHARACTER)
se->expr = gfc_build_indirect_ref (se->expr); se->expr = gfc_build_indirect_ref (se->expr);
}
ref = expr->ref; ref = expr->ref;
} }
...@@ -1083,6 +1096,15 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym, ...@@ -1083,6 +1096,15 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
var = NULL_TREE; var = NULL_TREE;
len = NULL_TREE; len = NULL_TREE;
/* Obtain the string length now because it is needed often below. */
if (sym->ts.type == BT_CHARACTER)
{
gcc_assert (sym->ts.cl && sym->ts.cl->length
&& sym->ts.cl->length->expr_type == EXPR_CONSTANT);
len = gfc_conv_mpz_to_tree
(sym->ts.cl->length->value.integer, sym->ts.cl->length->ts.kind);
}
if (se->ss != NULL) if (se->ss != NULL)
{ {
if (!sym->attr.elemental) if (!sym->attr.elemental)
...@@ -1097,6 +1119,9 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym, ...@@ -1097,6 +1119,9 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
/* Access the previously obtained result. */ /* Access the previously obtained result. */
gfc_conv_tmp_array_ref (se); gfc_conv_tmp_array_ref (se);
gfc_advance_se_ss_chain (se); gfc_advance_se_ss_chain (se);
/* Bundle in the string length. */
se->string_length=len;
return; return;
} }
} }
...@@ -1109,13 +1134,25 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym, ...@@ -1109,13 +1134,25 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
if (byref) if (byref)
{ {
if (se->direct_byref) if (se->direct_byref)
{
arglist = gfc_chainon_list (arglist, se->expr); arglist = gfc_chainon_list (arglist, se->expr);
/* Add string length to argument list. */
if (sym->ts.type == BT_CHARACTER)
{
sym->ts.cl->backend_decl = len;
arglist = gfc_chainon_list (arglist,
convert (gfc_charlen_type_node, len));
}
}
else if (sym->result->attr.dimension) else if (sym->result->attr.dimension)
{ {
gcc_assert (se->loop && se->ss); gcc_assert (se->loop && se->ss);
/* Set the type of the array. */ /* Set the type of the array. */
tmp = gfc_typenode_for_spec (&sym->ts); tmp = gfc_typenode_for_spec (&sym->ts);
info->dimen = se->loop->dimen; info->dimen = se->loop->dimen;
/* Allocate a temporary to store the result. */ /* Allocate a temporary to store the result. */
gfc_trans_allocate_temp_array (se->loop, info, tmp); gfc_trans_allocate_temp_array (se->loop, info, tmp);
...@@ -1124,22 +1161,46 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym, ...@@ -1124,22 +1161,46 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
gfc_conv_descriptor_stride (info->descriptor, gfc_rank_cst[0]); gfc_conv_descriptor_stride (info->descriptor, gfc_rank_cst[0]);
gfc_add_modify_expr (&se->pre, tmp, gfc_add_modify_expr (&se->pre, tmp,
convert (TREE_TYPE (tmp), integer_zero_node)); convert (TREE_TYPE (tmp), integer_zero_node));
/* Pass the temporary as the first argument. */ /* Pass the temporary as the first argument. */
tmp = info->descriptor; tmp = info->descriptor;
tmp = gfc_build_addr_expr (NULL, tmp); tmp = gfc_build_addr_expr (NULL, tmp);
arglist = gfc_chainon_list (arglist, tmp); arglist = gfc_chainon_list (arglist, tmp);
/* Add string length to argument list. */
if (sym->ts.type == BT_CHARACTER)
{
sym->ts.cl->backend_decl = len;
arglist = gfc_chainon_list (arglist,
convert (gfc_charlen_type_node, len));
}
} }
else if (sym->ts.type == BT_CHARACTER) else if (sym->ts.type == BT_CHARACTER)
{ {
gcc_assert (sym->ts.cl && sym->ts.cl->length
&& sym->ts.cl->length->expr_type == EXPR_CONSTANT); /* Pass the string length. */
len = gfc_conv_mpz_to_tree
(sym->ts.cl->length->value.integer, sym->ts.cl->length->ts.kind);
sym->ts.cl->backend_decl = len; sym->ts.cl->backend_decl = len;
type = gfc_get_character_type (sym->ts.kind, sym->ts.cl); type = gfc_get_character_type (sym->ts.kind, sym->ts.cl);
type = build_pointer_type (type); type = build_pointer_type (type);
/* Return an address to a char[4]* temporary for character pointers. */
if (sym->attr.pointer || sym->attr.allocatable)
{
/* Build char[4] * pstr. */
tmp = fold_build2 (MINUS_EXPR, gfc_charlen_type_node, len,
convert (gfc_charlen_type_node, integer_one_node));
tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
tmp = build_array_type (gfc_character1_type_node, tmp);
var = gfc_create_var (build_pointer_type (tmp), "pstr");
/* Provide an address expression for the function arguments. */
var = gfc_build_addr_expr (NULL, var);
}
else
{
var = gfc_conv_string_tmp (se, type, len); var = gfc_conv_string_tmp (se, type, len);
}
arglist = gfc_chainon_list (arglist, var); arglist = gfc_chainon_list (arglist, var);
arglist = gfc_chainon_list (arglist, arglist = gfc_chainon_list (arglist,
convert (gfc_charlen_type_node, len)); convert (gfc_charlen_type_node, len));
...@@ -1299,10 +1360,17 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym, ...@@ -1299,10 +1360,17 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
gfc_trans_runtime_check (tmp, gfc_strconst_fault, &se->pre); gfc_trans_runtime_check (tmp, gfc_strconst_fault, &se->pre);
} }
se->expr = info->descriptor; se->expr = info->descriptor;
/* Bundle in the string length. */
se->string_length = len;
} }
else if (sym->ts.type == BT_CHARACTER) else if (sym->ts.type == BT_CHARACTER)
{ {
/* Dereference for character pointer results. */
if (sym->attr.pointer || sym->attr.allocatable)
se->expr = gfc_build_indirect_ref (var);
else
se->expr = var; se->expr = var;
se->string_length = len; se->string_length = len;
} }
else else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment