diff options
Diffstat (limited to 'gcc/fortran/trans-array.c')
-rw-r--r-- | gcc/fortran/trans-array.c | 125 |
1 files changed, 67 insertions, 58 deletions
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index 06898920369..794322ac79a 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -1,6 +1,6 @@ /* Array translation routines Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011, 2012 + 2011, 2012, 2013 Free Software Foundation, Inc. Contributed by Paul Brook <paul@nowt.org> and Steven Bosscher <s.bosscher@student.tudelft.nl> @@ -159,7 +159,7 @@ gfc_conv_descriptor_data_get (tree desc) /* This provides WRITE access to the data field. TUPLES_P is true if we are generating tuples. - + This function gets called through the following macros: gfc_conv_descriptor_data_set gfc_conv_descriptor_data_set. */ @@ -593,7 +593,7 @@ gfc_get_temp_ss (tree type, tree string_length, int dimen) return ss; } - + /* Creates and initializes a scalar type gfc_ss struct. */ @@ -1363,7 +1363,7 @@ gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset, /* Variables needed for bounds-checking. */ static bool first_len; -static tree first_len_val; +static tree first_len_val; static bool typespec_chararray_ctor; static void @@ -2206,7 +2206,7 @@ trans_array_constructor (gfc_ss * ss, locus * where) if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && expr->ts.type == BT_CHARACTER && !typespec_chararray_ctor) - { + { first_len_val = gfc_create_var (gfc_charlen_type_node, "len"); first_len = true; } @@ -2217,7 +2217,7 @@ trans_array_constructor (gfc_ss * ss, locus * where) if (expr->ts.type == BT_CHARACTER) { bool const_string; - + /* 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. */ @@ -2924,9 +2924,9 @@ conv_array_index_offset (gfc_se * se, gfc_ss * ss, int dim, int i, gcc_assert (se->loop); index = se->loop->loopvar[se->loop->order[i]]; - /* Pointer functions can have stride[0] different from unity. + /* Pointer functions can have stride[0] different from unity. Use the stride returned by the function call and stored in - the descriptor for the temporary. */ + the descriptor for the temporary. */ if (se->ss && se->ss->info->type == GFC_SS_FUNCTION && se->ss->info->expr && se->ss->info->expr->symtree @@ -2986,7 +2986,7 @@ build_class_array_ref (gfc_se *se, tree base, tree index) ts = &ref->u.c.component->ts; class_ref = ref; break; - } + } } if (ts == NULL) @@ -3099,31 +3099,40 @@ static tree build_array_ref (tree desc, tree offset, tree decl) { tree tmp; + tree type; - /* Class array references need special treatment because the assigned - type size needs to be used to point to the element. */ + /* Class container types do not always have the GFC_CLASS_TYPE_P + but the canonical type does. */ if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)) - && TREE_CODE (desc) == COMPONENT_REF - && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (desc, 0)))) + && TREE_CODE (desc) == COMPONENT_REF) { - tree type = gfc_get_element_type (TREE_TYPE (desc)); - tmp = TREE_OPERAND (desc, 0); - tmp = gfc_get_class_array_ref (offset, tmp); - tmp = fold_convert (build_pointer_type (type), tmp); - tmp = build_fold_indirect_ref_loc (input_location, tmp); + type = TREE_TYPE (TREE_OPERAND (desc, 0)); + if (TYPE_CANONICAL (type) + && GFC_CLASS_TYPE_P (TYPE_CANONICAL (type))) + type = TYPE_CANONICAL (type); } else + type = NULL; + + /* Class array references need special treatment because the assigned + type size needs to be used to point to the element. */ + if (type && GFC_CLASS_TYPE_P (type)) { - tmp = gfc_conv_array_data (desc); + type = gfc_get_element_type (TREE_TYPE (desc)); + tmp = TREE_OPERAND (desc, 0); + tmp = gfc_get_class_array_ref (offset, tmp); + tmp = fold_convert (build_pointer_type (type), tmp); tmp = build_fold_indirect_ref_loc (input_location, tmp); - tmp = gfc_build_array_ref (tmp, offset, decl); + return tmp; } + tmp = gfc_conv_array_data (desc); + tmp = build_fold_indirect_ref_loc (input_location, tmp); + tmp = gfc_build_array_ref (tmp, offset, decl); return tmp; } - /* Build an array reference. se->expr already holds the array descriptor. This should be either a variable, indirect variable reference or component reference. For arrays which do not have a descriptor, se->expr will be @@ -3202,7 +3211,7 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym, tmp = tmpse.expr; } - cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, + cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, indexse.expr, tmp); asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' " "below lower bound of %%ld", n+1, sym->name); @@ -3964,8 +3973,8 @@ done: 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. - If upper bound is present, include both bounds in the + 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) { @@ -4012,7 +4021,7 @@ done: fold_convert (long_integer_type_node, lbound)); 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. */ @@ -4041,12 +4050,12 @@ done: gfc_trans_runtime_check (true, false, tmp2, &inner, expr_loc, msg, fold_convert (long_integer_type_node, tmp), - fold_convert (long_integer_type_node, ubound), + fold_convert (long_integer_type_node, ubound), fold_convert (long_integer_type_node, lbound)); gfc_trans_runtime_check (true, false, tmp3, &inner, expr_loc, msg, fold_convert (long_integer_type_node, tmp), - fold_convert (long_integer_type_node, ubound), + fold_convert (long_integer_type_node, ubound), fold_convert (long_integer_type_node, lbound)); free (msg); } @@ -4885,7 +4894,7 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset, ubound = lower[n]; } } - gfc_conv_descriptor_lbound_set (descriptor_block, descriptor, + gfc_conv_descriptor_lbound_set (descriptor_block, descriptor, gfc_rank_cst[n], se.expr); conv_lbound = se.expr; @@ -4916,11 +4925,11 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset, /* Check whether multiplying the stride by the number of elements in this dimension would overflow. We must also check whether the current dimension has zero size in order to avoid - division by zero. + division by zero. */ - tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, - gfc_array_index_type, - fold_convert (gfc_array_index_type, + tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, + gfc_array_index_type, + fold_convert (gfc_array_index_type, TYPE_MAX_VALUE (gfc_array_index_type)), size); cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR, @@ -4935,7 +4944,7 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset, tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node, *overflow, tmp); *overflow = gfc_evaluate_now (tmp, pblock); - + /* Multiply the stride by the number of elements in this dimension. */ stride = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, stride, size); @@ -4966,7 +4975,7 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset, ubound = lower[n]; } } - gfc_conv_descriptor_lbound_set (descriptor_block, descriptor, + gfc_conv_descriptor_lbound_set (descriptor_block, descriptor, gfc_rank_cst[n], se.expr); if (n < rank + corank - 1) @@ -5019,7 +5028,7 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset, /* First check for overflow. Since an array of type character can have zero element_size, we must check for that before dividing. */ - tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, + tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, size_type_node, TYPE_MAX_VALUE (size_type_node), element_size); cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR, @@ -5210,7 +5219,7 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg, { cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR, boolean_type_node, var_overflow, integer_zero_node)); - tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, + tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, error, gfc_finish_block (&elseblock)); } else @@ -5221,7 +5230,7 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg, if (expr->ts.type == BT_CLASS) { tmp = build_int_cst (unsigned_char_type_node, 0); - /* With class objects, it is best to play safe and null the + /* With class objects, it is best to play safe and null the memory because we cannot know if dynamic types have allocatable components or not. */ tmp = build_call_expr_loc (input_location, @@ -5233,7 +5242,7 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg, /* Update the array descriptors. */ if (dimension) gfc_conv_descriptor_offset_set (&set_descriptor_block, se->expr, offset); - + set_descriptor = gfc_finish_block (&set_descriptor_block); if (status != NULL_TREE) { @@ -5243,7 +5252,7 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg, gfc_add_expr_to_block (&se->pre, fold_build3_loc (input_location, COND_EXPR, void_type_node, gfc_likely (cond), set_descriptor, - build_empty_stmt (input_location))); + build_empty_stmt (input_location))); } else gfc_add_expr_to_block (&se->pre, set_descriptor); @@ -5331,7 +5340,7 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr) /* A single scalar or derived type value. Create an array with all elements equal to that value. */ gfc_init_se (&se, NULL); - + if (expr->expr_type == EXPR_CONSTANT) gfc_conv_constant (&se, expr); else @@ -5743,7 +5752,7 @@ gfc_trans_g77_array (gfc_symbol * sym, gfc_wrapped_block * block) tmp = gfc_conv_expr_present (sym); stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location)); } - + gfc_add_init_cleanup (block, stmt, NULL_TREE); } @@ -5945,7 +5954,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, asprintf (&msg, "Dimension %d of array '%s' has extent " "%%ld instead of %%ld", n+1, sym->name); - gfc_trans_runtime_check (true, false, tmp, &init, &loc, msg, + gfc_trans_runtime_check (true, false, tmp, &init, &loc, msg, fold_convert (long_integer_type_node, temp), fold_convert (long_integer_type_node, stride2)); @@ -6069,7 +6078,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, gfc_add_expr_to_block (&cleanup, tmp); stmtCleanup = gfc_finish_block (&cleanup); - + /* Only do the cleanup if the array was repacked. */ tmp = build_fold_indirect_ref_loc (input_location, dumdesc); tmp = gfc_conv_descriptor_data_get (tmp); @@ -6381,7 +6390,7 @@ walk_coarray (gfc_expr *e) EXPR is the right-hand side of a pointer assignment and se->expr is the descriptor for the previously-evaluated left-hand side. The function creates an assignment from - EXPR to se->expr. + EXPR to se->expr. The se->force_tmp flag disables the non-copying descriptor optimization @@ -6495,7 +6504,7 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr) return; } break; - + case EXPR_FUNCTION: /* A transformational function return value will be a temporary array descriptor. We still need to go through the scalarizer @@ -6785,7 +6794,7 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr) /* Vector subscripts need copying and are handled elsewhere. */ if (info->ref) gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE); - + /* look for the corresponding scalarizer dimension: dim. */ for (dim = 0; dim < ndim; dim++) if (ss->dim[dim] == n) @@ -7011,9 +7020,9 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77, if (!sym->attr.pointer && sym->as - && sym->as->type != AS_ASSUMED_SHAPE + && sym->as->type != AS_ASSUMED_SHAPE && sym->as->type != AS_DEFERRED - && sym->as->type != AS_ASSUMED_RANK + && sym->as->type != AS_ASSUMED_RANK && !sym->attr.allocatable) { /* Some variables are declared directly, others are declared as @@ -7071,7 +7080,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77, && expr->symtree->n.sym->attr.allocatable; /* Or ultimate allocatable components. */ - ultimate_alloc_comp = contiguous && ultimate_alloc_comp; + ultimate_alloc_comp = contiguous && ultimate_alloc_comp; if (no_pack || array_constructor || good_allocatable || ultimate_alloc_comp) { @@ -7254,7 +7263,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77, tree gfc_trans_dealloc_allocated (tree descriptor, bool coarray) -{ +{ tree tmp; tree var; stmtblock_t block; @@ -7454,7 +7463,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, tmp = gfc_conv_array_data (decl); var = build_fold_indirect_ref_loc (input_location, tmp); - + /* Get the number of elements - 1 and set the counter. */ if (GFC_DESCRIPTOR_TYPE_P (decl_type)) { @@ -7578,7 +7587,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, /* Allocatable CLASS components. */ comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, decl, cdecl, NULL_TREE); - + /* Add reference to '_data' component. */ tmp = CLASS_DATA (c)->backend_decl; comp = fold_build3_loc (input_location, COMPONENT_REF, @@ -7725,7 +7734,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, null_cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, src_data, - null_pointer_node); + null_pointer_node); gfc_add_expr_to_block (&fnblock, build3_v (COND_EXPR, null_cond, tmp, null_data)); @@ -8030,7 +8039,7 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, as = NULL; /* If the lhs shape is not the same as the rhs jump to setting the - bounds and doing the reallocation....... */ + bounds and doing the reallocation....... */ for (n = 0; n < expr1->rank; n++) { /* Check the shape. */ @@ -8051,13 +8060,13 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, tmp = build3_v (COND_EXPR, cond, build1_v (GOTO_EXPR, jump_label1), build_empty_stmt (input_location)); - gfc_add_expr_to_block (&fblock, tmp); + gfc_add_expr_to_block (&fblock, tmp); } /* ....else jump past the (re)alloc code. */ tmp = build1_v (GOTO_EXPR, jump_label2); gfc_add_expr_to_block (&fblock, tmp); - + /* Add the label to start automatic (re)allocation. */ tmp = build1_v (LABEL_EXPR, jump_label1); gfc_add_expr_to_block (&fblock, tmp); @@ -8096,7 +8105,7 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, unallocated allocatable variable, then it is allocated with each deferred type parameter equal to the corresponding type parameters of expr , with the shape of expr , and with each lower bound equal - to the corresponding element of LBOUND(expr)." + to the corresponding element of LBOUND(expr)." Reuse size1 to keep a dimension-by-dimension track of the stride of the new array. */ size1 = gfc_index_one_node; @@ -8340,7 +8349,7 @@ gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block) sym->backend_decl); type = TREE_TYPE (descriptor); } - + /* NULLIFY the data pointer. */ if (GFC_DESCRIPTOR_TYPE_P (type) && !sym->attr.save) gfc_conv_descriptor_data_set (&init, descriptor, null_pointer_node); |