| Index: gcc/gcc/fortran/trans-array.c
|
| diff --git a/gcc/gcc/fortran/trans-array.c b/gcc/gcc/fortran/trans-array.c
|
| index 3b5e6d9ed9001745fe97140494d6f54e89a4eef8..d5b5c4745b72f2e5d599671558d27170b3ac512b 100644
|
| --- a/gcc/gcc/fortran/trans-array.c
|
| +++ b/gcc/gcc/fortran/trans-array.c
|
| @@ -1,5 +1,5 @@
|
| /* Array translation routines
|
| - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
| + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
| Free Software Foundation, Inc.
|
| Contributed by Paul Brook <paul@nowt.org>
|
| and Steven Bosscher <s.bosscher@student.tudelft.nl>
|
| @@ -194,10 +194,10 @@ gfc_conv_descriptor_data_addr (tree desc)
|
| gcc_assert (DATA_FIELD == 0);
|
|
|
| t = fold_build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
|
| - return build_fold_addr_expr (t);
|
| + return gfc_build_addr_expr (NULL_TREE, t);
|
| }
|
|
|
| -tree
|
| +static tree
|
| gfc_conv_descriptor_offset (tree desc)
|
| {
|
| tree type;
|
| @@ -214,6 +214,21 @@ gfc_conv_descriptor_offset (tree desc)
|
| }
|
|
|
| tree
|
| +gfc_conv_descriptor_offset_get (tree desc)
|
| +{
|
| + return gfc_conv_descriptor_offset (desc);
|
| +}
|
| +
|
| +void
|
| +gfc_conv_descriptor_offset_set (stmtblock_t *block, tree desc,
|
| + tree value)
|
| +{
|
| + tree t = gfc_conv_descriptor_offset (desc);
|
| + gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
|
| +}
|
| +
|
| +
|
| +tree
|
| gfc_conv_descriptor_dtype (tree desc)
|
| {
|
| tree field;
|
| @@ -250,7 +265,7 @@ gfc_conv_descriptor_dimension (tree desc, tree dim)
|
| return tmp;
|
| }
|
|
|
| -tree
|
| +static tree
|
| gfc_conv_descriptor_stride (tree desc, tree dim)
|
| {
|
| tree tmp;
|
| @@ -267,6 +282,26 @@ gfc_conv_descriptor_stride (tree desc, tree dim)
|
| }
|
|
|
| tree
|
| +gfc_conv_descriptor_stride_get (tree desc, tree dim)
|
| +{
|
| + tree type = TREE_TYPE (desc);
|
| + gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
|
| + if (integer_zerop (dim)
|
| + && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
|
| + return gfc_index_one_node;
|
| +
|
| + return gfc_conv_descriptor_stride (desc, dim);
|
| +}
|
| +
|
| +void
|
| +gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc,
|
| + tree dim, tree value)
|
| +{
|
| + tree t = gfc_conv_descriptor_stride (desc, dim);
|
| + gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
|
| +}
|
| +
|
| +static tree
|
| gfc_conv_descriptor_lbound (tree desc, tree dim)
|
| {
|
| tree tmp;
|
| @@ -283,6 +318,20 @@ gfc_conv_descriptor_lbound (tree desc, tree dim)
|
| }
|
|
|
| tree
|
| +gfc_conv_descriptor_lbound_get (tree desc, tree dim)
|
| +{
|
| + return gfc_conv_descriptor_lbound (desc, dim);
|
| +}
|
| +
|
| +void
|
| +gfc_conv_descriptor_lbound_set (stmtblock_t *block, tree desc,
|
| + tree dim, tree value)
|
| +{
|
| + tree t = gfc_conv_descriptor_lbound (desc, dim);
|
| + gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
|
| +}
|
| +
|
| +static tree
|
| gfc_conv_descriptor_ubound (tree desc, tree dim)
|
| {
|
| tree tmp;
|
| @@ -298,6 +347,19 @@ gfc_conv_descriptor_ubound (tree desc, tree dim)
|
| return tmp;
|
| }
|
|
|
| +tree
|
| +gfc_conv_descriptor_ubound_get (tree desc, tree dim)
|
| +{
|
| + return gfc_conv_descriptor_ubound (desc, dim);
|
| +}
|
| +
|
| +void
|
| +gfc_conv_descriptor_ubound_set (stmtblock_t *block, tree desc,
|
| + tree dim, tree value)
|
| +{
|
| + tree t = gfc_conv_descriptor_ubound (desc, dim);
|
| + gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
|
| +}
|
|
|
| /* Build a null array descriptor constructor. */
|
|
|
| @@ -533,7 +595,7 @@ gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
|
| tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
|
| tmp);
|
| tmp = gfc_create_var (tmp, "A");
|
| - tmp = build_fold_addr_expr (tmp);
|
| + tmp = gfc_build_addr_expr (NULL_TREE, tmp);
|
| gfc_conv_descriptor_data_set (pre, desc, tmp);
|
| }
|
| else
|
| @@ -558,11 +620,13 @@ gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
|
| gcc_assert (tmp == gfc_get_element_type (TREE_TYPE (desc)));
|
| packed = gfc_create_var (build_pointer_type (tmp), "data");
|
|
|
| - tmp = build_call_expr (gfor_fndecl_in_pack, 1, initial);
|
| + tmp = build_call_expr_loc (input_location,
|
| + gfor_fndecl_in_pack, 1, initial);
|
| tmp = fold_convert (TREE_TYPE (packed), tmp);
|
| gfc_add_modify (pre, packed, tmp);
|
|
|
| - tmp = build_fold_indirect_ref (initial);
|
| + tmp = build_fold_indirect_ref_loc (input_location,
|
| + initial);
|
| source_data = gfc_conv_descriptor_data_get (tmp);
|
|
|
| /* internal_pack may return source->data without any allocation
|
| @@ -579,7 +643,8 @@ gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
|
| was_packed = fold_build2 (EQ_EXPR, boolean_type_node,
|
| packed, source_data);
|
| tmp = gfc_finish_block (&do_copying);
|
| - tmp = build3_v (COND_EXPR, was_packed, tmp, build_empty_stmt ());
|
| + tmp = build3_v (COND_EXPR, was_packed, tmp,
|
| + build_empty_stmt (input_location));
|
| gfc_add_expr_to_block (pre, tmp);
|
|
|
| tmp = fold_convert (pvoid_type_node, packed);
|
| @@ -592,8 +657,7 @@ gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
|
|
|
| /* The offset is zero because we create temporaries with a zero
|
| lower bound. */
|
| - tmp = gfc_conv_descriptor_offset (desc);
|
| - gfc_add_modify (pre, tmp, gfc_index_zero_node);
|
| + gfc_conv_descriptor_offset_set (pre, desc, gfc_index_zero_node);
|
|
|
| if (dealloc && !onstack)
|
| {
|
| @@ -661,7 +725,7 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post,
|
| /* Initialize the descriptor. */
|
| type =
|
| gfc_get_array_type_bounds (eltype, info->dimen, loop->from, loop->to, 1,
|
| - GFC_ARRAY_UNKNOWN);
|
| + GFC_ARRAY_UNKNOWN, true);
|
| desc = gfc_create_var (type, "atmp");
|
| GFC_DECL_PACKED_ARRAY (desc) = 1;
|
|
|
| @@ -704,21 +768,19 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post,
|
| of the descriptor fields. */
|
| tmp =
|
| fold_build2 (MINUS_EXPR, gfc_array_index_type,
|
| - gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]),
|
| - gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]));
|
| + gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[n]),
|
| + gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]));
|
| loop->to[n] = tmp;
|
| continue;
|
| }
|
|
|
| /* Store the stride and bound components in the descriptor. */
|
| - tmp = gfc_conv_descriptor_stride (desc, gfc_rank_cst[n]);
|
| - gfc_add_modify (pre, tmp, size);
|
| + gfc_conv_descriptor_stride_set (pre, desc, gfc_rank_cst[n], size);
|
|
|
| - tmp = gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]);
|
| - gfc_add_modify (pre, tmp, gfc_index_zero_node);
|
| + gfc_conv_descriptor_lbound_set (pre, desc, gfc_rank_cst[n],
|
| + gfc_index_zero_node);
|
|
|
| - tmp = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]);
|
| - gfc_add_modify (pre, tmp, loop->to[n]);
|
| + gfc_conv_descriptor_ubound_set (pre, desc, gfc_rank_cst[n], loop->to[n]);
|
|
|
| tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
|
| loop->to[n], gfc_index_one_node);
|
| @@ -775,7 +837,7 @@ gfc_conv_array_transpose (gfc_se * se, gfc_expr * expr)
|
| {
|
| tree dest, src, dest_index, src_index;
|
| gfc_loopinfo *loop;
|
| - gfc_ss_info *dest_info, *src_info;
|
| + gfc_ss_info *dest_info;
|
| gfc_ss *dest_ss, *src_ss;
|
| gfc_se src_se;
|
| int n;
|
| @@ -785,7 +847,6 @@ gfc_conv_array_transpose (gfc_se * se, gfc_expr * expr)
|
| src_ss = gfc_walk_expr (expr);
|
| dest_ss = se->ss;
|
|
|
| - src_info = &src_ss->data.info;
|
| dest_info = &dest_ss->data.info;
|
| gcc_assert (dest_info->dimen == 2);
|
|
|
| @@ -819,25 +880,22 @@ gfc_conv_array_transpose (gfc_se * se, gfc_expr * expr)
|
| dest_index = gfc_rank_cst[n];
|
| src_index = gfc_rank_cst[1 - n];
|
|
|
| - gfc_add_modify (&se->pre,
|
| - gfc_conv_descriptor_stride (dest, dest_index),
|
| - gfc_conv_descriptor_stride (src, src_index));
|
| + gfc_conv_descriptor_stride_set (&se->pre, dest, dest_index,
|
| + gfc_conv_descriptor_stride_get (src, src_index));
|
|
|
| - gfc_add_modify (&se->pre,
|
| - gfc_conv_descriptor_lbound (dest, dest_index),
|
| - gfc_conv_descriptor_lbound (src, src_index));
|
| + gfc_conv_descriptor_lbound_set (&se->pre, dest, dest_index,
|
| + gfc_conv_descriptor_lbound_get (src, src_index));
|
|
|
| - gfc_add_modify (&se->pre,
|
| - gfc_conv_descriptor_ubound (dest, dest_index),
|
| - gfc_conv_descriptor_ubound (src, src_index));
|
| + gfc_conv_descriptor_ubound_set (&se->pre, dest, dest_index,
|
| + gfc_conv_descriptor_ubound_get (src, src_index));
|
|
|
| if (!loop->to[n])
|
| {
|
| gcc_assert (integer_zerop (loop->from[n]));
|
| loop->to[n] =
|
| fold_build2 (MINUS_EXPR, gfc_array_index_type,
|
| - gfc_conv_descriptor_ubound (dest, dest_index),
|
| - gfc_conv_descriptor_lbound (dest, dest_index));
|
| + gfc_conv_descriptor_ubound_get (dest, dest_index),
|
| + gfc_conv_descriptor_lbound_get (dest, dest_index));
|
| }
|
| }
|
|
|
| @@ -849,13 +907,12 @@ gfc_conv_array_transpose (gfc_se * se, gfc_expr * expr)
|
| element is still at the same offset as before, except where the loop
|
| starts at zero. */
|
| if (!integer_zerop (loop->from[0]))
|
| - dest_info->offset = gfc_conv_descriptor_offset (src);
|
| + dest_info->offset = gfc_conv_descriptor_offset_get (src);
|
| else
|
| dest_info->offset = gfc_index_zero_node;
|
|
|
| - gfc_add_modify (&se->pre,
|
| - gfc_conv_descriptor_offset (dest),
|
| - dest_info->offset);
|
| + gfc_conv_descriptor_offset_set (&se->pre, dest,
|
| + dest_info->offset);
|
|
|
| if (dest_info->dimen > loop->temp_dim)
|
| loop->temp_dim = dest_info->dimen;
|
| @@ -893,11 +950,11 @@ gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
|
| if (integer_zerop (extra))
|
| return;
|
|
|
| - ubound = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[0]);
|
| + ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
|
|
|
| /* Add EXTRA to the upper bound. */
|
| tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, ubound, extra);
|
| - gfc_add_modify (pblock, ubound, tmp);
|
| + gfc_conv_descriptor_ubound_set (pblock, desc, gfc_rank_cst[0], tmp);
|
|
|
| /* Get the value of the current data pointer. */
|
| arg0 = gfc_conv_descriptor_data_get (desc);
|
| @@ -1027,7 +1084,8 @@ gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
|
| gfc_conv_expr (se, expr);
|
|
|
| /* Store the value. */
|
| - tmp = build_fold_indirect_ref (gfc_conv_descriptor_data_get (desc));
|
| + tmp = build_fold_indirect_ref_loc (input_location,
|
| + gfc_conv_descriptor_data_get (desc));
|
| tmp = gfc_build_array_ref (tmp, offset, NULL);
|
|
|
| if (expr->ts.type == BT_CHARACTER)
|
| @@ -1057,7 +1115,7 @@ gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
|
| gfc_trans_string_copy (&se->pre, esize, tmp, expr->ts.kind,
|
| se->string_length, se->expr, expr->ts.kind);
|
| }
|
| - if (flag_bounds_check && !typespec_chararray_ctor)
|
| + if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !typespec_chararray_ctor)
|
| {
|
| if (first_len)
|
| {
|
| @@ -1182,6 +1240,9 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
|
| gfc_se se;
|
| mpz_t size;
|
|
|
| + tree shadow_loopvar = NULL_TREE;
|
| + gfc_saved_var saved_loopvar;
|
| +
|
| mpz_init (size);
|
| for (; c; c = c->next)
|
| {
|
| @@ -1189,6 +1250,20 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
|
| if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
|
| gfc_put_offset_into_var (pblock, poffset, offsetvar);
|
|
|
| + /* Shadowing the iterator avoids changing its value and saves us from
|
| + keeping track of it. Further, it makes sure that there's always a
|
| + backend-decl for the symbol, even if there wasn't one before,
|
| + e.g. in the case of an iterator that appears in a specification
|
| + expression in an interface mapping. */
|
| + if (c->iterator)
|
| + {
|
| + gfc_symbol *sym = c->iterator->var->symtree->n.sym;
|
| + tree type = gfc_typenode_for_spec (&sym->ts);
|
| +
|
| + shadow_loopvar = gfc_create_var (type, "shadow_loopvar");
|
| + gfc_shadow_sym (sym, shadow_loopvar, &saved_loopvar);
|
| + }
|
| +
|
| gfc_start_block (&body);
|
|
|
| if (c->expr->expr_type == EXPR_ARRAY)
|
| @@ -1279,14 +1354,16 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
|
|
|
| /* Use BUILTIN_MEMCPY to assign the values. */
|
| tmp = gfc_conv_descriptor_data_get (desc);
|
| - tmp = build_fold_indirect_ref (tmp);
|
| + tmp = build_fold_indirect_ref_loc (input_location,
|
| + tmp);
|
| tmp = gfc_build_array_ref (tmp, *poffset, NULL);
|
| - tmp = build_fold_addr_expr (tmp);
|
| - init = build_fold_addr_expr (init);
|
| + tmp = gfc_build_addr_expr (NULL_TREE, tmp);
|
| + init = gfc_build_addr_expr (NULL_TREE, init);
|
|
|
| size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
|
| bound = build_int_cst (NULL_TREE, n * size);
|
| - tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3,
|
| + tmp = build_call_expr_loc (input_location,
|
| + built_in_decls[BUILT_IN_MEMCPY], 3,
|
| tmp, init, bound);
|
| gfc_add_expr_to_block (&body, tmp);
|
|
|
| @@ -1312,53 +1389,35 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
|
| else
|
| {
|
| /* Build the implied do-loop. */
|
| + stmtblock_t implied_do_block;
|
| tree cond;
|
| tree end;
|
| tree step;
|
| - tree loopvar;
|
| tree exit_label;
|
| tree loopbody;
|
| tree tmp2;
|
| - tree tmp_loopvar;
|
|
|
| loopbody = gfc_finish_block (&body);
|
|
|
| - if (c->iterator->var->symtree->n.sym->backend_decl)
|
| - {
|
| - gfc_init_se (&se, NULL);
|
| - gfc_conv_expr (&se, c->iterator->var);
|
| - gfc_add_block_to_block (pblock, &se.pre);
|
| - loopvar = se.expr;
|
| - }
|
| - else
|
| - {
|
| - /* If the iterator appears in a specification expression in
|
| - an interface mapping, we need to make a temp for the loop
|
| - variable because it is not declared locally. */
|
| - loopvar = gfc_typenode_for_spec (&c->iterator->var->ts);
|
| - loopvar = gfc_create_var (loopvar, "loopvar");
|
| - }
|
| -
|
| - /* Make a temporary, store the current value in that
|
| - and return it, once the loop is done. */
|
| - tmp_loopvar = gfc_create_var (TREE_TYPE (loopvar), "loopvar");
|
| - gfc_add_modify (pblock, tmp_loopvar, loopvar);
|
| + /* Create a new block that holds the implied-do loop. A temporary
|
| + loop-variable is used. */
|
| + gfc_start_block(&implied_do_block);
|
|
|
| /* Initialize the loop. */
|
| gfc_init_se (&se, NULL);
|
| gfc_conv_expr_val (&se, c->iterator->start);
|
| - gfc_add_block_to_block (pblock, &se.pre);
|
| - gfc_add_modify (pblock, loopvar, se.expr);
|
| + gfc_add_block_to_block (&implied_do_block, &se.pre);
|
| + gfc_add_modify (&implied_do_block, shadow_loopvar, se.expr);
|
|
|
| gfc_init_se (&se, NULL);
|
| gfc_conv_expr_val (&se, c->iterator->end);
|
| - gfc_add_block_to_block (pblock, &se.pre);
|
| - end = gfc_evaluate_now (se.expr, pblock);
|
| + gfc_add_block_to_block (&implied_do_block, &se.pre);
|
| + end = gfc_evaluate_now (se.expr, &implied_do_block);
|
|
|
| gfc_init_se (&se, NULL);
|
| gfc_conv_expr_val (&se, c->iterator->step);
|
| - gfc_add_block_to_block (pblock, &se.pre);
|
| - step = gfc_evaluate_now (se.expr, pblock);
|
| + gfc_add_block_to_block (&implied_do_block, &se.pre);
|
| + step = gfc_evaluate_now (se.expr, &implied_do_block);
|
|
|
| /* If this array expands dynamically, and the number of iterations
|
| is not constant, we won't have allocated space for the static
|
| @@ -1366,7 +1425,7 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
|
| if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
|
| {
|
| /* Get the number of iterations. */
|
| - tmp = gfc_get_iteration_count (loopvar, end, step);
|
| + tmp = gfc_get_iteration_count (shadow_loopvar, end, step);
|
|
|
| /* Get the static part of C->EXPR's size. */
|
| gfc_get_array_constructor_element_size (&size, c->expr);
|
| @@ -1374,7 +1433,7 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
|
|
|
| /* Grow the array by TMP * TMP2 elements. */
|
| tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, tmp, tmp2);
|
| - gfc_grow_array (pblock, desc, tmp);
|
| + gfc_grow_array (&implied_do_block, desc, tmp);
|
| }
|
|
|
| /* Generate the loop body. */
|
| @@ -1388,32 +1447,36 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
|
| build_int_cst (TREE_TYPE (step), 0));
|
| cond = fold_build3 (COND_EXPR, boolean_type_node, tmp,
|
| fold_build2 (GT_EXPR, boolean_type_node,
|
| - loopvar, end),
|
| + shadow_loopvar, end),
|
| fold_build2 (LT_EXPR, boolean_type_node,
|
| - loopvar, end));
|
| + shadow_loopvar, end));
|
| tmp = build1_v (GOTO_EXPR, exit_label);
|
| TREE_USED (exit_label) = 1;
|
| - tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
|
| + tmp = build3_v (COND_EXPR, cond, tmp,
|
| + build_empty_stmt (input_location));
|
| gfc_add_expr_to_block (&body, tmp);
|
|
|
| /* The main loop body. */
|
| gfc_add_expr_to_block (&body, loopbody);
|
|
|
| /* Increase loop variable by step. */
|
| - tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (loopvar), loopvar, step);
|
| - gfc_add_modify (&body, loopvar, tmp);
|
| + tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (shadow_loopvar), shadow_loopvar, step);
|
| + gfc_add_modify (&body, shadow_loopvar, tmp);
|
|
|
| /* Finish the loop. */
|
| tmp = gfc_finish_block (&body);
|
| tmp = build1_v (LOOP_EXPR, tmp);
|
| - gfc_add_expr_to_block (pblock, tmp);
|
| + gfc_add_expr_to_block (&implied_do_block, tmp);
|
|
|
| /* Add the exit label. */
|
| tmp = build1_v (LABEL_EXPR, exit_label);
|
| - gfc_add_expr_to_block (pblock, tmp);
|
| + gfc_add_expr_to_block (&implied_do_block, tmp);
|
|
|
| - /* Restore the original value of the loop counter. */
|
| - gfc_add_modify (pblock, loopvar, tmp_loopvar);
|
| + /* Finishe the implied-do loop. */
|
| + tmp = gfc_finish_block(&implied_do_block);
|
| + gfc_add_expr_to_block(pblock, tmp);
|
| +
|
| + gfc_restore_sym (c->iterator->var->symtree->n.sym, &saved_loopvar);
|
| }
|
| }
|
| mpz_clear (size);
|
| @@ -1468,7 +1531,7 @@ get_array_ctor_var_strlen (gfc_expr * expr, tree * len)
|
| }
|
| }
|
|
|
| - *len = ts->cl->backend_decl;
|
| + *len = ts->u.cl->backend_decl;
|
| }
|
|
|
|
|
| @@ -1484,12 +1547,12 @@ get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
|
| if (*len && INTEGER_CST_P (*len))
|
| return;
|
|
|
| - if (!e->ref && e->ts.cl && e->ts.cl->length
|
| - && e->ts.cl->length->expr_type == EXPR_CONSTANT)
|
| + if (!e->ref && e->ts.u.cl && e->ts.u.cl->length
|
| + && e->ts.u.cl->length->expr_type == EXPR_CONSTANT)
|
| {
|
| /* This is easy. */
|
| - gfc_conv_const_charlen (e->ts.cl);
|
| - *len = e->ts.cl->backend_decl;
|
| + gfc_conv_const_charlen (e->ts.u.cl);
|
| + *len = e->ts.u.cl->backend_decl;
|
| }
|
| else
|
| {
|
| @@ -1510,7 +1573,7 @@ get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
|
| gfc_add_block_to_block (block, &se.pre);
|
| gfc_add_block_to_block (block, &se.post);
|
|
|
| - e->ts.cl->backend_decl = *len;
|
| + e->ts.u.cl->backend_decl = *len;
|
| }
|
| }
|
|
|
| @@ -1650,7 +1713,7 @@ gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
|
| as.upper[i] = gfc_int_expr (tmp - 1);
|
| }
|
|
|
| - tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC);
|
| + tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC, true);
|
|
|
| init = build_constructor_from_list (tmptype, nreverse (list));
|
|
|
| @@ -1685,7 +1748,7 @@ gfc_trans_constant_array_constructor (gfc_loopinfo * loop,
|
| info = &ss->data.info;
|
|
|
| info->descriptor = tmp;
|
| - info->data = build_fold_addr_expr (tmp);
|
| + info->data = gfc_build_addr_expr (NULL_TREE, tmp);
|
| info->offset = gfc_index_zero_node;
|
|
|
| for (i = 0; i < info->dimen; i++)
|
| @@ -1760,11 +1823,11 @@ gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss, locus * where)
|
|
|
| /* Do bounds-checking here and in gfc_trans_array_ctor_element only if no
|
| typespec was given for the array constructor. */
|
| - typespec_chararray_ctor = (ss->expr->ts.cl
|
| - && ss->expr->ts.cl->length_from_typespec);
|
| + typespec_chararray_ctor = (ss->expr->ts.u.cl
|
| + && ss->expr->ts.u.cl->length_from_typespec);
|
|
|
| - if (flag_bounds_check && ss->expr->ts.type == BT_CHARACTER
|
| - && !typespec_chararray_ctor)
|
| + if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
|
| + && ss->expr->ts.type == BT_CHARACTER && !typespec_chararray_ctor)
|
| {
|
| first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
|
| first_len = true;
|
| @@ -1780,14 +1843,14 @@ gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss, locus * where)
|
| /* get_array_ctor_strlen walks the elements of the constructor, if a
|
| typespec was given, we already know the string length and want the one
|
| specified there. */
|
| - if (typespec_chararray_ctor && ss->expr->ts.cl->length
|
| - && ss->expr->ts.cl->length->expr_type != EXPR_CONSTANT)
|
| + if (typespec_chararray_ctor && ss->expr->ts.u.cl->length
|
| + && ss->expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
|
| {
|
| gfc_se length_se;
|
|
|
| const_string = false;
|
| gfc_init_se (&length_se, NULL);
|
| - gfc_conv_expr_type (&length_se, ss->expr->ts.cl->length,
|
| + gfc_conv_expr_type (&length_se, ss->expr->ts.u.cl->length,
|
| gfc_charlen_type_node);
|
| ss->string_length = length_se.expr;
|
| gfc_add_block_to_block (&loop->pre, &length_se.pre);
|
| @@ -1801,7 +1864,7 @@ gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss, locus * where)
|
| and not end up here. */
|
| gcc_assert (ss->string_length);
|
|
|
| - ss->expr->ts.cl->backend_decl = ss->string_length;
|
| + ss->expr->ts.u.cl->backend_decl = ss->string_length;
|
|
|
| type = gfc_get_character_type_len (ss->expr->ts.kind, ss->string_length);
|
| if (const_string)
|
| @@ -1874,7 +1937,7 @@ gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss, locus * where)
|
| /* If the array grows dynamically, the upper bound of the loop variable
|
| is determined by the array's final upper bound. */
|
| if (dynamic)
|
| - loop->to[0] = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[0]);
|
| + loop->to[0] = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
|
|
|
| if (TREE_USED (offsetvar))
|
| pushdecl (offsetvar);
|
| @@ -1882,7 +1945,7 @@ gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss, locus * where)
|
| gcc_assert (INTEGER_CST_P (offset));
|
| #if 0
|
| /* Disable bound checking for now because it's probably broken. */
|
| - if (flag_bounds_check)
|
| + if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
|
| {
|
| gcc_unreachable ();
|
| }
|
| @@ -1928,8 +1991,8 @@ gfc_set_vector_loop_bounds (gfc_loopinfo * loop, gfc_ss_info * info)
|
| desc = info->subscript[dim]->data.info.descriptor;
|
| zero = gfc_rank_cst[0];
|
| tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
|
| - gfc_conv_descriptor_ubound (desc, zero),
|
| - gfc_conv_descriptor_lbound (desc, zero));
|
| + gfc_conv_descriptor_ubound_get (desc, zero),
|
| + gfc_conv_descriptor_lbound_get (desc, zero));
|
| tmp = gfc_evaluate_now (tmp, &loop->pre);
|
| loop->to[n] = tmp;
|
| }
|
| @@ -1983,9 +2046,10 @@ gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
|
| break;
|
|
|
| case GFC_SS_REFERENCE:
|
| - /* Scalar reference. Evaluate this now. */
|
| + /* Scalar argument to elemental procedure. Evaluate this
|
| + now. */
|
| gfc_init_se (&se, NULL);
|
| - gfc_conv_expr_reference (&se, ss->expr);
|
| + gfc_conv_expr (&se, ss->expr);
|
| gfc_add_block_to_block (&loop->pre, &se.pre);
|
| gfc_add_block_to_block (&loop->post, &se.post);
|
|
|
| @@ -2031,11 +2095,11 @@ gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
|
| case GFC_SS_CONSTRUCTOR:
|
| if (ss->expr->ts.type == BT_CHARACTER
|
| && ss->string_length == NULL
|
| - && ss->expr->ts.cl
|
| - && ss->expr->ts.cl->length)
|
| + && ss->expr->ts.u.cl
|
| + && ss->expr->ts.u.cl->length)
|
| {
|
| gfc_init_se (&se, NULL);
|
| - gfc_conv_expr_type (&se, ss->expr->ts.cl->length,
|
| + gfc_conv_expr_type (&se, ss->expr->ts.u.cl->length,
|
| gfc_charlen_type_node);
|
| ss->string_length = se.expr;
|
| gfc_add_block_to_block (&loop->pre, &se.pre);
|
| @@ -2138,7 +2202,7 @@ gfc_conv_array_data (tree descriptor)
|
| else
|
| {
|
| /* Descriptorless arrays. */
|
| - return build_fold_addr_expr (descriptor);
|
| + return gfc_build_addr_expr (NULL_TREE, descriptor);
|
| }
|
| }
|
| else
|
| @@ -2157,7 +2221,7 @@ gfc_conv_array_offset (tree descriptor)
|
| if (GFC_ARRAY_TYPE_P (type))
|
| return GFC_TYPE_ARRAY_OFFSET (type);
|
| else
|
| - return gfc_conv_descriptor_offset (descriptor);
|
| + return gfc_conv_descriptor_offset_get (descriptor);
|
| }
|
|
|
|
|
| @@ -2176,7 +2240,7 @@ gfc_conv_array_stride (tree descriptor, int dim)
|
| if (tmp != NULL_TREE)
|
| return tmp;
|
|
|
| - tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[dim]);
|
| + tmp = gfc_conv_descriptor_stride_get (descriptor, gfc_rank_cst[dim]);
|
| return tmp;
|
| }
|
|
|
| @@ -2195,7 +2259,7 @@ gfc_conv_array_lbound (tree descriptor, int dim)
|
| if (tmp != NULL_TREE)
|
| return tmp;
|
|
|
| - tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[dim]);
|
| + tmp = gfc_conv_descriptor_lbound_get (descriptor, gfc_rank_cst[dim]);
|
| return tmp;
|
| }
|
|
|
| @@ -2219,7 +2283,7 @@ gfc_conv_array_ubound (tree descriptor, int dim)
|
| if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
|
| return gfc_index_zero_node;
|
|
|
| - tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[dim]);
|
| + tmp = gfc_conv_descriptor_ubound_get (descriptor, gfc_rank_cst[dim]);
|
| return tmp;
|
| }
|
|
|
| @@ -2231,11 +2295,11 @@ gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n,
|
| locus * where, bool check_upper)
|
| {
|
| tree fault;
|
| - tree tmp;
|
| + tree tmp_lo, tmp_up;
|
| char *msg;
|
| const char * name = NULL;
|
|
|
| - if (!flag_bounds_check)
|
| + if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
|
| return index;
|
|
|
| index = gfc_evaluate_now (index, &se->pre);
|
| @@ -2253,10 +2317,6 @@ gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n,
|
| && se->loop->ss->loop_chain->expr->symtree)
|
| name = se->loop->ss->loop_chain->expr->symtree->name;
|
|
|
| - if (!name && se->loop && se->loop->ss && se->loop->ss->loop_chain
|
| - && se->loop->ss->loop_chain->expr->symtree)
|
| - name = se->loop->ss->loop_chain->expr->symtree->name;
|
| -
|
| if (!name && se->loop && se->loop->ss && se->loop->ss->expr)
|
| {
|
| if (se->loop->ss->expr->expr_type == EXPR_FUNCTION
|
| @@ -2268,34 +2328,49 @@ gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n,
|
| name = "unnamed constant";
|
| }
|
|
|
| - /* Check lower bound. */
|
| - tmp = gfc_conv_array_lbound (descriptor, n);
|
| - fault = fold_build2 (LT_EXPR, boolean_type_node, index, tmp);
|
| - if (name)
|
| - asprintf (&msg, "%s for array '%s', lower bound of dimension %d exceeded"
|
| - "(%%ld < %%ld)", gfc_msg_fault, name, n+1);
|
| - else
|
| - asprintf (&msg, "%s, lower bound of dimension %d exceeded (%%ld < %%ld)",
|
| - gfc_msg_fault, n+1);
|
| - gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
|
| - fold_convert (long_integer_type_node, index),
|
| - fold_convert (long_integer_type_node, tmp));
|
| - gfc_free (msg);
|
| -
|
| - /* Check upper bound. */
|
| + if (TREE_CODE (descriptor) == VAR_DECL)
|
| + name = IDENTIFIER_POINTER (DECL_NAME (descriptor));
|
| +
|
| + /* If upper bound is present, include both bounds in the error message. */
|
| if (check_upper)
|
| {
|
| - tmp = gfc_conv_array_ubound (descriptor, n);
|
| - fault = fold_build2 (GT_EXPR, boolean_type_node, index, tmp);
|
| + tmp_lo = gfc_conv_array_lbound (descriptor, n);
|
| + tmp_up = gfc_conv_array_ubound (descriptor, n);
|
| +
|
| + if (name)
|
| + asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
|
| + "outside of expected range (%%ld:%%ld)", n+1, name);
|
| + else
|
| + asprintf (&msg, "Index '%%ld' of dimension %d "
|
| + "outside of expected range (%%ld:%%ld)", n+1);
|
| +
|
| + fault = fold_build2 (LT_EXPR, boolean_type_node, index, tmp_lo);
|
| + gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
|
| + fold_convert (long_integer_type_node, index),
|
| + fold_convert (long_integer_type_node, tmp_lo),
|
| + fold_convert (long_integer_type_node, tmp_up));
|
| + fault = fold_build2 (GT_EXPR, boolean_type_node, index, tmp_up);
|
| + gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
|
| + fold_convert (long_integer_type_node, index),
|
| + fold_convert (long_integer_type_node, tmp_lo),
|
| + fold_convert (long_integer_type_node, tmp_up));
|
| + gfc_free (msg);
|
| + }
|
| + else
|
| + {
|
| + tmp_lo = gfc_conv_array_lbound (descriptor, n);
|
| +
|
| if (name)
|
| - asprintf (&msg, "%s for array '%s', upper bound of dimension %d "
|
| - " exceeded (%%ld > %%ld)", gfc_msg_fault, name, n+1);
|
| + asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
|
| + "below lower bound of %%ld", n+1, name);
|
| else
|
| - asprintf (&msg, "%s, upper bound of dimension %d exceeded (%%ld > %%ld)",
|
| - gfc_msg_fault, n+1);
|
| + asprintf (&msg, "Index '%%ld' of dimension %d "
|
| + "below lower bound of %%ld", n+1);
|
| +
|
| + fault = fold_build2 (LT_EXPR, boolean_type_node, index, tmp_lo);
|
| gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
|
| fold_convert (long_integer_type_node, index),
|
| - fold_convert (long_integer_type_node, tmp));
|
| + fold_convert (long_integer_type_node, tmp_lo));
|
| gfc_free (msg);
|
| }
|
|
|
| @@ -2329,8 +2404,8 @@ gfc_conv_array_index_offset (gfc_se * se, gfc_ss_info * info, int dim, int i,
|
|
|
| index = gfc_trans_array_bound_check (se, info->descriptor,
|
| index, dim, &ar->where,
|
| - (ar->as->type != AS_ASSUMED_SIZE
|
| - && !ar->as->cp_was_assumed) || dim < ar->dimen - 1);
|
| + ar->as->type != AS_ASSUMED_SIZE
|
| + || dim < ar->dimen - 1);
|
| break;
|
|
|
| case DIMEN_VECTOR:
|
| @@ -2348,15 +2423,16 @@ gfc_conv_array_index_offset (gfc_se * se, gfc_ss_info * info, int dim, int i,
|
| index, gfc_conv_array_stride (desc, 0));
|
|
|
| /* Read the vector to get an index into info->descriptor. */
|
| - data = build_fold_indirect_ref (gfc_conv_array_data (desc));
|
| + data = build_fold_indirect_ref_loc (input_location,
|
| + gfc_conv_array_data (desc));
|
| index = gfc_build_array_ref (data, index, NULL);
|
| index = gfc_evaluate_now (index, &se->pre);
|
|
|
| /* Do any bounds checking on the final info->descriptor index. */
|
| index = gfc_trans_array_bound_check (se, info->descriptor,
|
| index, dim, &ar->where,
|
| - (ar->as->type != AS_ASSUMED_SIZE
|
| - && !ar->as->cp_was_assumed) || dim < ar->dimen - 1);
|
| + ar->as->type != AS_ASSUMED_SIZE
|
| + || dim < ar->dimen - 1);
|
| break;
|
|
|
| case DIMEN_RANGE:
|
| @@ -2422,7 +2498,8 @@ gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
|
| if (se->ss->expr && is_subref_array (se->ss->expr))
|
| decl = se->ss->expr->symtree->n.sym->backend_decl;
|
|
|
| - tmp = build_fold_indirect_ref (info->data);
|
| + tmp = build_fold_indirect_ref_loc (input_location,
|
| + info->data);
|
| se->expr = gfc_build_array_ref (tmp, index, decl);
|
| }
|
|
|
| @@ -2452,6 +2529,7 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
|
| tree tmp;
|
| tree stride;
|
| gfc_se indexse;
|
| + gfc_se tmpse;
|
|
|
| /* Handle scalarized references separately. */
|
| if (ar->type != AR_ELEMENT)
|
| @@ -2471,7 +2549,7 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
|
| gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
|
| gfc_add_block_to_block (&se->pre, &indexse.pre);
|
|
|
| - if (flag_bounds_check)
|
| + if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
|
| {
|
| /* Check array bounds. */
|
| tree cond;
|
| @@ -2482,11 +2560,19 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
|
|
|
| /* Lower bound. */
|
| tmp = gfc_conv_array_lbound (se->expr, n);
|
| + if (sym->attr.temporary)
|
| + {
|
| + gfc_init_se (&tmpse, se);
|
| + gfc_conv_expr_type (&tmpse, ar->as->lower[n],
|
| + gfc_array_index_type);
|
| + gfc_add_block_to_block (&se->pre, &tmpse.pre);
|
| + tmp = tmpse.expr;
|
| + }
|
| +
|
| cond = fold_build2 (LT_EXPR, boolean_type_node,
|
| indexse.expr, tmp);
|
| - asprintf (&msg, "%s for array '%s', "
|
| - "lower bound of dimension %d exceeded (%%ld < %%ld)",
|
| - gfc_msg_fault, sym->name, n+1);
|
| + asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
|
| + "below lower bound of %%ld", n+1, sym->name);
|
| gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
|
| fold_convert (long_integer_type_node,
|
| indexse.expr),
|
| @@ -2495,15 +2581,22 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
|
|
|
| /* Upper bound, but not for the last dimension of assumed-size
|
| arrays. */
|
| - if (n < ar->dimen - 1
|
| - || (ar->as->type != AS_ASSUMED_SIZE && !ar->as->cp_was_assumed))
|
| + if (n < ar->dimen - 1 || ar->as->type != AS_ASSUMED_SIZE)
|
| {
|
| tmp = gfc_conv_array_ubound (se->expr, n);
|
| + if (sym->attr.temporary)
|
| + {
|
| + gfc_init_se (&tmpse, se);
|
| + gfc_conv_expr_type (&tmpse, ar->as->upper[n],
|
| + gfc_array_index_type);
|
| + gfc_add_block_to_block (&se->pre, &tmpse.pre);
|
| + tmp = tmpse.expr;
|
| + }
|
| +
|
| cond = fold_build2 (GT_EXPR, boolean_type_node,
|
| indexse.expr, tmp);
|
| - asprintf (&msg, "%s for array '%s', "
|
| - "upper bound of dimension %d exceeded (%%ld > %%ld)",
|
| - gfc_msg_fault, sym->name, n+1);
|
| + asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
|
| + "above upper bound of %%ld", n+1, sym->name);
|
| gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
|
| fold_convert (long_integer_type_node,
|
| indexse.expr),
|
| @@ -2669,7 +2762,7 @@ gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
|
|
|
| /* Generates the actual loop code for a scalarization loop. */
|
|
|
| -static void
|
| +void
|
| gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
|
| stmtblock_t * pbody)
|
| {
|
| @@ -2678,41 +2771,98 @@ gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
|
| tree tmp;
|
| tree loopbody;
|
| tree exit_label;
|
| + tree stmt;
|
| + tree init;
|
| + tree incr;
|
|
|
| - loopbody = gfc_finish_block (pbody);
|
| + if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS))
|
| + == (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS)
|
| + && n == loop->dimen - 1)
|
| + {
|
| + /* We create an OMP_FOR construct for the outermost scalarized loop. */
|
| + init = make_tree_vec (1);
|
| + cond = make_tree_vec (1);
|
| + incr = make_tree_vec (1);
|
| +
|
| + /* Cycle statement is implemented with a goto. Exit statement must not
|
| + be present for this loop. */
|
| + exit_label = gfc_build_label_decl (NULL_TREE);
|
| + TREE_USED (exit_label) = 1;
|
| +
|
| + /* Label for cycle statements (if needed). */
|
| + tmp = build1_v (LABEL_EXPR, exit_label);
|
| + gfc_add_expr_to_block (pbody, tmp);
|
| +
|
| + stmt = make_node (OMP_FOR);
|
| +
|
| + TREE_TYPE (stmt) = void_type_node;
|
| + OMP_FOR_BODY (stmt) = loopbody = gfc_finish_block (pbody);
|
| +
|
| + OMP_FOR_CLAUSES (stmt) = build_omp_clause (input_location,
|
| + OMP_CLAUSE_SCHEDULE);
|
| + OMP_CLAUSE_SCHEDULE_KIND (OMP_FOR_CLAUSES (stmt))
|
| + = OMP_CLAUSE_SCHEDULE_STATIC;
|
| + if (ompws_flags & OMPWS_NOWAIT)
|
| + OMP_CLAUSE_CHAIN (OMP_FOR_CLAUSES (stmt))
|
| + = build_omp_clause (input_location, OMP_CLAUSE_NOWAIT);
|
| +
|
| + /* Initialize the loopvar. */
|
| + TREE_VEC_ELT (init, 0) = build2_v (MODIFY_EXPR, loop->loopvar[n],
|
| + loop->from[n]);
|
| + OMP_FOR_INIT (stmt) = init;
|
| + /* The exit condition. */
|
| + TREE_VEC_ELT (cond, 0) = build2 (LE_EXPR, boolean_type_node,
|
| + loop->loopvar[n], loop->to[n]);
|
| + OMP_FOR_COND (stmt) = cond;
|
| + /* Increment the loopvar. */
|
| + tmp = build2 (PLUS_EXPR, gfc_array_index_type,
|
| + loop->loopvar[n], gfc_index_one_node);
|
| + TREE_VEC_ELT (incr, 0) = fold_build2 (MODIFY_EXPR,
|
| + void_type_node, loop->loopvar[n], tmp);
|
| + OMP_FOR_INCR (stmt) = incr;
|
| +
|
| + ompws_flags &= ~OMPWS_CURR_SINGLEUNIT;
|
| + gfc_add_expr_to_block (&loop->code[n], stmt);
|
| + }
|
| + else
|
| + {
|
| + loopbody = gfc_finish_block (pbody);
|
|
|
| - /* Initialize the loopvar. */
|
| - gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
|
| + /* Initialize the loopvar. */
|
| + if (loop->loopvar[n] != loop->from[n])
|
| + gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
|
|
|
| - exit_label = gfc_build_label_decl (NULL_TREE);
|
| + exit_label = gfc_build_label_decl (NULL_TREE);
|
|
|
| - /* Generate the loop body. */
|
| - gfc_init_block (&block);
|
| + /* Generate the loop body. */
|
| + gfc_init_block (&block);
|
|
|
| - /* The exit condition. */
|
| - cond = fold_build2 (GT_EXPR, boolean_type_node,
|
| - loop->loopvar[n], loop->to[n]);
|
| - tmp = build1_v (GOTO_EXPR, exit_label);
|
| - TREE_USED (exit_label) = 1;
|
| - tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
|
| - gfc_add_expr_to_block (&block, tmp);
|
| + /* The exit condition. */
|
| + cond = fold_build2 (GT_EXPR, boolean_type_node,
|
| + loop->loopvar[n], loop->to[n]);
|
| + tmp = build1_v (GOTO_EXPR, exit_label);
|
| + TREE_USED (exit_label) = 1;
|
| + tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
|
| + gfc_add_expr_to_block (&block, tmp);
|
|
|
| - /* The main body. */
|
| - gfc_add_expr_to_block (&block, loopbody);
|
| + /* The main body. */
|
| + gfc_add_expr_to_block (&block, loopbody);
|
|
|
| - /* Increment the loopvar. */
|
| - tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
|
| - loop->loopvar[n], gfc_index_one_node);
|
| - gfc_add_modify (&block, loop->loopvar[n], tmp);
|
| + /* Increment the loopvar. */
|
| + tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
|
| + loop->loopvar[n], gfc_index_one_node);
|
| + gfc_add_modify (&block, loop->loopvar[n], tmp);
|
|
|
| - /* Build the loop. */
|
| - tmp = gfc_finish_block (&block);
|
| - tmp = build1_v (LOOP_EXPR, tmp);
|
| - gfc_add_expr_to_block (&loop->code[n], tmp);
|
| + /* Build the loop. */
|
| + tmp = gfc_finish_block (&block);
|
| + tmp = build1_v (LOOP_EXPR, tmp);
|
| + gfc_add_expr_to_block (&loop->code[n], tmp);
|
| +
|
| + /* Add the exit label. */
|
| + tmp = build1_v (LABEL_EXPR, exit_label);
|
| + gfc_add_expr_to_block (&loop->code[n], tmp);
|
| + }
|
|
|
| - /* Add the exit label. */
|
| - tmp = build1_v (LABEL_EXPR, exit_label);
|
| - gfc_add_expr_to_block (&loop->code[n], tmp);
|
| }
|
|
|
|
|
| @@ -3017,13 +3167,13 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
|
| }
|
|
|
| /* The rest is just runtime bound checking. */
|
| - if (flag_bounds_check)
|
| + if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
|
| {
|
| stmtblock_t block;
|
| tree lbound, ubound;
|
| tree end;
|
| tree size[GFC_MAX_DIMENSIONS];
|
| - tree stride_pos, stride_neg, non_zerosized, tmp2;
|
| + tree stride_pos, stride_neg, non_zerosized, tmp2, tmp3;
|
| gfc_ss_info *info;
|
| char *msg;
|
| int dim;
|
| @@ -3056,8 +3206,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
|
| continue;
|
|
|
| if (dim == info->ref->u.ar.dimen - 1
|
| - && (info->ref->u.ar.as->type == AS_ASSUMED_SIZE
|
| - || info->ref->u.ar.as->cp_was_assumed))
|
| + && info->ref->u.ar.as->type == AS_ASSUMED_SIZE)
|
| check_upper = false;
|
| else
|
| check_upper = true;
|
| @@ -3103,98 +3252,118 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
|
| stride_pos, stride_neg);
|
|
|
| /* Check the start of the range against the lower and upper
|
| - bounds of the array, if the range is not empty. */
|
| - tmp = fold_build2 (LT_EXPR, boolean_type_node, info->start[n],
|
| - lbound);
|
| - tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
|
| - non_zerosized, tmp);
|
| - asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
|
| - " exceeded (%%ld < %%ld)", gfc_msg_fault,
|
| - info->dim[n]+1, ss->expr->symtree->name);
|
| - gfc_trans_runtime_check (true, false, tmp, &inner,
|
| - &ss->expr->where, msg,
|
| - fold_convert (long_integer_type_node,
|
| - info->start[n]),
|
| - fold_convert (long_integer_type_node,
|
| - lbound));
|
| - gfc_free (msg);
|
| -
|
| + bounds of the array, if the range is not empty.
|
| + If upper bound is present, include both bounds in the
|
| + error message. */
|
| if (check_upper)
|
| {
|
| - tmp = fold_build2 (GT_EXPR, boolean_type_node,
|
| - info->start[n], ubound);
|
| + tmp = fold_build2 (LT_EXPR, boolean_type_node,
|
| + info->start[n], lbound);
|
| + tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
|
| + non_zerosized, tmp);
|
| + tmp2 = fold_build2 (GT_EXPR, boolean_type_node,
|
| + info->start[n], ubound);
|
| + tmp2 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
|
| + non_zerosized, tmp2);
|
| + asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
|
| + "outside of expected range (%%ld:%%ld)",
|
| + info->dim[n]+1, ss->expr->symtree->name);
|
| + gfc_trans_runtime_check (true, false, tmp, &inner,
|
| + &ss->expr->where, msg,
|
| + fold_convert (long_integer_type_node, info->start[n]),
|
| + fold_convert (long_integer_type_node, lbound),
|
| + fold_convert (long_integer_type_node, ubound));
|
| + gfc_trans_runtime_check (true, false, tmp2, &inner,
|
| + &ss->expr->where, msg,
|
| + fold_convert (long_integer_type_node, info->start[n]),
|
| + fold_convert (long_integer_type_node, lbound),
|
| + fold_convert (long_integer_type_node, ubound));
|
| + gfc_free (msg);
|
| + }
|
| + else
|
| + {
|
| + tmp = fold_build2 (LT_EXPR, boolean_type_node,
|
| + info->start[n], lbound);
|
| tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
|
| non_zerosized, tmp);
|
| - asprintf (&msg, "%s, upper bound of dimension %d of array "
|
| - "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault,
|
| + asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
|
| + "below lower bound of %%ld",
|
| info->dim[n]+1, ss->expr->symtree->name);
|
| - gfc_trans_runtime_check (true, false, tmp, &inner,
|
| - &ss->expr->where, msg,
|
| - fold_convert (long_integer_type_node, info->start[n]),
|
| - fold_convert (long_integer_type_node, ubound));
|
| + gfc_trans_runtime_check (true, false, tmp, &inner,
|
| + &ss->expr->where, msg,
|
| + fold_convert (long_integer_type_node, info->start[n]),
|
| + fold_convert (long_integer_type_node, lbound));
|
| gfc_free (msg);
|
| }
|
| -
|
| +
|
| /* Compute the last element of the range, which is not
|
| necessarily "end" (think 0:5:3, which doesn't contain 5)
|
| and check it against both lower and upper bounds. */
|
| - tmp2 = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
|
| +
|
| + tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
|
| info->start[n]);
|
| - tmp2 = fold_build2 (TRUNC_MOD_EXPR, gfc_array_index_type, tmp2,
|
| + tmp = fold_build2 (TRUNC_MOD_EXPR, gfc_array_index_type, tmp,
|
| info->stride[n]);
|
| - tmp2 = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
|
| - tmp2);
|
| -
|
| - tmp = fold_build2 (LT_EXPR, boolean_type_node, tmp2, lbound);
|
| - tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
|
| - non_zerosized, tmp);
|
| - asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
|
| - " exceeded (%%ld < %%ld)", gfc_msg_fault,
|
| - info->dim[n]+1, ss->expr->symtree->name);
|
| - gfc_trans_runtime_check (true, false, tmp, &inner,
|
| - &ss->expr->where, msg,
|
| - fold_convert (long_integer_type_node,
|
| - tmp2),
|
| - fold_convert (long_integer_type_node,
|
| - lbound));
|
| - gfc_free (msg);
|
| -
|
| + tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
|
| + tmp);
|
| + tmp2 = fold_build2 (LT_EXPR, boolean_type_node, tmp, lbound);
|
| + tmp2 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
|
| + non_zerosized, tmp2);
|
| if (check_upper)
|
| {
|
| - tmp = fold_build2 (GT_EXPR, boolean_type_node, tmp2, ubound);
|
| - tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
|
| - non_zerosized, tmp);
|
| - asprintf (&msg, "%s, upper bound of dimension %d of array "
|
| - "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault,
|
| + tmp3 = fold_build2 (GT_EXPR, boolean_type_node, tmp, ubound);
|
| + tmp3 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
|
| + non_zerosized, tmp3);
|
| + asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
|
| + "outside of expected range (%%ld:%%ld)",
|
| info->dim[n]+1, ss->expr->symtree->name);
|
| - gfc_trans_runtime_check (true, false, tmp, &inner,
|
| - &ss->expr->where, msg,
|
| - fold_convert (long_integer_type_node, tmp2),
|
| - fold_convert (long_integer_type_node, ubound));
|
| + gfc_trans_runtime_check (true, false, tmp2, &inner,
|
| + &ss->expr->where, msg,
|
| + fold_convert (long_integer_type_node, tmp),
|
| + fold_convert (long_integer_type_node, ubound),
|
| + fold_convert (long_integer_type_node, lbound));
|
| + gfc_trans_runtime_check (true, false, tmp3, &inner,
|
| + &ss->expr->where, msg,
|
| + fold_convert (long_integer_type_node, tmp),
|
| + fold_convert (long_integer_type_node, ubound),
|
| + fold_convert (long_integer_type_node, lbound));
|
| gfc_free (msg);
|
| }
|
| -
|
| + else
|
| + {
|
| + asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
|
| + "below lower bound of %%ld",
|
| + info->dim[n]+1, ss->expr->symtree->name);
|
| + gfc_trans_runtime_check (true, false, tmp2, &inner,
|
| + &ss->expr->where, msg,
|
| + fold_convert (long_integer_type_node, tmp),
|
| + fold_convert (long_integer_type_node, lbound));
|
| + gfc_free (msg);
|
| + }
|
| +
|
| /* Check the section sizes match. */
|
| tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
|
| info->start[n]);
|
| tmp = fold_build2 (FLOOR_DIV_EXPR, gfc_array_index_type, tmp,
|
| info->stride[n]);
|
| + tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
|
| + gfc_index_one_node, tmp);
|
| tmp = fold_build2 (MAX_EXPR, gfc_array_index_type, tmp,
|
| build_int_cst (gfc_array_index_type, 0));
|
| /* We remember the size of the first section, and check all the
|
| others against this. */
|
| if (size[n])
|
| {
|
| - tree tmp3;
|
| -
|
| tmp3 = fold_build2 (NE_EXPR, boolean_type_node, tmp, size[n]);
|
| - asprintf (&msg, "%s, size mismatch for dimension %d "
|
| - "of array '%s' (%%ld/%%ld)", gfc_msg_bounds,
|
| + asprintf (&msg, "Array bound mismatch for dimension %d "
|
| + "of array '%s' (%%ld/%%ld)",
|
| info->dim[n]+1, ss->expr->symtree->name);
|
| +
|
| gfc_trans_runtime_check (true, false, tmp3, &inner,
|
| &ss->expr->where, msg,
|
| fold_convert (long_integer_type_node, tmp),
|
| fold_convert (long_integer_type_node, size[n]));
|
| +
|
| gfc_free (msg);
|
| }
|
| else
|
| @@ -3209,7 +3378,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
|
| || ss->expr->symtree->n.sym->attr.not_always_present)
|
| tmp = build3_v (COND_EXPR,
|
| gfc_conv_expr_present (ss->expr->symtree->n.sym),
|
| - tmp, build_empty_stmt ());
|
| + tmp, build_empty_stmt (input_location));
|
|
|
| gfc_add_expr_to_block (&block, tmp);
|
|
|
| @@ -3288,13 +3457,9 @@ gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
|
| gfc_ss *ss;
|
| gfc_ref *lref;
|
| gfc_ref *rref;
|
| - gfc_ref *aref;
|
| int nDepend = 0;
|
| - int temp_dim = 0;
|
|
|
| loop->temp_ss = NULL;
|
| - aref = dest->data.info.ref;
|
| - temp_dim = 0;
|
|
|
| for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
|
| {
|
| @@ -3343,7 +3508,6 @@ gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
|
| if (depends[n])
|
| loop->order[dim++] = n;
|
| }
|
| - temp_dim = dim;
|
| for (n = 0; n < loop->dimen; n++)
|
| {
|
| if (! depends[n])
|
| @@ -3386,12 +3550,10 @@ void
|
| gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
|
| {
|
| int n;
|
| - int dim;
|
| gfc_ss_info *info;
|
| gfc_ss_info *specinfo;
|
| gfc_ss *ss;
|
| tree tmp;
|
| - tree len;
|
| gfc_ss *loopspec[GFC_MAX_DIMENSIONS];
|
| bool dynamic[GFC_MAX_DIMENSIONS];
|
| gfc_constructor *c;
|
| @@ -3572,7 +3734,6 @@ gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
|
| loop->temp_ss->string_length);
|
|
|
| tmp = loop->temp_ss->data.temp.type;
|
| - len = loop->temp_ss->string_length;
|
| n = loop->temp_ss->data.temp.dimen;
|
| memset (&loop->temp_ss->data.info, 0, sizeof (gfc_ss_info));
|
| loop->temp_ss->type = GFC_SS_SECTION;
|
| @@ -3604,8 +3765,6 @@ gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
|
|
|
| for (n = 0; n < info->dimen; n++)
|
| {
|
| - dim = info->dim[n];
|
| -
|
| /* If we are specifying the range the delta is already set. */
|
| if (loopspec[n] != ss)
|
| {
|
| @@ -3705,8 +3864,8 @@ gfc_array_init_size (tree descriptor, int rank, tree * poffset,
|
| ubound = lower[n];
|
| }
|
| }
|
| - tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[n]);
|
| - gfc_add_modify (pblock, tmp, se.expr);
|
| + gfc_conv_descriptor_lbound_set (pblock, descriptor, gfc_rank_cst[n],
|
| + se.expr);
|
|
|
| /* Work out the offset for this component. */
|
| tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, se.expr, stride);
|
| @@ -3722,12 +3881,10 @@ gfc_array_init_size (tree descriptor, int rank, tree * poffset,
|
| gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
|
| gfc_add_block_to_block (pblock, &se.pre);
|
|
|
| - tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[n]);
|
| - gfc_add_modify (pblock, tmp, se.expr);
|
| + gfc_conv_descriptor_ubound_set (pblock, descriptor, gfc_rank_cst[n], se.expr);
|
|
|
| /* Store the stride. */
|
| - tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[n]);
|
| - gfc_add_modify (pblock, tmp, stride);
|
| + gfc_conv_descriptor_stride_set (pblock, descriptor, gfc_rank_cst[n], stride);
|
|
|
| /* Calculate the size of this dimension. */
|
| size = fold_build2 (PLUS_EXPR, gfc_array_index_type, se.expr, size);
|
| @@ -3856,13 +4013,12 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
|
| tmp = fold_build2 (MODIFY_EXPR, void_type_node, pointer, tmp);
|
| gfc_add_expr_to_block (&se->pre, tmp);
|
|
|
| - tmp = gfc_conv_descriptor_offset (se->expr);
|
| - gfc_add_modify (&se->pre, tmp, offset);
|
| + gfc_conv_descriptor_offset_set (&se->pre, se->expr, offset);
|
|
|
| if (expr->ts.type == BT_DERIVED
|
| - && expr->ts.derived->attr.alloc_comp)
|
| + && expr->ts.u.derived->attr.alloc_comp)
|
| {
|
| - tmp = gfc_nullify_alloc_comp (expr->ts.derived, se->expr,
|
| + tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, se->expr,
|
| ref->u.ar.as->rank);
|
| gfc_add_expr_to_block (&se->pre, tmp);
|
| }
|
| @@ -3953,11 +4109,11 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr)
|
| {
|
| /* Problems occur when we get something like
|
| integer :: a(lots) = (/(i, i=1, lots)/) */
|
| - gfc_error_now ("The number of elements in the array constructor "
|
| - "at %L requires an increase of the allowed %d "
|
| - "upper limit. See -fmax-array-constructor "
|
| - "option", &expr->where,
|
| - gfc_option.flag_max_array_constructor);
|
| + gfc_fatal_error ("The number of elements in the array constructor "
|
| + "at %L requires an increase of the allowed %d "
|
| + "upper limit. See -fmax-array-constructor "
|
| + "option", &expr->where,
|
| + gfc_option.flag_max_array_constructor);
|
| return NULL_TREE;
|
| }
|
| if (mpz_cmp_si (c->n.offset, 0) != 0)
|
| @@ -4148,9 +4304,9 @@ gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, tree fnbody)
|
|
|
| /* Evaluate character string length. */
|
| if (sym->ts.type == BT_CHARACTER
|
| - && onstack && !INTEGER_CST_P (sym->ts.cl->backend_decl))
|
| + && onstack && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
|
| {
|
| - gfc_conv_string_length (sym->ts.cl, NULL, &block);
|
| + gfc_conv_string_length (sym->ts.u.cl, NULL, &block);
|
|
|
| gfc_trans_vla_type_sizes (sym, &block);
|
|
|
| @@ -4173,8 +4329,8 @@ gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, tree fnbody)
|
| gcc_assert (!sym->module);
|
|
|
| if (sym->ts.type == BT_CHARACTER
|
| - && !INTEGER_CST_P (sym->ts.cl->backend_decl))
|
| - gfc_conv_string_length (sym->ts.cl, NULL, &block);
|
| + && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
|
| + gfc_conv_string_length (sym->ts.u.cl, NULL, &block);
|
|
|
| size = gfc_trans_array_bounds (type, sym, &offset, &block);
|
|
|
| @@ -4239,8 +4395,8 @@ gfc_trans_g77_array (gfc_symbol * sym, tree body)
|
| gfc_start_block (&block);
|
|
|
| if (sym->ts.type == BT_CHARACTER
|
| - && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
|
| - gfc_conv_string_length (sym->ts.cl, NULL, &block);
|
| + && TREE_CODE (sym->ts.u.cl->backend_decl) == VAR_DECL)
|
| + gfc_conv_string_length (sym->ts.u.cl, NULL, &block);
|
|
|
| /* Evaluate the bounds of the array. */
|
| gfc_trans_array_bounds (type, sym, &offset, &block);
|
| @@ -4266,7 +4422,7 @@ gfc_trans_g77_array (gfc_symbol * sym, tree body)
|
| if (sym->attr.optional || sym->attr.not_always_present)
|
| {
|
| tmp = gfc_conv_expr_present (sym);
|
| - stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
|
| + stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
|
| }
|
|
|
| gfc_add_expr_to_block (&block, stmt);
|
| @@ -4327,14 +4483,16 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
|
| type = TREE_TYPE (tmpdesc);
|
| gcc_assert (GFC_ARRAY_TYPE_P (type));
|
| dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
|
| - dumdesc = build_fold_indirect_ref (dumdesc);
|
| + dumdesc = build_fold_indirect_ref_loc (input_location,
|
| + dumdesc);
|
| gfc_start_block (&block);
|
|
|
| if (sym->ts.type == BT_CHARACTER
|
| - && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
|
| - gfc_conv_string_length (sym->ts.cl, NULL, &block);
|
| + && TREE_CODE (sym->ts.u.cl->backend_decl) == VAR_DECL)
|
| + gfc_conv_string_length (sym->ts.u.cl, NULL, &block);
|
|
|
| - checkparm = (sym->as->type == AS_EXPLICIT && flag_bounds_check);
|
| + checkparm = (sym->as->type == AS_EXPLICIT
|
| + && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS));
|
|
|
| no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
|
| || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));
|
| @@ -4346,7 +4504,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
|
| anything as we still don't know the array stride. */
|
| partial = gfc_create_var (boolean_type_node, "partial");
|
| TREE_USED (partial) = 1;
|
| - tmp = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
|
| + tmp = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
|
| tmp = fold_build2 (EQ_EXPR, boolean_type_node, tmp, gfc_index_one_node);
|
| gfc_add_modify (&block, partial, tmp);
|
| }
|
| @@ -4360,7 +4518,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
|
| if (no_repack)
|
| {
|
| /* Set the first stride. */
|
| - stride = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
|
| + stride = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
|
| stride = gfc_evaluate_now (stride, &block);
|
|
|
| tmp = fold_build2 (EQ_EXPR, boolean_type_node,
|
| @@ -4378,7 +4536,8 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
|
| gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
|
| /* A library call to repack the array if necessary. */
|
| tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
|
| - stmt_unpacked = build_call_expr (gfor_fndecl_in_pack, 1, tmp);
|
| + stmt_unpacked = build_call_expr_loc (input_location,
|
| + gfor_fndecl_in_pack, 1, tmp);
|
|
|
| stride = gfc_index_one_node;
|
|
|
| @@ -4413,8 +4572,8 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
|
| if (checkparm || !sym->as->upper[n])
|
| {
|
| /* Get the bounds of the actual parameter. */
|
| - dubound = gfc_conv_descriptor_ubound (dumdesc, gfc_rank_cst[n]);
|
| - dlbound = gfc_conv_descriptor_lbound (dumdesc, gfc_rank_cst[n]);
|
| + dubound = gfc_conv_descriptor_ubound_get (dumdesc, gfc_rank_cst[n]);
|
| + dlbound = gfc_conv_descriptor_lbound_get (dumdesc, gfc_rank_cst[n]);
|
| }
|
| else
|
| {
|
| @@ -4451,15 +4610,26 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
|
| {
|
| /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)). */
|
| char * msg;
|
| + tree temp;
|
|
|
| - tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
|
| - ubound, lbound);
|
| - stride2 = fold_build2 (MINUS_EXPR, gfc_array_index_type,
|
| + temp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
|
| + ubound, lbound);
|
| + temp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
|
| + gfc_index_one_node, temp);
|
| +
|
| + stride2 = fold_build2 (MINUS_EXPR, gfc_array_index_type,
|
| dubound, dlbound);
|
| - tmp = fold_build2 (NE_EXPR, gfc_array_index_type, tmp, stride2);
|
| - asprintf (&msg, "%s for dimension %d of array '%s'",
|
| - gfc_msg_bounds, n+1, sym->name);
|
| - gfc_trans_runtime_check (true, false, tmp, &block, &loc, msg);
|
| + stride2 = fold_build2 (PLUS_EXPR, gfc_array_index_type,
|
| + gfc_index_one_node, stride2);
|
| +
|
| + tmp = fold_build2 (NE_EXPR, gfc_array_index_type, temp, stride2);
|
| + asprintf (&msg, "Dimension %d of array '%s' has extent "
|
| + "%%ld instead of %%ld", n+1, sym->name);
|
| +
|
| + gfc_trans_runtime_check (true, false, tmp, &block, &loc, msg,
|
| + fold_convert (long_integer_type_node, temp),
|
| + fold_convert (long_integer_type_node, stride2));
|
| +
|
| gfc_free (msg);
|
| }
|
| }
|
| @@ -4484,7 +4654,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
|
| if (no_repack || partial != NULL_TREE)
|
| {
|
| stmt_unpacked =
|
| - gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[n+1]);
|
| + gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[n+1]);
|
| }
|
|
|
| /* Figure out the stride if not a known constant. */
|
| @@ -4549,7 +4719,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
|
| if (optional_arg)
|
| {
|
| tmp = gfc_conv_expr_present (sym);
|
| - stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
|
| + stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
|
| }
|
| gfc_add_expr_to_block (&block, stmt);
|
|
|
| @@ -4564,7 +4734,8 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
|
| if (sym->attr.intent != INTENT_IN)
|
| {
|
| /* Copy the data back. */
|
| - tmp = build_call_expr (gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
|
| + tmp = build_call_expr_loc (input_location,
|
| + gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
|
| gfc_add_expr_to_block (&cleanup, tmp);
|
| }
|
|
|
| @@ -4575,15 +4746,17 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
|
| stmt = gfc_finish_block (&cleanup);
|
|
|
| /* Only do the cleanup if the array was repacked. */
|
| - tmp = build_fold_indirect_ref (dumdesc);
|
| + tmp = build_fold_indirect_ref_loc (input_location,
|
| + dumdesc);
|
| tmp = gfc_conv_descriptor_data_get (tmp);
|
| tmp = fold_build2 (NE_EXPR, boolean_type_node, tmp, tmpdesc);
|
| - stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
|
| + stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
|
|
|
| if (optional_arg)
|
| {
|
| tmp = gfc_conv_expr_present (sym);
|
| - stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
|
| + stmt = build3_v (COND_EXPR, tmp, stmt,
|
| + build_empty_stmt (input_location));
|
| }
|
| gfc_add_expr_to_block (&block, stmt);
|
| }
|
| @@ -4617,7 +4790,8 @@ gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
|
| }
|
|
|
| tmp = gfc_conv_array_data (desc);
|
| - tmp = build_fold_indirect_ref (tmp);
|
| + tmp = build_fold_indirect_ref_loc (input_location,
|
| + tmp);
|
| tmp = gfc_build_array_ref (tmp, offset, NULL);
|
|
|
| /* Offset the data pointer for pointer assignments from arrays with
|
| @@ -4704,47 +4878,104 @@ gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
|
| }
|
|
|
|
|
| -/* gfc_conv_expr_descriptor needs the character length of elemental
|
| - functions before the function is called so that the size of the
|
| - temporary can be obtained. The only way to do this is to convert
|
| - the expression, mapping onto the actual arguments. */
|
| +/* gfc_conv_expr_descriptor needs the string length an expression
|
| + so that the size of the temporary can be obtained. This is done
|
| + by adding up the string lengths of all the elements in the
|
| + expression. Function with non-constant expressions have their
|
| + string lengths mapped onto the actual arguments using the
|
| + interface mapping machinery in trans-expr.c. */
|
| static void
|
| -get_elemental_fcn_charlen (gfc_expr *expr, gfc_se *se)
|
| +get_array_charlen (gfc_expr *expr, gfc_se *se)
|
| {
|
| gfc_interface_mapping mapping;
|
| gfc_formal_arglist *formal;
|
| gfc_actual_arglist *arg;
|
| gfc_se tse;
|
|
|
| - formal = expr->symtree->n.sym->formal;
|
| - arg = expr->value.function.actual;
|
| - gfc_init_interface_mapping (&mapping);
|
| -
|
| - /* Set se = NULL in the calls to the interface mapping, to suppress any
|
| - backend stuff. */
|
| - for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
|
| + if (expr->ts.u.cl->length
|
| + && gfc_is_constant_expr (expr->ts.u.cl->length))
|
| {
|
| - if (!arg->expr)
|
| - continue;
|
| - if (formal->sym)
|
| - gfc_add_interface_mapping (&mapping, formal->sym, NULL, arg->expr);
|
| + if (!expr->ts.u.cl->backend_decl)
|
| + gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
|
| + return;
|
| }
|
|
|
| - gfc_init_se (&tse, NULL);
|
| + switch (expr->expr_type)
|
| + {
|
| + case EXPR_OP:
|
| + get_array_charlen (expr->value.op.op1, se);
|
| +
|
| + /* For parentheses the expression ts.u.cl is identical. */
|
| + if (expr->value.op.op == INTRINSIC_PARENTHESES)
|
| + return;
|
| +
|
| + expr->ts.u.cl->backend_decl =
|
| + gfc_create_var (gfc_charlen_type_node, "sln");
|
| +
|
| + if (expr->value.op.op2)
|
| + {
|
| + get_array_charlen (expr->value.op.op2, se);
|
| +
|
| + gcc_assert (expr->value.op.op == INTRINSIC_CONCAT);
|
|
|
| - /* Build the expression for the character length and convert it. */
|
| - gfc_apply_interface_mapping (&mapping, &tse, expr->ts.cl->length);
|
| + /* Add the string lengths and assign them to the expression
|
| + string length backend declaration. */
|
| + gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
|
| + fold_build2 (PLUS_EXPR, gfc_charlen_type_node,
|
| + expr->value.op.op1->ts.u.cl->backend_decl,
|
| + expr->value.op.op2->ts.u.cl->backend_decl));
|
| + }
|
| + else
|
| + gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
|
| + expr->value.op.op1->ts.u.cl->backend_decl);
|
| + break;
|
| +
|
| + case EXPR_FUNCTION:
|
| + if (expr->value.function.esym == NULL
|
| + || expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
|
| + {
|
| + gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
|
| + break;
|
| + }
|
| +
|
| + /* Map expressions involving the dummy arguments onto the actual
|
| + argument expressions. */
|
| + gfc_init_interface_mapping (&mapping);
|
| + formal = expr->symtree->n.sym->formal;
|
| + arg = expr->value.function.actual;
|
|
|
| - gfc_add_block_to_block (&se->pre, &tse.pre);
|
| - gfc_add_block_to_block (&se->post, &tse.post);
|
| - tse.expr = fold_convert (gfc_charlen_type_node, tse.expr);
|
| - tse.expr = fold_build2 (MAX_EXPR, gfc_charlen_type_node, tse.expr,
|
| - build_int_cst (gfc_charlen_type_node, 0));
|
| - expr->ts.cl->backend_decl = tse.expr;
|
| - gfc_free_interface_mapping (&mapping);
|
| + /* Set se = NULL in the calls to the interface mapping, to suppress any
|
| + backend stuff. */
|
| + for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
|
| + {
|
| + if (!arg->expr)
|
| + continue;
|
| + if (formal->sym)
|
| + gfc_add_interface_mapping (&mapping, formal->sym, NULL, arg->expr);
|
| + }
|
| +
|
| + gfc_init_se (&tse, NULL);
|
| +
|
| + /* Build the expression for the character length and convert it. */
|
| + gfc_apply_interface_mapping (&mapping, &tse, expr->ts.u.cl->length);
|
| +
|
| + gfc_add_block_to_block (&se->pre, &tse.pre);
|
| + gfc_add_block_to_block (&se->post, &tse.post);
|
| + tse.expr = fold_convert (gfc_charlen_type_node, tse.expr);
|
| + tse.expr = fold_build2 (MAX_EXPR, gfc_charlen_type_node, tse.expr,
|
| + build_int_cst (gfc_charlen_type_node, 0));
|
| + expr->ts.u.cl->backend_decl = tse.expr;
|
| + gfc_free_interface_mapping (&mapping);
|
| + break;
|
| +
|
| + default:
|
| + gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
|
| + break;
|
| + }
|
| }
|
|
|
|
|
| +
|
| /* Convert an array for passing as an actual argument. Expressions and
|
| vector subscripts are evaluated and stored in a temporary, which is then
|
| passed. For whole arrays the descriptor is passed. For array sections
|
| @@ -4838,7 +5069,7 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
|
| {
|
| /* We pass full arrays directly. This means that pointers and
|
| allocatable arrays should also work. */
|
| - se->expr = build_fold_addr_expr (desc);
|
| + se->expr = gfc_build_addr_expr (NULL_TREE, desc);
|
| }
|
| else
|
| {
|
| @@ -4869,7 +5100,7 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
|
|
|
| /* For pointer assignments pass the descriptor directly. */
|
| se->ss = secss;
|
| - se->expr = build_fold_addr_expr (se->expr);
|
| + se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
|
| gfc_conv_expr (se, expr);
|
| return;
|
| }
|
| @@ -4879,8 +5110,8 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
|
| /* Elemental function. */
|
| need_tmp = 1;
|
| if (expr->ts.type == BT_CHARACTER
|
| - && expr->ts.cl->length->expr_type != EXPR_CONSTANT)
|
| - get_elemental_fcn_charlen (expr, se);
|
| + && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
|
| + get_array_charlen (expr, se);
|
|
|
| info = NULL;
|
| }
|
| @@ -4940,13 +5171,14 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
|
| loop.temp_ss->type = GFC_SS_TEMP;
|
| loop.temp_ss->next = gfc_ss_terminator;
|
|
|
| - if (expr->ts.type == BT_CHARACTER && !expr->ts.cl->backend_decl)
|
| - gfc_conv_string_length (expr->ts.cl, expr, &se->pre);
|
| + if (expr->ts.type == BT_CHARACTER
|
| + && !expr->ts.u.cl->backend_decl)
|
| + get_array_charlen (expr, se);
|
|
|
| loop.temp_ss->data.temp.type = gfc_typenode_for_spec (&expr->ts);
|
|
|
| if (expr->ts.type == BT_CHARACTER)
|
| - loop.temp_ss->string_length = expr->ts.cl->backend_decl;
|
| + loop.temp_ss->string_length = expr->ts.u.cl->backend_decl;
|
| else
|
| loop.temp_ss->string_length = NULL;
|
|
|
| @@ -4984,7 +5216,8 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
|
| {
|
| gfc_conv_expr (&rse, expr);
|
| if (POINTER_TYPE_P (TREE_TYPE (rse.expr)))
|
| - rse.expr = build_fold_indirect_ref (rse.expr);
|
| + rse.expr = build_fold_indirect_ref_loc (input_location,
|
| + rse.expr);
|
| }
|
| else
|
| gfc_conv_expr_val (&rse, expr);
|
| @@ -5042,7 +5275,7 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
|
| parmtype = gfc_get_element_type (TREE_TYPE (desc));
|
| parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen,
|
| loop.from, loop.to, 0,
|
| - GFC_ARRAY_UNKNOWN);
|
| + GFC_ARRAY_UNKNOWN, false);
|
| parm = gfc_create_var (parmtype, "parm");
|
| }
|
|
|
| @@ -5128,19 +5361,21 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
|
| to = fold_build2 (PLUS_EXPR, gfc_array_index_type, to, tmp);
|
| from = gfc_index_one_node;
|
| }
|
| - tmp = gfc_conv_descriptor_lbound (parm, gfc_rank_cst[dim]);
|
| - gfc_add_modify (&loop.pre, tmp, from);
|
| + gfc_conv_descriptor_lbound_set (&loop.pre, parm,
|
| + gfc_rank_cst[dim], from);
|
|
|
| /* Set the new upper bound. */
|
| - tmp = gfc_conv_descriptor_ubound (parm, gfc_rank_cst[dim]);
|
| - gfc_add_modify (&loop.pre, tmp, to);
|
| + gfc_conv_descriptor_ubound_set (&loop.pre, parm,
|
| + gfc_rank_cst[dim], to);
|
|
|
| /* Multiply the stride by the section stride to get the
|
| total stride. */
|
| stride = fold_build2 (MULT_EXPR, gfc_array_index_type,
|
| stride, info->stride[dim]);
|
|
|
| - if (se->direct_byref && info->ref && info->ref->u.ar.type != AR_FULL)
|
| + if (se->direct_byref
|
| + && info->ref
|
| + && info->ref->u.ar.type != AR_FULL)
|
| {
|
| base = fold_build2 (MINUS_EXPR, TREE_TYPE (base),
|
| base, stride);
|
| @@ -5157,16 +5392,17 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
|
| }
|
|
|
| /* Store the new stride. */
|
| - tmp = gfc_conv_descriptor_stride (parm, gfc_rank_cst[dim]);
|
| - gfc_add_modify (&loop.pre, tmp, stride);
|
| + gfc_conv_descriptor_stride_set (&loop.pre, parm,
|
| + gfc_rank_cst[dim], stride);
|
|
|
| dim++;
|
| }
|
|
|
| if (se->data_not_needed)
|
| - gfc_conv_descriptor_data_set (&loop.pre, parm, gfc_index_zero_node);
|
| + gfc_conv_descriptor_data_set (&loop.pre, parm,
|
| + gfc_index_zero_node);
|
| else
|
| - /* Point the data pointer at the first element in the section. */
|
| + /* Point the data pointer at the 1st element in the section. */
|
| gfc_get_dataptr_offset (&loop.pre, parm, desc, offset,
|
| subref_array_target, expr);
|
|
|
| @@ -5174,15 +5410,13 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
|
| && !se->data_not_needed)
|
| {
|
| /* Set the offset. */
|
| - tmp = gfc_conv_descriptor_offset (parm);
|
| - gfc_add_modify (&loop.pre, tmp, base);
|
| + gfc_conv_descriptor_offset_set (&loop.pre, parm, base);
|
| }
|
| else
|
| {
|
| /* Only the callee knows what the correct offset it, so just set
|
| it to zero here. */
|
| - tmp = gfc_conv_descriptor_offset (parm);
|
| - gfc_add_modify (&loop.pre, tmp, gfc_index_zero_node);
|
| + gfc_conv_descriptor_offset_set (&loop.pre, parm, gfc_index_zero_node);
|
| }
|
| desc = parm;
|
| }
|
| @@ -5191,7 +5425,7 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
|
| {
|
| /* Get a pointer to the new descriptor. */
|
| if (se->want_pointer)
|
| - se->expr = build_fold_addr_expr (desc);
|
| + se->expr = gfc_build_addr_expr (NULL_TREE, desc);
|
| else
|
| se->expr = desc;
|
| }
|
| @@ -5203,35 +5437,89 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
|
| gfc_cleanup_loop (&loop);
|
| }
|
|
|
| +/* Helper function for gfc_conv_array_parameter if array size needs to be
|
| + computed. */
|
| +
|
| +static void
|
| +array_parameter_size (tree desc, gfc_expr *expr, tree *size)
|
| +{
|
| + tree elem;
|
| + if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
|
| + *size = GFC_TYPE_ARRAY_SIZE (TREE_TYPE (desc));
|
| + else if (expr->rank > 1)
|
| + *size = build_call_expr_loc (input_location,
|
| + gfor_fndecl_size0, 1,
|
| + gfc_build_addr_expr (NULL, desc));
|
| + else
|
| + {
|
| + tree ubound = gfc_conv_descriptor_ubound_get (desc, gfc_index_zero_node);
|
| + tree lbound = gfc_conv_descriptor_lbound_get (desc, gfc_index_zero_node);
|
| +
|
| + *size = fold_build2 (MINUS_EXPR, gfc_array_index_type, ubound, lbound);
|
| + *size = fold_build2 (PLUS_EXPR, gfc_array_index_type, *size,
|
| + gfc_index_one_node);
|
| + *size = fold_build2 (MAX_EXPR, gfc_array_index_type, *size,
|
| + gfc_index_zero_node);
|
| + }
|
| + elem = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
|
| + *size = fold_build2 (MULT_EXPR, gfc_array_index_type, *size,
|
| + fold_convert (gfc_array_index_type, elem));
|
| +}
|
|
|
| /* Convert an array for passing as an actual parameter. */
|
| /* TODO: Optimize passing g77 arrays. */
|
|
|
| void
|
| -gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
|
| - const gfc_symbol *fsym, const char *proc_name)
|
| +gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, bool g77,
|
| + const gfc_symbol *fsym, const char *proc_name,
|
| + tree *size)
|
| {
|
| tree ptr;
|
| tree desc;
|
| tree tmp = NULL_TREE;
|
| tree stmt;
|
| tree parent = DECL_CONTEXT (current_function_decl);
|
| - bool full_array_var, this_array_result;
|
| + bool full_array_var;
|
| + bool this_array_result;
|
| + bool contiguous;
|
| + bool no_pack;
|
| + bool array_constructor;
|
| + bool good_allocatable;
|
| + bool ultimate_ptr_comp;
|
| + bool ultimate_alloc_comp;
|
| gfc_symbol *sym;
|
| stmtblock_t block;
|
| + gfc_ref *ref;
|
| +
|
| + ultimate_ptr_comp = false;
|
| + ultimate_alloc_comp = false;
|
| + for (ref = expr->ref; ref; ref = ref->next)
|
| + {
|
| + if (ref->next == NULL)
|
| + break;
|
| +
|
| + if (ref->type == REF_COMPONENT)
|
| + {
|
| + ultimate_ptr_comp = ref->u.c.component->attr.pointer;
|
| + ultimate_alloc_comp = ref->u.c.component->attr.allocatable;
|
| + }
|
| + }
|
| +
|
| + full_array_var = false;
|
| + contiguous = false;
|
| +
|
| + if (expr->expr_type == EXPR_VARIABLE && ref && !ultimate_ptr_comp)
|
| + full_array_var = gfc_full_array_ref_p (ref, &contiguous);
|
|
|
| - full_array_var = (expr->expr_type == EXPR_VARIABLE
|
| - && expr->ref->type == REF_ARRAY
|
| - && expr->ref->u.ar.type == AR_FULL);
|
| sym = full_array_var ? expr->symtree->n.sym : NULL;
|
|
|
| /* The symbol should have an array specification. */
|
| - gcc_assert (!sym || sym->as);
|
| + gcc_assert (!sym || sym->as || ref->u.ar.as);
|
|
|
| if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
|
| {
|
| get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
|
| - expr->ts.cl->backend_decl = tmp;
|
| + expr->ts.u.cl->backend_decl = tmp;
|
| se->string_length = tmp;
|
| }
|
|
|
| @@ -5248,40 +5536,95 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
|
| tmp = gfc_get_symbol_decl (sym);
|
|
|
| if (sym->ts.type == BT_CHARACTER)
|
| - se->string_length = sym->ts.cl->backend_decl;
|
| - if (!sym->attr.pointer && sym->as->type != AS_ASSUMED_SHAPE
|
| - && !sym->attr.allocatable)
|
| + se->string_length = sym->ts.u.cl->backend_decl;
|
| +
|
| + if (sym->ts.type == BT_DERIVED)
|
| + {
|
| + gfc_conv_expr_descriptor (se, expr, ss);
|
| + se->expr = gfc_conv_array_data (se->expr);
|
| + return;
|
| + }
|
| +
|
| + if (!sym->attr.pointer
|
| + && sym->as
|
| + && sym->as->type != AS_ASSUMED_SHAPE
|
| + && !sym->attr.allocatable)
|
| {
|
| /* Some variables are declared directly, others are declared as
|
| pointers and allocated on the heap. */
|
| if (sym->attr.dummy || POINTER_TYPE_P (TREE_TYPE (tmp)))
|
| se->expr = tmp;
|
| else
|
| - se->expr = build_fold_addr_expr (tmp);
|
| + se->expr = gfc_build_addr_expr (NULL_TREE, tmp);
|
| + if (size)
|
| + array_parameter_size (tmp, expr, size);
|
| return;
|
| }
|
| +
|
| if (sym->attr.allocatable)
|
| {
|
| if (sym->attr.dummy || sym->attr.result)
|
| {
|
| gfc_conv_expr_descriptor (se, expr, ss);
|
| - se->expr = gfc_conv_array_data (se->expr);
|
| + tmp = se->expr;
|
| }
|
| - else
|
| - se->expr = gfc_conv_array_data (tmp);
|
| + if (size)
|
| + array_parameter_size (tmp, expr, size);
|
| + se->expr = gfc_conv_array_data (tmp);
|
| return;
|
| }
|
| }
|
|
|
| + /* A convenient reduction in scope. */
|
| + contiguous = g77 && !this_array_result && contiguous;
|
| +
|
| + /* There is no need to pack and unpack the array, if it is contiguous
|
| + and not deferred or assumed shape. */
|
| + no_pack = ((sym && sym->as
|
| + && !sym->attr.pointer
|
| + && sym->as->type != AS_DEFERRED
|
| + && sym->as->type != AS_ASSUMED_SHAPE)
|
| + ||
|
| + (ref && ref->u.ar.as
|
| + && ref->u.ar.as->type != AS_DEFERRED
|
| + && ref->u.ar.as->type != AS_ASSUMED_SHAPE));
|
| +
|
| + no_pack = contiguous && no_pack;
|
| +
|
| + /* Array constructors are always contiguous and do not need packing. */
|
| + array_constructor = g77 && !this_array_result && expr->expr_type == EXPR_ARRAY;
|
| +
|
| + /* Same is true of contiguous sections from allocatable variables. */
|
| + good_allocatable = contiguous
|
| + && expr->symtree
|
| + && expr->symtree->n.sym->attr.allocatable;
|
| +
|
| + /* Or ultimate allocatable components. */
|
| + ultimate_alloc_comp = contiguous && ultimate_alloc_comp;
|
| +
|
| + if (no_pack || array_constructor || good_allocatable || ultimate_alloc_comp)
|
| + {
|
| + gfc_conv_expr_descriptor (se, expr, ss);
|
| + if (expr->ts.type == BT_CHARACTER)
|
| + se->string_length = expr->ts.u.cl->backend_decl;
|
| + if (size)
|
| + array_parameter_size (se->expr, expr, size);
|
| + se->expr = gfc_conv_array_data (se->expr);
|
| + return;
|
| + }
|
| +
|
| if (this_array_result)
|
| {
|
| /* Result of the enclosing function. */
|
| gfc_conv_expr_descriptor (se, expr, ss);
|
| - se->expr = build_fold_addr_expr (se->expr);
|
| + if (size)
|
| + array_parameter_size (se->expr, expr, size);
|
| + se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
|
|
|
| if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
|
| && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
|
| - se->expr = gfc_conv_array_data (build_fold_indirect_ref (se->expr));
|
| + se->expr = gfc_conv_array_data (build_fold_indirect_ref_loc (input_location,
|
| + se->expr));
|
|
|
| return;
|
| }
|
| @@ -5290,16 +5633,21 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
|
| /* Every other type of array. */
|
| se->want_pointer = 1;
|
| gfc_conv_expr_descriptor (se, expr, ss);
|
| + if (size)
|
| + array_parameter_size (build_fold_indirect_ref_loc (input_location,
|
| + se->expr),
|
| + expr, size);
|
| }
|
|
|
| /* Deallocate the allocatable components of structures that are
|
| not variable. */
|
| if (expr->ts.type == BT_DERIVED
|
| - && expr->ts.derived->attr.alloc_comp
|
| + && expr->ts.u.derived->attr.alloc_comp
|
| && expr->expr_type != EXPR_VARIABLE)
|
| {
|
| - tmp = build_fold_indirect_ref (se->expr);
|
| - tmp = gfc_deallocate_alloc_comp (expr->ts.derived, tmp, expr->rank);
|
| + tmp = build_fold_indirect_ref_loc (input_location,
|
| + se->expr);
|
| + tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp, expr->rank);
|
| gfc_add_expr_to_block (&se->post, tmp);
|
| }
|
|
|
| @@ -5307,7 +5655,6 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
|
| {
|
| desc = se->expr;
|
| /* Repack the array. */
|
| -
|
| if (gfc_option.warn_array_temp)
|
| {
|
| if (fsym)
|
| @@ -5317,7 +5664,8 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
|
| gfc_warning ("Creating array temporary at %L", &expr->where);
|
| }
|
|
|
| - ptr = build_call_expr (gfor_fndecl_in_pack, 1, desc);
|
| + ptr = build_call_expr_loc (input_location,
|
| + gfor_fndecl_in_pack, 1, desc);
|
|
|
| if (fsym && fsym->attr.optional && sym && sym->attr.optional)
|
| {
|
| @@ -5331,7 +5679,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
|
|
|
| se->expr = ptr;
|
|
|
| - if (gfc_option.flag_check_array_temporaries)
|
| + if (gfc_option.rtcheck & GFC_RTCHECK_ARRAY_TEMPS)
|
| {
|
| char * msg;
|
|
|
| @@ -5341,7 +5689,8 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
|
| else
|
| asprintf (&msg, "An array temporary was created");
|
|
|
| - tmp = build_fold_indirect_ref (desc);
|
| + tmp = build_fold_indirect_ref_loc (input_location,
|
| + desc);
|
| tmp = gfc_conv_array_data (tmp);
|
| tmp = fold_build2 (NE_EXPR, boolean_type_node,
|
| fold_convert (TREE_TYPE (tmp), ptr), tmp);
|
| @@ -5360,7 +5709,8 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
|
| /* Copy the data back. */
|
| if (fsym == NULL || fsym->attr.intent != INTENT_IN)
|
| {
|
| - tmp = build_call_expr (gfor_fndecl_in_unpack, 2, desc, ptr);
|
| + tmp = build_call_expr_loc (input_location,
|
| + gfor_fndecl_in_unpack, 2, desc, ptr);
|
| gfc_add_expr_to_block (&block, tmp);
|
| }
|
|
|
| @@ -5373,7 +5723,8 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
|
| gfc_init_block (&block);
|
| /* Only if it was repacked. This code needs to be executed before the
|
| loop cleanup code. */
|
| - tmp = build_fold_indirect_ref (desc);
|
| + tmp = build_fold_indirect_ref_loc (input_location,
|
| + desc);
|
| tmp = gfc_conv_array_data (tmp);
|
| tmp = fold_build2 (NE_EXPR, boolean_type_node,
|
| fold_convert (TREE_TYPE (tmp), ptr), tmp);
|
| @@ -5382,7 +5733,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
|
| tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
|
| gfc_conv_expr_present (sym), tmp);
|
|
|
| - tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
|
| + tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
|
|
|
| gfc_add_expr_to_block (&block, tmp);
|
| gfc_add_block_to_block (&block, &se->post);
|
| @@ -5431,23 +5782,25 @@ get_full_array_size (stmtblock_t *block, tree decl, int rank)
|
| tree nelems;
|
| tree tmp;
|
| idx = gfc_rank_cst[rank - 1];
|
| - nelems = gfc_conv_descriptor_ubound (decl, idx);
|
| - tmp = gfc_conv_descriptor_lbound (decl, idx);
|
| + nelems = gfc_conv_descriptor_ubound_get (decl, idx);
|
| + tmp = gfc_conv_descriptor_lbound_get (decl, idx);
|
| tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, nelems, tmp);
|
| tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
|
| tmp, gfc_index_one_node);
|
| tmp = gfc_evaluate_now (tmp, block);
|
|
|
| - nelems = gfc_conv_descriptor_stride (decl, idx);
|
| + nelems = gfc_conv_descriptor_stride_get (decl, idx);
|
| tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, nelems, tmp);
|
| return gfc_evaluate_now (tmp, block);
|
| }
|
|
|
|
|
| -/* Allocate dest to the same size as src, and copy src -> dest. */
|
| +/* Allocate dest to the same size as src, and copy src -> dest.
|
| + If no_malloc is set, only the copy is done. */
|
|
|
| -tree
|
| -gfc_duplicate_allocatable(tree dest, tree src, tree type, int rank)
|
| +static tree
|
| +duplicate_allocatable(tree dest, tree src, tree type, int rank,
|
| + bool no_malloc)
|
| {
|
| tree tmp;
|
| tree size;
|
| @@ -5456,34 +5809,66 @@ gfc_duplicate_allocatable(tree dest, tree src, tree type, int rank)
|
| tree null_data;
|
| stmtblock_t block;
|
|
|
| - /* If the source is null, set the destination to null. */
|
| + /* If the source is null, set the destination to null. Then,
|
| + allocate memory to the destination. */
|
| gfc_init_block (&block);
|
| - gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
|
| - null_data = gfc_finish_block (&block);
|
|
|
| - gfc_init_block (&block);
|
| + if (rank == 0)
|
| + {
|
| + tmp = null_pointer_node;
|
| + tmp = fold_build2 (MODIFY_EXPR, type, dest, tmp);
|
| + gfc_add_expr_to_block (&block, tmp);
|
| + null_data = gfc_finish_block (&block);
|
| +
|
| + gfc_init_block (&block);
|
| + size = TYPE_SIZE_UNIT (type);
|
| + if (!no_malloc)
|
| + {
|
| + tmp = gfc_call_malloc (&block, type, size);
|
| + tmp = fold_build2 (MODIFY_EXPR, void_type_node, dest,
|
| + fold_convert (type, tmp));
|
| + gfc_add_expr_to_block (&block, tmp);
|
| + }
|
| +
|
| + tmp = built_in_decls[BUILT_IN_MEMCPY];
|
| + tmp = build_call_expr_loc (input_location, tmp, 3,
|
| + dest, src, size);
|
| + }
|
| + else
|
| + {
|
| + gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
|
| + null_data = gfc_finish_block (&block);
|
| +
|
| + gfc_init_block (&block);
|
| + nelems = get_full_array_size (&block, src, rank);
|
| + tmp = fold_convert (gfc_array_index_type,
|
| + TYPE_SIZE_UNIT (gfc_get_element_type (type)));
|
| + size = fold_build2 (MULT_EXPR, gfc_array_index_type, nelems, tmp);
|
| + if (!no_malloc)
|
| + {
|
| + tmp = TREE_TYPE (gfc_conv_descriptor_data_get (src));
|
| + tmp = gfc_call_malloc (&block, tmp, size);
|
| + gfc_conv_descriptor_data_set (&block, dest, tmp);
|
| + }
|
| +
|
| + /* We know the temporary and the value will be the same length,
|
| + so can use memcpy. */
|
| + tmp = built_in_decls[BUILT_IN_MEMCPY];
|
| + tmp = build_call_expr_loc (input_location,
|
| + tmp, 3, gfc_conv_descriptor_data_get (dest),
|
| + gfc_conv_descriptor_data_get (src), size);
|
| + }
|
|
|
| - nelems = get_full_array_size (&block, src, rank);
|
| - size = fold_build2 (MULT_EXPR, gfc_array_index_type, nelems,
|
| - fold_convert (gfc_array_index_type,
|
| - TYPE_SIZE_UNIT (gfc_get_element_type (type))));
|
| -
|
| - /* Allocate memory to the destination. */
|
| - tmp = gfc_call_malloc (&block, TREE_TYPE (gfc_conv_descriptor_data_get (src)),
|
| - size);
|
| - gfc_conv_descriptor_data_set (&block, dest, tmp);
|
| -
|
| - /* We know the temporary and the value will be the same length,
|
| - so can use memcpy. */
|
| - tmp = built_in_decls[BUILT_IN_MEMCPY];
|
| - tmp = build_call_expr (tmp, 3, gfc_conv_descriptor_data_get (dest),
|
| - gfc_conv_descriptor_data_get (src), size);
|
| gfc_add_expr_to_block (&block, tmp);
|
| tmp = gfc_finish_block (&block);
|
|
|
| /* Null the destination if the source is null; otherwise do
|
| the allocate and copy. */
|
| - null_cond = gfc_conv_descriptor_data_get (src);
|
| + if (rank == 0)
|
| + null_cond = src;
|
| + else
|
| + null_cond = gfc_conv_descriptor_data_get (src);
|
| +
|
| null_cond = convert (pvoid_type_node, null_cond);
|
| null_cond = fold_build2 (NE_EXPR, boolean_type_node,
|
| null_cond, null_pointer_node);
|
| @@ -5491,11 +5876,30 @@ gfc_duplicate_allocatable(tree dest, tree src, tree type, int rank)
|
| }
|
|
|
|
|
| +/* Allocate dest to the same size as src, and copy data src -> dest. */
|
| +
|
| +tree
|
| +gfc_duplicate_allocatable (tree dest, tree src, tree type, int rank)
|
| +{
|
| + return duplicate_allocatable(dest, src, type, rank, false);
|
| +}
|
| +
|
| +
|
| +/* Copy data src -> dest. */
|
| +
|
| +tree
|
| +gfc_copy_allocatable_data (tree dest, tree src, tree type, int rank)
|
| +{
|
| + return duplicate_allocatable(dest, src, type, rank, true);
|
| +}
|
| +
|
| +
|
| /* Recursively traverse an object of derived type, generating code to
|
| deallocate, nullify or copy allocatable components. This is the work horse
|
| function for the functions named in this enum. */
|
|
|
| -enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP, COPY_ALLOC_COMP};
|
| +enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP, COPY_ALLOC_COMP,
|
| + COPY_ONLY_ALLOC_COMP};
|
|
|
| static tree
|
| structure_alloc_comps (gfc_symbol * der_type, tree decl,
|
| @@ -5518,8 +5922,9 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
|
|
|
| gfc_init_block (&fnblock);
|
|
|
| - if (POINTER_TYPE_P (TREE_TYPE (decl)))
|
| - decl = build_fold_indirect_ref (decl);
|
| + if (POINTER_TYPE_P (TREE_TYPE (decl)) && rank != 0)
|
| + decl = build_fold_indirect_ref_loc (input_location,
|
| + decl);
|
|
|
| /* If this an array of derived types with allocatable components
|
| build a loop and recursively call this function. */
|
| @@ -5527,7 +5932,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
|
| || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
|
| {
|
| tmp = gfc_conv_array_data (decl);
|
| - var = build_fold_indirect_ref (tmp);
|
| + var = build_fold_indirect_ref_loc (input_location,
|
| + tmp);
|
|
|
| /* Get the number of elements - 1 and set the counter. */
|
| if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
|
| @@ -5566,10 +5972,19 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
|
| tmp = gfc_duplicate_allocatable (dest, decl, TREE_TYPE(decl), rank);
|
| gfc_add_expr_to_block (&fnblock, tmp);
|
| }
|
| - tmp = build_fold_indirect_ref (gfc_conv_array_data (dest));
|
| + tmp = build_fold_indirect_ref_loc (input_location,
|
| + gfc_conv_array_data (dest));
|
| dref = gfc_build_array_ref (tmp, index, NULL);
|
| tmp = structure_alloc_comps (der_type, vref, dref, rank, purpose);
|
| }
|
| + else if (purpose == COPY_ONLY_ALLOC_COMP)
|
| + {
|
| + tmp = build_fold_indirect_ref_loc (input_location,
|
| + gfc_conv_array_data (dest));
|
| + dref = gfc_build_array_ref (tmp, index, NULL);
|
| + tmp = structure_alloc_comps (der_type, vref, dref, rank,
|
| + COPY_ALLOC_COMP);
|
| + }
|
| else
|
| tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose);
|
|
|
| @@ -5586,7 +6001,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
|
|
|
| tmp = gfc_finish_block (&fnblock);
|
| if (null_cond != NULL_TREE)
|
| - tmp = build3_v (COND_EXPR, null_cond, tmp, build_empty_stmt ());
|
| + tmp = build3_v (COND_EXPR, null_cond, tmp,
|
| + build_empty_stmt (input_location));
|
|
|
| return tmp;
|
| }
|
| @@ -5596,7 +6012,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
|
| for (c = der_type->components; c; c = c->next)
|
| {
|
| bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED)
|
| - && c->ts.derived->attr.alloc_comp;
|
| + && c->ts.u.derived->attr.alloc_comp;
|
| cdecl = c->backend_decl;
|
| ctype = TREE_TYPE (cdecl);
|
|
|
| @@ -5610,35 +6026,86 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
|
| comp = fold_build3 (COMPONENT_REF, ctype,
|
| decl, cdecl, NULL_TREE);
|
| rank = c->as ? c->as->rank : 0;
|
| - tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
|
| + tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
|
| rank, purpose);
|
| gfc_add_expr_to_block (&fnblock, tmp);
|
| }
|
|
|
| - if (c->attr.allocatable)
|
| + if (c->attr.allocatable && c->attr.dimension)
|
| {
|
| comp = fold_build3 (COMPONENT_REF, ctype,
|
| decl, cdecl, NULL_TREE);
|
| tmp = gfc_trans_dealloc_allocated (comp);
|
| gfc_add_expr_to_block (&fnblock, tmp);
|
| }
|
| + else if (c->attr.allocatable)
|
| + {
|
| + /* Allocatable scalar components. */
|
| + comp = fold_build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
|
| +
|
| + tmp = gfc_deallocate_with_status (comp, NULL_TREE, true, NULL);
|
| + gfc_add_expr_to_block (&fnblock, tmp);
|
| +
|
| + tmp = fold_build2 (MODIFY_EXPR, void_type_node, comp,
|
| + build_int_cst (TREE_TYPE (comp), 0));
|
| + gfc_add_expr_to_block (&fnblock, tmp);
|
| + }
|
| + else if (c->ts.type == BT_CLASS
|
| + && c->ts.u.derived->components->attr.allocatable)
|
| + {
|
| + /* Allocatable scalar CLASS components. */
|
| + comp = fold_build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
|
| +
|
| + /* Add reference to '$data' component. */
|
| + tmp = c->ts.u.derived->components->backend_decl;
|
| + comp = fold_build3 (COMPONENT_REF, TREE_TYPE (tmp),
|
| + comp, tmp, NULL_TREE);
|
| +
|
| + tmp = gfc_deallocate_with_status (comp, NULL_TREE, true, NULL);
|
| + gfc_add_expr_to_block (&fnblock, tmp);
|
| +
|
| + tmp = fold_build2 (MODIFY_EXPR, void_type_node, comp,
|
| + build_int_cst (TREE_TYPE (comp), 0));
|
| + gfc_add_expr_to_block (&fnblock, tmp);
|
| + }
|
| break;
|
|
|
| case NULLIFY_ALLOC_COMP:
|
| if (c->attr.pointer)
|
| continue;
|
| - else if (c->attr.allocatable)
|
| + else if (c->attr.allocatable && c->attr.dimension)
|
| {
|
| comp = fold_build3 (COMPONENT_REF, ctype,
|
| decl, cdecl, NULL_TREE);
|
| gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
|
| }
|
| + else if (c->attr.allocatable)
|
| + {
|
| + /* Allocatable scalar components. */
|
| + comp = fold_build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
|
| + tmp = fold_build2 (MODIFY_EXPR, void_type_node, comp,
|
| + build_int_cst (TREE_TYPE (comp), 0));
|
| + gfc_add_expr_to_block (&fnblock, tmp);
|
| + }
|
| + else if (c->ts.type == BT_CLASS
|
| + && c->ts.u.derived->components->attr.allocatable)
|
| + {
|
| + /* Allocatable scalar CLASS components. */
|
| + comp = fold_build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
|
| + /* Add reference to '$data' component. */
|
| + tmp = c->ts.u.derived->components->backend_decl;
|
| + comp = fold_build3 (COMPONENT_REF, TREE_TYPE (tmp),
|
| + comp, tmp, NULL_TREE);
|
| + tmp = fold_build2 (MODIFY_EXPR, void_type_node, comp,
|
| + build_int_cst (TREE_TYPE (comp), 0));
|
| + gfc_add_expr_to_block (&fnblock, tmp);
|
| + }
|
| else if (cmp_has_alloc_comps)
|
| {
|
| comp = fold_build3 (COMPONENT_REF, ctype,
|
| decl, cdecl, NULL_TREE);
|
| rank = c->as ? c->as->rank : 0;
|
| - tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
|
| + tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
|
| rank, purpose);
|
| gfc_add_expr_to_block (&fnblock, tmp);
|
| }
|
| @@ -5655,7 +6122,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
|
|
|
| if (c->attr.allocatable && !cmp_has_alloc_comps)
|
| {
|
| - tmp = gfc_duplicate_allocatable(dcmp, comp, ctype, c->as->rank);
|
| + rank = c->as ? c->as->rank : 0;
|
| + tmp = gfc_duplicate_allocatable(dcmp, comp, ctype, rank);
|
| gfc_add_expr_to_block (&fnblock, tmp);
|
| }
|
|
|
| @@ -5664,7 +6132,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
|
| rank = c->as ? c->as->rank : 0;
|
| tmp = fold_convert (TREE_TYPE (dcmp), comp);
|
| gfc_add_modify (&fnblock, dcmp, tmp);
|
| - tmp = structure_alloc_comps (c->ts.derived, comp, dcmp,
|
| + tmp = structure_alloc_comps (c->ts.u.derived, comp, dcmp,
|
| rank, purpose);
|
| gfc_add_expr_to_block (&fnblock, tmp);
|
| }
|
| @@ -5702,7 +6170,7 @@ gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
|
|
|
|
|
| /* Recursively traverse an object of derived type, generating code to
|
| - copy its allocatable components. */
|
| + copy it and its allocatable components. */
|
|
|
| tree
|
| gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
|
| @@ -5711,6 +6179,16 @@ gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
|
| }
|
|
|
|
|
| +/* Recursively traverse an object of derived type, generating code to
|
| + copy only its allocatable components. */
|
| +
|
| +tree
|
| +gfc_copy_only_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
|
| +{
|
| + return structure_alloc_comps (der_type, decl, dest, rank, COPY_ONLY_ALLOC_COMP);
|
| +}
|
| +
|
| +
|
| /* NULLIFY an allocatable/pointer array on function entry, free it on exit.
|
| Do likewise, recursively if necessary, with the allocatable components of
|
| derived types. */
|
| @@ -5727,7 +6205,7 @@ gfc_trans_deferred_array (gfc_symbol * sym, tree body)
|
| bool sym_has_alloc_comp;
|
|
|
| sym_has_alloc_comp = (sym->ts.type == BT_DERIVED)
|
| - && sym->ts.derived->attr.alloc_comp;
|
| + && sym->ts.u.derived->attr.alloc_comp;
|
|
|
| /* Make sure the frontend gets these right. */
|
| if (!(sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp))
|
| @@ -5741,14 +6219,14 @@ gfc_trans_deferred_array (gfc_symbol * sym, tree body)
|
| || TREE_CODE (sym->backend_decl) == PARM_DECL);
|
|
|
| if (sym->ts.type == BT_CHARACTER
|
| - && !INTEGER_CST_P (sym->ts.cl->backend_decl))
|
| + && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
|
| {
|
| - gfc_conv_string_length (sym->ts.cl, NULL, &fnblock);
|
| + gfc_conv_string_length (sym->ts.u.cl, NULL, &fnblock);
|
| gfc_trans_vla_type_sizes (sym, &fnblock);
|
| }
|
|
|
| - /* Dummy and use associated variables don't need anything special. */
|
| - if (sym->attr.dummy || sym->attr.use_assoc)
|
| + /* Dummy, use associated and result variables don't need anything special. */
|
| + if (sym->attr.dummy || sym->attr.use_assoc || sym->attr.result)
|
| {
|
| gfc_add_expr_to_block (&fnblock, body);
|
|
|
| @@ -5777,7 +6255,7 @@ gfc_trans_deferred_array (gfc_symbol * sym, tree body)
|
| if (!sym->attr.save)
|
| {
|
| rank = sym->as ? sym->as->rank : 0;
|
| - tmp = gfc_nullify_alloc_comp (sym->ts.derived, descriptor, rank);
|
| + tmp = gfc_nullify_alloc_comp (sym->ts.u.derived, descriptor, rank);
|
| gfc_add_expr_to_block (&fnblock, tmp);
|
| if (sym->value)
|
| {
|
| @@ -5790,7 +6268,8 @@ gfc_trans_deferred_array (gfc_symbol * sym, tree body)
|
| {
|
| /* If the backend_decl is not a descriptor, we must have a pointer
|
| to one. */
|
| - descriptor = build_fold_indirect_ref (sym->backend_decl);
|
| + descriptor = build_fold_indirect_ref_loc (input_location,
|
| + sym->backend_decl);
|
| type = TREE_TYPE (descriptor);
|
| }
|
|
|
| @@ -5809,11 +6288,12 @@ gfc_trans_deferred_array (gfc_symbol * sym, tree body)
|
| {
|
| int rank;
|
| rank = sym->as ? sym->as->rank : 0;
|
| - tmp = gfc_deallocate_alloc_comp (sym->ts.derived, descriptor, rank);
|
| + tmp = gfc_deallocate_alloc_comp (sym->ts.u.derived, descriptor, rank);
|
| gfc_add_expr_to_block (&fnblock, tmp);
|
| }
|
|
|
| - if (sym->attr.allocatable && !sym->attr.save && !sym->attr.result)
|
| + if (sym->attr.allocatable && sym->attr.dimension
|
| + && !sym->attr.save && !sym->attr.result)
|
| {
|
| tmp = gfc_trans_dealloc_allocated (sym->backend_decl);
|
| gfc_add_expr_to_block (&fnblock, tmp);
|
| @@ -5843,7 +6323,6 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
|
| gfc_ref *ref;
|
| gfc_array_ref *ar;
|
| gfc_ss *newss;
|
| - gfc_ss *head;
|
| int n;
|
|
|
| for (ref = expr->ref; ref; ref = ref->next)
|
| @@ -5916,8 +6395,6 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
|
| newss->data.info.dimen = 0;
|
| newss->data.info.ref = ref;
|
|
|
| - head = newss;
|
| -
|
| /* We add SS chains for all the subscripts in the section. */
|
| for (n = 0; n < ar->dimen; n++)
|
| {
|
| @@ -6121,6 +6598,7 @@ gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
|
| gfc_ss *newss;
|
| gfc_intrinsic_sym *isym;
|
| gfc_symbol *sym;
|
| + gfc_component *comp = NULL;
|
|
|
| isym = expr->value.function.isym;
|
|
|
| @@ -6133,7 +6611,9 @@ gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
|
| sym = expr->symtree->n.sym;
|
|
|
| /* A function that returns arrays. */
|
| - if (gfc_return_by_reference (sym) && sym->result->attr.dimension)
|
| + gfc_is_proc_ptr_comp (expr, &comp);
|
| + if ((!comp && gfc_return_by_reference (sym) && sym->result->attr.dimension)
|
| + || (comp && comp->attr.dimension))
|
| {
|
| newss = gfc_get_ss ();
|
| newss->type = GFC_SS_FUNCTION;
|
|
|