/* Expression translation
- Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software
+ Foundation, Inc.
Contributed by Paul Brook <paul@nowt.org>
and Steven Bosscher <s.bosscher@student.tudelft.nl>
gfc_conv_string_parameter (se);
else
{
+ /* Avoid multiple evaluation of substring start. */
+ if (!CONSTANT_CLASS_P (start.expr) && !DECL_P (start.expr))
+ start.expr = gfc_evaluate_now (start.expr, &se->pre);
+
/* Change the start of the string. */
if (TYPE_STRING_FLAG (TREE_TYPE (se->expr)))
tmp = se->expr;
gfc_conv_expr_type (&end, ref->u.ss.end, gfc_charlen_type_node);
gfc_add_block_to_block (&se->pre, &end.pre);
}
+ if (!CONSTANT_CLASS_P (end.expr) && !DECL_P (end.expr))
+ end.expr = gfc_evaluate_now (end.expr, &se->pre);
+
if (flag_bounds_check)
{
tree nonempty = fold_build2 (LE_EXPR, boolean_type_node,
{
/* Allocate a temporary to hold the result. */
var = gfc_create_var (type, "pstr");
- tmp = build_call_expr (gfor_fndecl_internal_malloc, 1, len);
- tmp = convert (type, tmp);
+ tmp = gfc_call_malloc (&se->pre, type, len);
gfc_add_modify_expr (&se->pre, var, tmp);
/* Free the temporary afterwards. */
- tmp = convert (pvoid_type_node, var);
- tmp = build_call_expr (gfor_fndecl_internal_free, 1, tmp);
+ tmp = gfc_call_free (convert (pvoid_type_node, var));
gfc_add_expr_to_block (&se->post, tmp);
}
static tree
gfc_get_interface_mapping_array (stmtblock_t * block, gfc_symbol * sym,
- int packed, tree data)
+ gfc_packed packed, tree data)
{
tree type;
tree var;
/* Create the replacement variable. */
tmp = gfc_conv_descriptor_data_get (desc);
- value = gfc_get_interface_mapping_array (&se->pre, sym, 0, tmp);
+ value = gfc_get_interface_mapping_array (&se->pre, sym,
+ PACKED_NO, tmp);
/* Use DESC to work out the upper bounds, strides and offset. */
gfc_set_interface_mapping_bounds (&se->pre, TREE_TYPE (value), desc);
}
else
/* Otherwise we have a packed array. */
- value = gfc_get_interface_mapping_array (&se->pre, sym, 2, se->expr);
+ value = gfc_get_interface_mapping_array (&se->pre, sym,
+ PACKED_FULL, se->expr);
new_sym->backend_decl = value;
}
if (byref)
{
if (se->direct_byref)
- retargs = gfc_chainon_list (retargs, se->expr);
+ {
+ /* Sometimes, too much indirection can be applied; eg. for
+ function_result = array_valued_recursive_function. */
+ if (TREE_TYPE (TREE_TYPE (se->expr))
+ && TREE_TYPE (TREE_TYPE (TREE_TYPE (se->expr)))
+ && GFC_DESCRIPTOR_TYPE_P
+ (TREE_TYPE (TREE_TYPE (TREE_TYPE (se->expr)))))
+ se->expr = build_fold_indirect_ref (se->expr);
+
+ retargs = gfc_chainon_list (retargs, se->expr);
+ }
else if (sym->result->attr.dimension)
{
gcc_assert (se->loop && info);
if (expr1->expr_type == EXPR_VARIABLE
&& expr1->rank > 0
&& expr1->ref
+ && expr1->ref->next == NULL
&& gfc_full_array_ref_p (expr1->ref)
&& is_zero_initializer_p (expr2))
{