https://gcc.gnu.org/g:a3f1cdd8ed46f9816b31ab162ae4dac547d34ebc
commit r15-2934-ga3f1cdd8ed46f9816b31ab162ae4dac547d34ebc Author: Andre Vehreschild <ve...@gcc.gnu.org> Date: Fri Aug 9 12:47:18 2024 +0200 Add corank to gfc_expr. Compute the corank of an expression along side to the regular rank. This safe costly calls to gfc_get_corank (), which consecutively has been removed. In some locations the code needed some adaption to model the difference between expr.corank and gfc_get_corank correctly. The latter always returned the codimension of the expression and not its current corank, i.e. the resolution of all indezes. This commit is preparatory to fixing PR fortran/110033 and may contain parts of that fix already. gcc/fortran/ChangeLog: * arith.cc (reduce_unary): Use expr.corank. (reduce_binary_ac): Same. (reduce_binary_ca): Same. (reduce_binary_aa): Same. * array.cc (gfc_match_array_ref): Same. * check.cc (dim_corank_check): Same. (gfc_check_move_alloc): Same. (gfc_check_image_index): Same. * class.cc (gfc_add_class_array_ref): Same. (finalize_component): Same. * data.cc (gfc_assign_data_value): Same. * decl.cc (match_clist_expr): Same. (add_init_expr_to_sym): Same. * expr.cc (simplify_intrinsic_op): Same. (simplify_parameter_variable): Same. (gfc_check_assign_symbol): Same. (gfc_get_variable_expr): Same. (gfc_add_full_array_ref): Same. (gfc_lval_expr_from_sym): Same. (gfc_get_corank): Removed. * frontend-passes.cc (callback_reduction): Use expr.corank. (create_var): Same. (combine_array_constructor): Same. (optimize_minmaxloc): Same. * gfortran.h (gfc_get_corank): Add corank to gfc_expr. * intrinsic.cc (gfc_get_intrinsic_function_symbol): Use expr.corank. (gfc_convert_type_warn): Same. (gfc_convert_chartype): Same. * iresolve.cc (resolve_bound): Same. (gfc_resolve_cshift): Same. (gfc_resolve_eoshift): Same. (gfc_resolve_logical): Same. (gfc_resolve_matmul): Same. * match.cc (copy_ts_from_selector_to_associate): Same. * matchexp.cc (gfc_get_parentheses): Same. * parse.cc (parse_associate): Same. * primary.cc (gfc_match_rvalue): Same. * resolve.cc (resolve_structure_cons): Same. (resolve_actual_arglist): Same. (resolve_elemental_actual): Same. (resolve_generic_f0): Same. (resolve_unknown_f): Same. (resolve_operator): Same. (gfc_expression_rank): Same and set dimen_type for coarray to default. (gfc_op_rank_conformable): Use expr.corank. (add_caf_get_intrinsic): Same. (resolve_variable): Same. (gfc_fixup_inferred_type_refs): Same. (check_host_association): Same. (resolve_compcall): Same. (resolve_expr_ppc): Same. (resolve_assoc_var): Same. (fixup_array_ref): Same. (resolve_select_type): Same. (add_comp_ref): Same. (get_temp_from_expr): Same. (resolve_fl_var_and_proc): Same. (resolve_symbol): Same. * symbol.cc (gfc_is_associate_pointer): Same. * trans-array.cc (walk_coarray): Same. (gfc_conv_expr_descriptor): Same. (gfc_walk_array_ref): Same. * trans-array.h (gfc_walk_array_ref): Same. * trans-expr.cc (gfc_get_ultimate_alloc_ptr_comps_caf_token): Same. * trans-intrinsic.cc (trans_this_image): Same. (trans_image_index): Same. (conv_intrinsic_cobound): Same. (gfc_walk_intrinsic_function): Same. (conv_intrinsic_move_alloc): Same. * trans-stmt.cc (gfc_trans_lock_unlock): Same. (trans_associate_var): Same and adapt to slightly different behaviour of expr.corank and gfc_get_corank. (gfc_trans_allocate): Same. * trans.cc (gfc_add_finalizer_call): Same. Diff: --- gcc/fortran/arith.cc | 4 + gcc/fortran/array.cc | 16 ++- gcc/fortran/check.cc | 18 +-- gcc/fortran/class.cc | 3 + gcc/fortran/data.cc | 1 + gcc/fortran/decl.cc | 2 + gcc/fortran/expr.cc | 51 +++------ gcc/fortran/frontend-passes.cc | 5 + gcc/fortran/gfortran.h | 2 +- gcc/fortran/intrinsic.cc | 3 + gcc/fortran/iresolve.cc | 20 +++- gcc/fortran/match.cc | 30 +++-- gcc/fortran/matchexp.cc | 1 + gcc/fortran/parse.cc | 39 ++++--- gcc/fortran/primary.cc | 10 +- gcc/fortran/resolve.cc | 243 ++++++++++++++++++++++++++++++++--------- gcc/fortran/symbol.cc | 3 +- gcc/fortran/trans-array.cc | 33 ++++-- gcc/fortran/trans-array.h | 3 +- gcc/fortran/trans-expr.cc | 7 +- gcc/fortran/trans-intrinsic.cc | 12 +- gcc/fortran/trans-stmt.cc | 133 +++++++++++++--------- gcc/fortran/trans.cc | 11 +- 23 files changed, 450 insertions(+), 200 deletions(-) diff --git a/gcc/fortran/arith.cc b/gcc/fortran/arith.cc index b373c25e5e1..19916c105ad 100644 --- a/gcc/fortran/arith.cc +++ b/gcc/fortran/arith.cc @@ -1393,6 +1393,7 @@ reduce_unary (arith (*eval) (gfc_expr *, gfc_expr **), gfc_expr *op, } r->shape = gfc_copy_shape (op->shape, op->rank); r->rank = op->rank; + r->corank = op->corank; r->value.constructor = head; *result = r; } @@ -1456,6 +1457,7 @@ reduce_binary_ac (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **), r->shape = gfc_get_shape (op1->rank); } r->rank = op1->rank; + r->corank = op1->corank; r->value.constructor = head; *result = r; } @@ -1519,6 +1521,7 @@ reduce_binary_ca (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **), r->shape = gfc_get_shape (op2->rank); } r->rank = op2->rank; + r->corank = op2->corank; r->value.constructor = head; *result = r; } @@ -1585,6 +1588,7 @@ reduce_binary_aa (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **), } r->shape = gfc_copy_shape (op1->shape, op1->rank); r->rank = op1->rank; + r->corank = op1->corank; r->value.constructor = head; *result = r; } diff --git a/gcc/fortran/array.cc b/gcc/fortran/array.cc index a5e94f1fa77..1fa61ebfe2a 100644 --- a/gcc/fortran/array.cc +++ b/gcc/fortran/array.cc @@ -203,6 +203,12 @@ gfc_match_array_ref (gfc_array_ref *ar, gfc_array_spec *as, int init, { ar->type = AR_FULL; ar->dimen = 0; + if (corank != 0) + { + for (int i = 0; i < GFC_MAX_DIMENSIONS; ++i) + ar->dimen_type[i] = DIMEN_THIS_IMAGE; + ar->codimen = corank; + } return MATCH_YES; } @@ -238,7 +244,15 @@ coarray: if (!matched_bracket && gfc_match_char ('[') != MATCH_YES) { if (ar->dimen > 0) - return MATCH_YES; + { + if (corank != 0) + { + for (int i = ar->dimen; i < GFC_MAX_DIMENSIONS; ++i) + ar->dimen_type[i] = DIMEN_THIS_IMAGE; + ar->codimen = corank; + } + return MATCH_YES; + } else return MATCH_ERROR; } diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc index 2f50d84b876..ee1e7417f38 100644 --- a/gcc/fortran/check.cc +++ b/gcc/fortran/check.cc @@ -1075,8 +1075,6 @@ dim_check (gfc_expr *dim, int n, bool optional) static bool dim_corank_check (gfc_expr *dim, gfc_expr *array) { - int corank; - gcc_assert (array->expr_type == EXPR_VARIABLE); if (dim->expr_type != EXPR_CONSTANT) @@ -1085,10 +1083,8 @@ dim_corank_check (gfc_expr *dim, gfc_expr *array) if (array->ts.type == BT_CLASS) return true; - corank = gfc_get_corank (array); - if (mpz_cmp_ui (dim->value.integer, 1) < 0 - || mpz_cmp_ui (dim->value.integer, corank) > 0) + || mpz_cmp_ui (dim->value.integer, array->corank) > 0) { gfc_error ("%<dim%> argument of %qs intrinsic at %L is not a valid " "codimension index", gfc_current_intrinsic, &dim->where); @@ -4269,11 +4265,11 @@ gfc_check_move_alloc (gfc_expr *from, gfc_expr *to) } /* IR F08/0040; cf. 12-006A. */ - if (gfc_get_corank (to) != gfc_get_corank (from)) + if (to->corank != from->corank) { gfc_error ("The FROM and TO arguments of the MOVE_ALLOC intrinsic at %L " - "must have the same corank %d/%d", &to->where, - gfc_get_corank (from), gfc_get_corank (to)); + "must have the same corank %d/%d", + &to->where, from->corank, to->corank); return false; } @@ -5996,13 +5992,11 @@ gfc_check_image_index (gfc_expr *coarray, gfc_expr *sub) if (gfc_array_size (sub, &nelems)) { - int corank = gfc_get_corank (coarray); - - if (mpz_cmp_ui (nelems, corank) != 0) + if (mpz_cmp_ui (nelems, coarray->corank) != 0) { gfc_error ("The number of array elements of the SUB argument to " "IMAGE_INDEX at %L shall be %d (corank) not %d", - &sub->where, corank, (int) mpz_get_si (nelems)); + &sub->where, coarray->corank, (int) mpz_get_si (nelems)); mpz_clear (nelems); return false; } diff --git a/gcc/fortran/class.cc b/gcc/fortran/class.cc index b9dcc0a3d98..88fbba2818a 100644 --- a/gcc/fortran/class.cc +++ b/gcc/fortran/class.cc @@ -264,10 +264,12 @@ void gfc_add_class_array_ref (gfc_expr *e) { int rank = CLASS_DATA (e)->as->rank; + int corank = CLASS_DATA (e)->as->corank; gfc_array_spec *as = CLASS_DATA (e)->as; gfc_ref *ref = NULL; gfc_add_data_component (e); e->rank = rank; + e->corank = corank; for (ref = e->ref; ref; ref = ref->next) if (!ref->next) break; @@ -1061,6 +1063,7 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp, ref->next->u.ar.as = comp->ts.type == BT_CLASS ? CLASS_DATA (comp)->as : comp->as; e->rank = ref->next->u.ar.as->rank; + e->corank = ref->next->u.ar.as->corank; ref->next->u.ar.type = e->rank ? AR_FULL : AR_ELEMENT; } diff --git a/gcc/fortran/data.cc b/gcc/fortran/data.cc index 70247490e47..d80ba66d358 100644 --- a/gcc/fortran/data.cc +++ b/gcc/fortran/data.cc @@ -327,6 +327,7 @@ gfc_assign_data_value (gfc_expr *lvalue, gfc_expr *rvalue, mpz_t index, /* Setup the expression to hold the constructor. */ expr->expr_type = EXPR_ARRAY; expr->rank = ref->u.ar.as->rank; + expr->corank = ref->u.ar.as->corank; } if (ref->u.ar.type == AR_ELEMENT) diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc index b8308aeee55..f712a454154 100644 --- a/gcc/fortran/decl.cc +++ b/gcc/fortran/decl.cc @@ -912,6 +912,7 @@ match_clist_expr (gfc_expr **result, gfc_typespec *ts, gfc_array_spec *as) /* Set the rank/shape to match the LHS as auto-reshape is implied. */ expr->rank = as->rank; + expr->corank = as->corank; expr->shape = gfc_get_shape (as->rank); for (int i = 0; i < as->rank; ++i) spec_dimen_size (as, i, &expr->shape[i]); @@ -2277,6 +2278,7 @@ add_init_expr_to_sym (const char *name, gfc_expr **initp, locus *var_locus) mpz_clear (size); } init->rank = sym->as->rank; + init->corank = sym->as->corank; } sym->value = init; diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc index be138d196a2..d3a1f8c0ba1 100644 --- a/gcc/fortran/expr.cc +++ b/gcc/fortran/expr.cc @@ -1320,6 +1320,7 @@ simplify_intrinsic_op (gfc_expr *p, int type) } result->rank = p->rank; + result->corank = p->corank; result->where = p->where; gfc_replace_expr (p, result); @@ -2161,6 +2162,7 @@ simplify_parameter_variable (gfc_expr *p, int type) e->expr_type = EXPR_ARRAY; e->ts = p->ts; e->rank = p->rank; + e->corank = p->corank; e->value.constructor = NULL; e->shape = gfc_copy_shape (p->shape, p->rank); e->where = p->where; @@ -2181,6 +2183,7 @@ simplify_parameter_variable (gfc_expr *p, int type) gfc_free_shape (&e->shape, e->rank); e->shape = gfc_copy_shape (p->shape, p->rank); e->rank = p->rank; + e->corank = p->corank; if (e->ts.type == BT_CHARACTER && p->ts.u.cl) e->ts = p->ts; @@ -4596,7 +4599,10 @@ gfc_check_assign_symbol (gfc_symbol *sym, gfc_component *comp, gfc_expr *rvalue) lvalue.expr_type = EXPR_VARIABLE; lvalue.ts = sym->ts; if (sym->as) - lvalue.rank = sym->as->rank; + { + lvalue.rank = sym->as->rank; + lvalue.corank = sym->as->corank; + } lvalue.symtree = XCNEW (gfc_symtree); lvalue.symtree->n.sym = sym; lvalue.where = sym->declared_at; @@ -4609,6 +4615,7 @@ gfc_check_assign_symbol (gfc_symbol *sym, gfc_component *comp, gfc_expr *rvalue) lvalue.ref->u.c.sym = sym; lvalue.ts = comp->ts; lvalue.rank = comp->as ? comp->as->rank : 0; + lvalue.corank = comp->as ? comp->as->corank : 0; lvalue.where = comp->loc; pointer = comp->ts.type == BT_CLASS && CLASS_DATA (comp) ? CLASS_DATA (comp)->attr.class_pointer : comp->attr.pointer; @@ -5261,14 +5268,15 @@ gfc_get_variable_expr (gfc_symtree *var) && CLASS_DATA (var->n.sym) && CLASS_DATA (var->n.sym)->as))) { - e->rank = var->n.sym->ts.type == BT_CLASS - ? CLASS_DATA (var->n.sym)->as->rank : var->n.sym->as->rank; + gfc_array_spec *as = var->n.sym->ts.type == BT_CLASS + ? CLASS_DATA (var->n.sym)->as + : var->n.sym->as; + e->rank = as->rank; + e->corank = as->corank; e->ref = gfc_get_ref (); e->ref->type = REF_ARRAY; e->ref->u.ar.type = AR_FULL; - e->ref->u.ar.as = gfc_copy_array_spec (var->n.sym->ts.type == BT_CLASS - ? CLASS_DATA (var->n.sym)->as - : var->n.sym->as); + e->ref->u.ar.as = gfc_copy_array_spec (as); } return e; @@ -5297,6 +5305,8 @@ gfc_add_full_array_ref (gfc_expr *e, gfc_array_spec *as) ref->type = REF_ARRAY; ref->u.ar.type = AR_FULL; ref->u.ar.dimen = e->rank; + /* Do not set the corank here, or resolve will not be able to set correct + dimen-types for the coarray. */ ref->u.ar.where = e->where; ref->u.ar.as = as; } @@ -5316,7 +5326,8 @@ gfc_lval_expr_from_sym (gfc_symbol *sym) /* It will always be a full array. */ as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as; lval->rank = as ? as->rank : 0; - if (lval->rank) + lval->corank = as ? as->corank : 0; + if (lval->rank || lval->corank) gfc_add_full_array_ref (lval, as); return lval; } @@ -5872,32 +5883,6 @@ gfc_is_coarray (gfc_expr *e) } -int -gfc_get_corank (gfc_expr *e) -{ - int corank; - gfc_ref *ref; - - if (!gfc_is_coarray (e)) - return 0; - - if (e->ts.type == BT_CLASS && CLASS_DATA (e)) - corank = CLASS_DATA (e)->as - ? CLASS_DATA (e)->as->corank : 0; - else - corank = e->symtree->n.sym->as ? e->symtree->n.sym->as->corank : 0; - - for (ref = e->ref; ref; ref = ref->next) - { - if (ref->type == REF_ARRAY) - corank = ref->u.ar.as->corank; - gcc_assert (ref->type != REF_SUBSTRING); - } - - return corank; -} - - /* Check whether the expression has an ultimate allocatable component. Being itself allocatable does not count. */ bool diff --git a/gcc/fortran/frontend-passes.cc b/gcc/fortran/frontend-passes.cc index 3c06018fdbb..104ccb1a4c1 100644 --- a/gcc/fortran/frontend-passes.cc +++ b/gcc/fortran/frontend-passes.cc @@ -515,6 +515,7 @@ callback_reduction (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, new_expr->ts = fn->ts; new_expr->expr_type = EXPR_OP; new_expr->rank = fn->rank; + new_expr->corank = fn->corank; new_expr->where = fn->where; new_expr->value.op.op = op; new_expr->value.op.op1 = res; @@ -791,6 +792,7 @@ create_var (gfc_expr * e, const char *vname) { symbol->as = gfc_get_array_spec (); symbol->as->rank = e->rank; + symbol->as->corank = e->corank; if (e->shape == NULL) { @@ -853,6 +855,7 @@ create_var (gfc_expr * e, const char *vname) result->ts = symbol->ts; result->ts.deferred = deferred; result->rank = e->rank; + result->corank = e->corank; result->shape = gfc_copy_shape (e->shape, e->rank); result->symtree = symtree; result->where = e->where; @@ -1839,6 +1842,7 @@ combine_array_constructor (gfc_expr *e) new_expr->ts = e->ts; new_expr->expr_type = EXPR_OP; new_expr->rank = c->expr->rank; + new_expr->corank = c->expr->corank; new_expr->where = c->expr->where; new_expr->value.op.op = e->value.op.op; @@ -2283,6 +2287,7 @@ optimize_minmaxloc (gfc_expr **e) *e = gfc_get_array_expr (fn->ts.type, fn->ts.kind, &fn->where); (*e)->shape = fn->shape; fn->rank = 0; + fn->corank = 0; fn->shape = NULL; gfc_constructor_append_expr (&(*e)->value.constructor, fn, &fn->where); diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 8d89797412e..729d811d945 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -2571,6 +2571,7 @@ typedef struct gfc_expr gfc_typespec ts; /* These two refer to the overall expression */ int rank; /* 0 indicates a scalar, -1 an assumed-rank array. */ + int corank; /* same as rank, but for coarrays. */ mpz_t *shape; /* Can be NULL if shape is unknown at compile time */ /* Nonnull for functions and structure constructors, may also used to hold the @@ -3801,7 +3802,6 @@ bool gfc_is_class_array_function (gfc_expr *); bool gfc_ref_this_image (gfc_ref *ref); bool gfc_is_coindexed (gfc_expr *); bool gfc_is_coarray (gfc_expr *); -int gfc_get_corank (gfc_expr *); bool gfc_has_ultimate_allocatable (gfc_expr *); bool gfc_has_ultimate_pointer (gfc_expr *); gfc_expr* gfc_find_team_co (gfc_expr *); diff --git a/gcc/fortran/intrinsic.cc b/gcc/fortran/intrinsic.cc index 62c349da7f6..f7cbb4bb5e2 100644 --- a/gcc/fortran/intrinsic.cc +++ b/gcc/fortran/intrinsic.cc @@ -165,6 +165,7 @@ gfc_get_intrinsic_function_symbol (gfc_expr *expr) sym->as = gfc_get_array_spec (); sym->as->type = AS_ASSUMED_SHAPE; sym->as->rank = expr->rank; + sym->as->corank = expr->corank; } return sym; } @@ -5382,6 +5383,7 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag, new_expr->where = old_where; new_expr->ts = *ts; new_expr->rank = rank; + new_expr->corank = expr->corank; new_expr->shape = gfc_copy_shape (shape, rank); gfc_get_ha_sym_tree (sym->name, &new_expr->symtree); @@ -5457,6 +5459,7 @@ gfc_convert_chartype (gfc_expr *expr, gfc_typespec *ts) new_expr->where = old_where; new_expr->ts = *ts; new_expr->rank = rank; + new_expr->corank = expr->corank; new_expr->shape = gfc_copy_shape (shape, rank); gfc_get_ha_sym_tree (sym->name, &new_expr->symtree); diff --git a/gcc/fortran/iresolve.cc b/gcc/fortran/iresolve.cc index c63a4a8d38c..753c636a1af 100644 --- a/gcc/fortran/iresolve.cc +++ b/gcc/fortran/iresolve.cc @@ -152,13 +152,21 @@ resolve_bound (gfc_expr *f, gfc_expr *array, gfc_expr *dim, gfc_expr *kind, if (dim == NULL) { - f->rank = 1; if (array->rank != -1) { - f->shape = gfc_get_shape (1); - mpz_init_set_ui (f->shape[0], coarray ? gfc_get_corank (array) - : array->rank); + /* Assume f->rank gives the size of the shape, because there is no + other way to determine the size. */ + if (!f->shape || f->rank != 1) + { + if (f->shape) + gfc_free_shape (&f->shape, f->rank); + f->shape = gfc_get_shape (1); + } + mpz_init_set_ui (f->shape[0], coarray ? array->corank : array->rank); } + /* Applying bound to a coarray always results in a regular array. */ + f->rank = 1; + f->corank = 0; } f->value.function.name = gfc_get_string ("%s", name); @@ -748,6 +756,7 @@ gfc_resolve_cshift (gfc_expr *f, gfc_expr *array, gfc_expr *shift, f->ts = array->ts; f->rank = array->rank; + f->corank = array->corank; f->shape = gfc_copy_shape (array->shape, array->rank); if (shift->rank > 0) @@ -916,6 +925,7 @@ gfc_resolve_eoshift (gfc_expr *f, gfc_expr *array, gfc_expr *shift, f->ts = array->ts; f->rank = array->rank; + f->corank = array->corank; f->shape = gfc_copy_shape (array->shape, array->rank); n = 0; @@ -1554,6 +1564,7 @@ gfc_resolve_logical (gfc_expr *f, gfc_expr *a, gfc_expr *kind) f->ts.kind = (kind == NULL) ? gfc_default_logical_kind : mpz_get_si (kind->value.integer); f->rank = a->rank; + f->corank = a->corank; f->value.function.name = gfc_get_string ("__logical_%d_%c%d", f->ts.kind, @@ -1584,6 +1595,7 @@ gfc_resolve_matmul (gfc_expr *f, gfc_expr *a, gfc_expr *b) } f->rank = (a->rank == 2 && b->rank == 2) ? 2 : 1; + f->corank = a->corank; if (a->rank == 2 && b->rank == 2) { diff --git a/gcc/fortran/match.cc b/gcc/fortran/match.cc index e4b60bf5f68..d30a98f48fa 100644 --- a/gcc/fortran/match.cc +++ b/gcc/fortran/match.cc @@ -6328,7 +6328,7 @@ copy_ts_from_selector_to_associate (gfc_expr *associate, gfc_expr *selector, { gfc_ref *ref; gfc_symbol *assoc_sym; - int rank = 0; + int rank = 0, corank = 0; assoc_sym = associate->symtree->n.sym; @@ -6346,6 +6346,7 @@ copy_ts_from_selector_to_associate (gfc_expr *associate, gfc_expr *selector, { assoc_sym->attr.dimension = 1; assoc_sym->as = gfc_copy_array_spec (CLASS_DATA (selector)->as); + corank = assoc_sym->as->corank; goto build_class_sym; } else if (selector->ts.type == BT_CLASS @@ -6372,13 +6373,20 @@ copy_ts_from_selector_to_associate (gfc_expr *associate, gfc_expr *selector, } if (!ref || ref->u.ar.type == AR_FULL) - selector->rank = CLASS_DATA (selector)->as->rank; + { + selector->rank = CLASS_DATA (selector)->as->rank; + selector->corank = CLASS_DATA (selector)->as->corank; + } else if (ref->u.ar.type == AR_SECTION) - selector->rank = ref->u.ar.dimen; + { + selector->rank = ref->u.ar.dimen; + selector->corank = ref->u.ar.codimen; + } else selector->rank = 0; rank = selector->rank; + corank = selector->corank; } if (rank) @@ -6400,12 +6408,20 @@ copy_ts_from_selector_to_associate (gfc_expr *associate, gfc_expr *selector, assoc_sym->as->rank = rank; assoc_sym->as->type = AS_DEFERRED; } - else - assoc_sym->as = NULL; } - else - assoc_sym->as = NULL; + if (corank != 0 && rank == 0) + { + if (!assoc_sym->as) + assoc_sym->as = gfc_get_array_spec (); + assoc_sym->as->corank = corank; + assoc_sym->attr.codimension = 1; + } + else if (corank == 0 && rank == 0 && assoc_sym->as) + { + free (assoc_sym->as); + assoc_sym->as = NULL; + } build_class_sym: /* Deal with the very specific case of a SELECT_TYPE selector being an associate_name whose type has been identified by component references. diff --git a/gcc/fortran/matchexp.cc b/gcc/fortran/matchexp.cc index 3f7140a6973..9e773cf8fee 100644 --- a/gcc/fortran/matchexp.cc +++ b/gcc/fortran/matchexp.cc @@ -133,6 +133,7 @@ gfc_get_parentheses (gfc_expr *e) e2 = gfc_get_operator_expr (&e->where, INTRINSIC_PARENTHESES, e, NULL); e2->ts = e->ts; e2->rank = e->rank; + e2->corank = e->corank; return e2; } diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc index b28c8a94547..a814b7910d3 100644 --- a/gcc/fortran/parse.cc +++ b/gcc/fortran/parse.cc @@ -5164,7 +5164,7 @@ parse_associate (void) { gfc_symbol *sym, *tsym; gfc_expr *target; - int rank; + int rank, corank; if (gfc_get_sym_tree (a->name, NULL, &a->st, false)) gcc_unreachable (); @@ -5225,11 +5225,17 @@ parse_associate (void) if (sym->ts.type == BT_CLASS) { if (CLASS_DATA (sym)->as) - target->rank = CLASS_DATA (sym)->as->rank; + { + target->rank = CLASS_DATA (sym)->as->rank; + target->corank = CLASS_DATA (sym)->as->corank; + } sym->attr.class_ok = 1; } else - target->rank = tsym->result->as ? tsym->result->as->rank : 0; + { + target->rank = tsym->result->as ? tsym->result->as->rank : 0; + target->corank = tsym->result->as ? tsym->result->as->corank : 0; + } } /* Check if the target expression is array valued. This cannot be done @@ -5261,18 +5267,19 @@ parse_associate (void) } rank = target->rank; + corank = target->corank; /* Fixup cases where the ranks are mismatched. */ if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)) { - if ((!CLASS_DATA (sym)->as && rank != 0) - || (CLASS_DATA (sym)->as - && CLASS_DATA (sym)->as->rank != rank)) + if ((!CLASS_DATA (sym)->as && (rank != 0 || corank != 0)) + || (CLASS_DATA (sym)->as + && (CLASS_DATA (sym)->as->rank != rank + || CLASS_DATA (sym)->as->corank != corank))) { /* Don't just (re-)set the attr and as in the sym.ts, because this modifies the target's attr and as. Copy the data and do a build_class_symbol. */ symbol_attribute attr = CLASS_DATA (target)->attr; - int corank = gfc_get_corank (target); gfc_typespec type; if (rank || corank) @@ -5290,6 +5297,7 @@ parse_associate (void) attr.dimension = attr.codimension = 0; } attr.class_ok = 0; + attr.associate_var = 1; type = CLASS_DATA (sym)->ts; if (!gfc_build_class_symbol (&type, &attr, &as)) gcc_unreachable (); @@ -5300,17 +5308,22 @@ parse_associate (void) else sym->attr.class_ok = 1; } - else if ((!sym->as && rank != 0) - || (sym->as && sym->as->rank != rank)) + else if ((!sym->as && (rank != 0 || corank != 0)) + || (sym->as + && (sym->as->rank != rank || sym->as->corank != corank))) { as = gfc_get_array_spec (); as->type = AS_DEFERRED; as->rank = rank; - as->corank = gfc_get_corank (target); + as->corank = corank; sym->as = as; - sym->attr.dimension = 1; - if (as->corank) - sym->attr.codimension = 1; + if (rank) + sym->attr.dimension = 1; + if (corank) + { + as->cotype = AS_ASSUMED_SHAPE; + sym->attr.codimension = 1; + } } } diff --git a/gcc/fortran/primary.cc b/gcc/fortran/primary.cc index 76f6bcb8a78..fb00c08163b 100644 --- a/gcc/fortran/primary.cc +++ b/gcc/fortran/primary.cc @@ -3895,9 +3895,15 @@ gfc_match_rvalue (gfc_expr **result) if (sym->ts.type == BT_CLASS && sym->attr.class_ok && CLASS_DATA (sym)->as) - e->rank = CLASS_DATA (sym)->as->rank; + { + e->rank = CLASS_DATA (sym)->as->rank; + e->corank = CLASS_DATA (sym)->as->corank; + } else if (sym->as != NULL) - e->rank = sym->as->rank; + { + e->rank = sym->as->rank; + e->corank = sym->as->corank; + } if (!sym->attr.function && !gfc_add_function (&sym->attr, sym->name, NULL)) diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc index 8e88aac2fe0..ffc3721efbe 100644 --- a/gcc/fortran/resolve.cc +++ b/gcc/fortran/resolve.cc @@ -1439,6 +1439,7 @@ resolve_structure_cons (gfc_expr *expr, int init) cons->expr->where = para->where; cons->expr->expr_type = EXPR_ARRAY; cons->expr->rank = para->rank; + cons->expr->corank = para->corank; cons->expr->shape = gfc_copy_shape (para->shape, para->rank); gfc_constructor_append_expr (&cons->expr->value.constructor, para, &cons->expr->where); @@ -2180,13 +2181,14 @@ resolve_actual_arglist (gfc_actual_arglist *arg, procedure_type ptype, || (sym->ts.type == BT_CLASS && sym->attr.class_ok && CLASS_DATA (sym)->as)) { - e->rank = sym->ts.type == BT_CLASS - ? CLASS_DATA (sym)->as->rank : sym->as->rank; + gfc_array_spec *as + = sym->ts.type == BT_CLASS ? CLASS_DATA (sym)->as : sym->as; + e->rank = as->rank; + e->corank = as->corank; e->ref = gfc_get_ref (); e->ref->type = REF_ARRAY; e->ref->u.ar.type = AR_FULL; - e->ref->u.ar.as = sym->ts.type == BT_CLASS - ? CLASS_DATA (sym)->as : sym->as; + e->ref->u.ar.as = as; } /* These symbols are set untyped by calls to gfc_set_default_type @@ -2355,6 +2357,7 @@ resolve_elemental_actual (gfc_expr *expr, gfc_code *c) if (expr) { expr->rank = rank; + expr->corank = arg->expr->corank; if (!expr->shape && arg->expr->shape) { expr->shape = gfc_get_shape (rank); @@ -2801,9 +2804,15 @@ resolve_generic_f0 (gfc_expr *expr, gfc_symbol *sym) expr->ts = s->result->ts; if (s->as != NULL) - expr->rank = s->as->rank; + { + expr->rank = s->as->rank; + expr->corank = s->as->corank; + } else if (s->result != NULL && s->result->as != NULL) - expr->rank = s->result->as->rank; + { + expr->rank = s->result->as->rank; + expr->corank = s->result->as->corank; + } gfc_set_sym_referenced (expr->value.function.esym); @@ -2943,9 +2952,15 @@ found: if (sym->ts.type == BT_CLASS && !CLASS_DATA (sym)) return MATCH_ERROR; if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->as) - expr->rank = CLASS_DATA (sym)->as->rank; + { + expr->rank = CLASS_DATA (sym)->as->rank; + expr->corank = CLASS_DATA (sym)->as->corank; + } else if (sym->as != NULL) - expr->rank = sym->as->rank; + { + expr->rank = sym->as->rank; + expr->corank = sym->as->corank; + } return MATCH_YES; } @@ -3066,7 +3081,10 @@ resolve_unknown_f (gfc_expr *expr) expr->value.function.esym = expr->symtree->n.sym; if (sym->as != NULL) - expr->rank = sym->as->rank; + { + expr->rank = sym->as->rank; + expr->corank = sym->as->corank; + } /* Type of the expression is either the type of the symbol or the default type of the symbol. */ @@ -4606,6 +4624,33 @@ resolve_operator (gfc_expr *e) } } + /* coranks have to be equal or one has to be zero to be combinable. */ + if (op1->corank == op2->corank || (op1->corank != 0 && op2->corank == 0)) + { + e->corank = op1->corank; + /* Only do this, when regular array has not set a shape yet. */ + if (e->shape == NULL) + { + if (op1->corank != 0) + { + e->shape = gfc_copy_shape (op1->shape, op1->corank); + } + } + } + else if (op1->corank == 0 && op2->corank != 0) + { + e->corank = op2->corank; + /* Only do this, when regular array has not set a shape yet. */ + if (e->shape == NULL) + e->shape = gfc_copy_shape (op2->shape, op2->corank); + } + else + { + gfc_error ("Inconsistent coranks for operator at %%L and %%L", + &op1->where, &op2->where); + return false; + } + break; case INTRINSIC_PARENTHESES: @@ -4614,6 +4659,7 @@ resolve_operator (gfc_expr *e) case INTRINSIC_UMINUS: /* Simply copy arrayness attribute */ e->rank = op1->rank; + e->corank = op1->corank; if (e->shape == NULL) e->shape = gfc_copy_shape (op1->shape, op1->rank); @@ -5651,8 +5697,8 @@ fail: void gfc_expression_rank (gfc_expr *e) { - gfc_ref *ref; - int i, rank; + gfc_ref *ref, *last_arr_ref = nullptr; + int i, rank, corank; /* Just to make sure, because EXPR_COMPCALL's also have an e->ref and that could lead to serious confusion... */ @@ -5664,22 +5710,42 @@ gfc_expression_rank (gfc_expr *e) goto done; /* Constructors can have a rank different from one via RESHAPE(). */ - e->rank = ((e->symtree == NULL || e->symtree->n.sym->as == NULL) - ? 0 : e->symtree->n.sym->as->rank); + if (e->symtree != NULL) + { + /* After errors the ts.u.derived of a CLASS might not be set. */ + gfc_array_spec *as = (e->symtree->n.sym->ts.type == BT_CLASS + && e->symtree->n.sym->ts.u.derived + && CLASS_DATA (e->symtree->n.sym)) + ? CLASS_DATA (e->symtree->n.sym)->as + : e->symtree->n.sym->as; + if (as) + { + e->rank = as->rank; + e->corank = as->corank; + goto done; + } + } + e->rank = 0; + e->corank = 0; goto done; } rank = 0; + corank = 0; for (ref = e->ref; ref; ref = ref->next) { if (ref->type == REF_COMPONENT && ref->u.c.component->attr.proc_pointer && ref->u.c.component->attr.function && !ref->next) - rank = ref->u.c.component->as ? ref->u.c.component->as->rank : 0; + { + rank = ref->u.c.component->as ? ref->u.c.component->as->rank : 0; + corank = ref->u.c.component->as ? ref->u.c.component->as->corank : 0; + } if (ref->type != REF_ARRAY) continue; + last_arr_ref = ref; if (ref->u.ar.type == AR_FULL && ref->u.ar.as) { rank = ref->u.ar.as->rank; @@ -5700,8 +5766,30 @@ gfc_expression_rank (gfc_expr *e) break; } } + if (last_arr_ref && last_arr_ref->u.ar.as) + { + for (i = last_arr_ref->u.ar.as->rank; + i < last_arr_ref->u.ar.as->rank + last_arr_ref->u.ar.as->corank; ++i) + { + /* For unknown dimen in non-resolved as assume full corank. */ + if (last_arr_ref->u.ar.dimen_type[i] == DIMEN_STAR + || (last_arr_ref->u.ar.dimen_type[i] == DIMEN_UNKNOWN + && !last_arr_ref->u.ar.as->resolved)) + { + corank = last_arr_ref->u.ar.as->corank; + break; + } + else if (last_arr_ref->u.ar.dimen_type[i] == DIMEN_RANGE + || last_arr_ref->u.ar.dimen_type[i] == DIMEN_VECTOR + || last_arr_ref->u.ar.dimen_type[i] == DIMEN_THIS_IMAGE) + corank++; + else if (last_arr_ref->u.ar.dimen_type[i] != DIMEN_ELEMENT) + gfc_internal_error ("Illegal coarray index"); + } + } e->rank = rank; + e->corank = corank; done: expression_shape (e); @@ -5719,7 +5807,9 @@ gfc_op_rank_conformable (gfc_expr *op1, gfc_expr *op2) if (op2->expr_type == EXPR_VARIABLE) gfc_expression_rank (op2); - return (op1->rank == 0 || op2->rank == 0 || op1->rank == op2->rank); + return (op1->rank == 0 || op2->rank == 0 || op1->rank == op2->rank) + && (op1->corank == 0 || op2->corank == 0 + || op1->corank == op2->corank); } @@ -5746,6 +5836,7 @@ add_caf_get_intrinsic (gfc_expr *e) "caf_get", tmp_expr->where, 1, tmp_expr); wrapper->ts = e->ts; wrapper->rank = e->rank; + wrapper->corank = e->corank; if (e->rank) wrapper->shape = gfc_copy_shape (e->shape, e->rank); *e = *wrapper; @@ -5926,7 +6017,8 @@ resolve_variable (gfc_expr *e) { if (sym->ts.type == BT_CLASS) gfc_fix_class_refs (e); - if (!sym->attr.dimension && e->ref && e->ref->type == REF_ARRAY) + if (!sym->attr.dimension && !sym->attr.codimension && e->ref + && e->ref->type == REF_ARRAY) { /* Unambiguously scalar! */ if (sym->assoc->target @@ -5936,7 +6028,8 @@ resolve_variable (gfc_expr *e) sym->name, &e->where); return false; } - else if (sym->attr.dimension && (!e->ref || e->ref->type != REF_ARRAY)) + else if ((sym->attr.dimension || sym->attr.codimension) + && (!e->ref || e->ref->type != REF_ARRAY)) { /* This can happen because the parser did not detect that the associate name is an array and the expression had no array @@ -5951,7 +6044,6 @@ resolve_variable (gfc_expr *e) } ref->next = e->ref; e->ref = ref; - } } @@ -5960,7 +6052,7 @@ resolve_variable (gfc_expr *e) /* On the other hand, the parser may not have known this is an array; in this case, we have to add a FULL reference. */ - if (sym->assoc && sym->attr.dimension && !e->ref) + if (sym->assoc && (sym->attr.dimension || sym->attr.codimension) && !e->ref) { e->ref = gfc_get_ref (); e->ref->type = REF_ARRAY; @@ -5973,7 +6065,8 @@ resolve_variable (gfc_expr *e) the full array ref to _vptr or _len refs. */ if (sym->assoc && sym->ts.type == BT_CLASS && sym->ts.u.derived && CLASS_DATA (sym) - && CLASS_DATA (sym)->attr.dimension + && (CLASS_DATA (sym)->attr.dimension + || CLASS_DATA (sym)->attr.codimension) && (e->ts.type != BT_DERIVED || !e->ts.u.derived->attr.vtype)) { gfc_ref *ref, *newref; @@ -6219,6 +6312,7 @@ gfc_fixup_inferred_type_refs (gfc_expr *e) if (sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS) { sym->attr.dimension = sym->assoc->target->rank ? 1 : 0; + sym->attr.codimension = sym->assoc->target->corank ? 1 : 0; if (!sym->attr.dimension && e->ref->type == REF_ARRAY) { ref = e->ref; @@ -6282,8 +6376,11 @@ gfc_fixup_inferred_type_refs (gfc_expr *e) && sym->assoc->target->ts.type == BT_CLASS) { e->rank = CLASS_DATA (sym)->as ? CLASS_DATA (sym)->as->rank : 0; + e->corank = CLASS_DATA (sym)->as ? CLASS_DATA (sym)->as->corank : 0; sym->attr.dimension = 0; + sym->attr.codimension = 0; CLASS_DATA (sym)->attr.dimension = e->rank ? 1 : 0; + CLASS_DATA (sym)->attr.codimension = e->corank ? 1 : 0; if (e->ref && (e->ref->type != REF_COMPONENT || e->ref->u.c.component->name[0] != '_')) { @@ -6463,6 +6560,7 @@ check_host_association (gfc_expr *e) gfc_free_ref_list (e->ref); e->ref = NULL; e->rank = sym->as ? sym->as->rank : 0; + e->corank = sym->as ? sym->as->corank : 0; } gfc_resolve_expr (e); @@ -7085,7 +7183,10 @@ resolve_compcall (gfc_expr* e, const char **name) /* Take the rank from the function's symbol. */ if (e->value.compcall.tbp->u.specific->n.sym->as) - e->rank = e->value.compcall.tbp->u.specific->n.sym->as->rank; + { + e->rank = e->value.compcall.tbp->u.specific->n.sym->as->rank; + e->corank = e->value.compcall.tbp->u.specific->n.sym->as->corank; + } /* For now, we simply transform it into an EXPR_FUNCTION call with the same arglist to the TBP's binding target. */ @@ -7410,7 +7511,10 @@ resolve_expr_ppc (gfc_expr* e) e->value.function.actual = e->value.compcall.actual; e->ts = comp->ts; if (comp->as != NULL) - e->rank = comp->as->rank; + { + e->rank = comp->as->rank; + e->corank = comp->as->corank; + } if (!comp->attr.function) gfc_add_function (&comp->attr, comp->name, &e->where); @@ -9482,8 +9586,8 @@ resolve_assoc_var (gfc_symbol* sym, bool resolve_target) sym->as = gfc_copy_array_spec (CLASS_DATA (target)->as); attr = CLASS_DATA (sym) ? CLASS_DATA (sym)->attr : sym->attr; sym->attr.dimension = target->rank ? 1 : 0; - gfc_change_class (&sym->ts, &attr, sym->as, - target->rank, gfc_get_corank (target)); + gfc_change_class (&sym->ts, &attr, sym->as, target->rank, + target->corank); sym->as = NULL; } else if (target->ts.type == BT_DERIVED @@ -9500,8 +9604,8 @@ resolve_assoc_var (gfc_symbol* sym, bool resolve_target) sym->ts = target->ts; attr = CLASS_DATA (sym) ? CLASS_DATA (sym)->attr : sym->attr; sym->attr.dimension = target->rank ? 1 : 0; - gfc_change_class (&sym->ts, &attr, sym->as, - target->rank, gfc_get_corank (target)); + gfc_change_class (&sym->ts, &attr, sym->as, target->rank, + target->corank); sym->as = NULL; target->ts = sym->ts; } @@ -9555,6 +9659,7 @@ resolve_assoc_var (gfc_symbol* sym, bool resolve_target) && CLASS_DATA (target)->as) { target->rank = CLASS_DATA (target)->as->rank; + target->corank = CLASS_DATA (target)->as->corank; if (!(sym->ts.type == BT_CLASS && CLASS_DATA (sym)->as)) { sym->ts = target->ts; @@ -9598,32 +9703,35 @@ resolve_assoc_var (gfc_symbol* sym, bool resolve_target) if (target->ts.type == BT_CLASS) gfc_fix_class_refs (target); - if (target->rank != 0 && !sym->attr.select_rank_temporary) + if ((target->rank != 0 || target->corank != 0) + && !sym->attr.select_rank_temporary) { gfc_array_spec *as; /* The rank may be incorrectly guessed at parsing, therefore make sure it is corrected now. */ - if (sym->ts.type != BT_CLASS && !sym->as) + if (sym->ts.type != BT_CLASS + && (!sym->as || sym->as->corank != target->corank)) { if (!sym->as) sym->as = gfc_get_array_spec (); as = sym->as; as->rank = target->rank; as->type = AS_DEFERRED; - as->corank = gfc_get_corank (target); + as->corank = target->corank; sym->attr.dimension = 1; if (as->corank != 0) sym->attr.codimension = 1; } - else if (sym->ts.type == BT_CLASS - && CLASS_DATA (sym) && !CLASS_DATA (sym)->as) + else if (sym->ts.type == BT_CLASS && CLASS_DATA (sym) + && (!CLASS_DATA (sym)->as + || CLASS_DATA (sym)->as->corank != target->corank)) { if (!CLASS_DATA (sym)->as) CLASS_DATA (sym)->as = gfc_get_array_spec (); as = CLASS_DATA (sym)->as; as->rank = target->rank; as->type = AS_DEFERRED; - as->corank = gfc_get_corank (target); + as->corank = target->corank; CLASS_DATA (sym)->attr.dimension = 1; if (as->corank != 0) CLASS_DATA (sym)->attr.codimension = 1; @@ -9733,8 +9841,8 @@ resolve_assoc_var (gfc_symbol* sym, bool resolve_target) This is corrected here as well.*/ static void -fixup_array_ref (gfc_expr **expr1, gfc_expr *expr2, - int rank, gfc_ref *ref) +fixup_array_ref (gfc_expr **expr1, gfc_expr *expr2, int rank, int corank, + gfc_ref *ref) { gfc_ref *nref = (*expr1)->ref; gfc_symbol *sym1 = (*expr1)->symtree->n.sym; @@ -9742,6 +9850,7 @@ fixup_array_ref (gfc_expr **expr1, gfc_expr *expr2, gfc_expr *selector = gfc_copy_expr (expr2); (*expr1)->rank = rank; + (*expr1)->corank = corank; if (selector) { gfc_resolve_expr (selector); @@ -9762,14 +9871,16 @@ fixup_array_ref (gfc_expr **expr1, gfc_expr *expr2, if ((*expr1)->ts.type != BT_CLASS) (*expr1)->ts = sym1->ts; - CLASS_DATA (sym1)->attr.dimension = 1; + CLASS_DATA (sym1)->attr.dimension = rank > 0 ? 1 : 0; + CLASS_DATA (sym1)->attr.codimension = corank > 0 ? 1 : 0; if (CLASS_DATA (sym1)->as == NULL && sym2) CLASS_DATA (sym1)->as = gfc_copy_array_spec (CLASS_DATA (sym2)->as); } else { - sym1->attr.dimension = 1; + sym1->attr.dimension = rank > 0 ? 1 : 0; + sym1->attr.codimension = corank > 0 ? 1 : 0; if (sym1->as == NULL && sym2) sym1->as = gfc_copy_array_spec (sym2->as); } @@ -9782,6 +9893,12 @@ fixup_array_ref (gfc_expr **expr1, gfc_expr *expr2, nref->next = gfc_copy_ref (ref); else if (ref && !nref) (*expr1)->ref = gfc_copy_ref (ref); + else if (ref && nref->u.ar.codimen != corank) + { + for (int i = nref->u.ar.dimen; i < GFC_MAX_DIMENSIONS; ++i) + nref->u.ar.dimen_type[i] = DIMEN_THIS_IMAGE; + nref->u.ar.codimen = corank; + } } @@ -9818,11 +9935,16 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns) char name[GFC_MAX_SYMBOL_LEN + 12 + 1]; gfc_namespace *ns; int error = 0; - int rank = 0; + int rank = 0, corank = 0; gfc_ref* ref = NULL; gfc_expr *selector_expr = NULL; ns = code->ext.block.ns; + if (code->expr2) + { + /* Set this, or coarray checks in resolve will fail. */ + code->expr1->symtree->n.sym->attr.select_type_temporary = 1; + } gfc_resolve (ns); /* Check for F03:C813. */ @@ -9834,7 +9956,10 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns) return; } - if (!code->expr1->symtree->n.sym->attr.class_ok) + /* Prevent segfault, when class type is not initialized due to previous + error. */ + if (!code->expr1->symtree->n.sym->attr.class_ok + || (code->expr1->ts.type == BT_CLASS && !code->expr1->ts.u.derived)) return; if (code->expr2) @@ -9865,10 +9990,12 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns) ? CLASS_DATA (code->expr2)->ts.u.derived : code->expr2->ts.u.derived; } - if (code->expr2->rank - && code->expr1->ts.type == BT_CLASS - && CLASS_DATA (code->expr1)->as) - CLASS_DATA (code->expr1)->as->rank = code->expr2->rank; + if (code->expr1->ts.type == BT_CLASS && CLASS_DATA (code->expr1)->as) + { + CLASS_DATA (code->expr1)->as->rank = code->expr2->rank; + CLASS_DATA (code->expr1)->as->corank = code->expr2->corank; + CLASS_DATA (code->expr1)->as->cotype = AS_DEFERRED; + } /* F2008: C803 The selector expression must not be coindexed. */ if (gfc_is_coindexed (code->expr2)) @@ -10005,9 +10132,10 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns) /* Ensure that the selector rank and arrayspec are available to correct expressions in which they might be missing. */ - if (code->expr2 && code->expr2->rank) + if (code->expr2 && (code->expr2->rank || code->expr2->corank)) { rank = code->expr2->rank; + corank = code->expr2->corank; for (ref = code->expr2->ref; ref; ref = ref->next) if (ref->next == NULL) break; @@ -10015,12 +10143,13 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns) ref = gfc_copy_ref (ref); /* Fixup expr1 if necessary. */ - if (rank) - fixup_array_ref (&code->expr1, code->expr2, rank, ref); + if (rank || corank) + fixup_array_ref (&code->expr1, code->expr2, rank, corank, ref); } - else if (code->expr1->rank) + else if (code->expr1->rank || code->expr1->corank) { rank = code->expr1->rank; + corank = code->expr1->corank; for (ref = code->expr1->ref; ref; ref = ref->next) if (ref->next == NULL) break; @@ -10047,6 +10176,7 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns) expression has to be set to zero. */ gfc_add_vptr_component (code->expr1); code->expr1->rank = 0; + code->expr1->corank = 0; code->expr1 = build_loc_call (code->expr1); selector_expr = code->expr1->value.function.actual->expr; @@ -10121,8 +10251,9 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns) { gfc_add_data_component (st->n.sym->assoc->target); /* Fixup the target expression if necessary. */ - if (rank) - fixup_array_ref (&st->n.sym->assoc->target, NULL, rank, ref); + if (rank || corank) + fixup_array_ref (&st->n.sym->assoc->target, nullptr, rank, corank, + ref); } new_st = gfc_get_code (EXEC_BLOCK); @@ -11757,6 +11888,7 @@ add_comp_ref (gfc_expr *e, gfc_component *c) { gfc_add_full_array_ref (e, c->as); e->rank = c->as->rank; + e->corank = c->as->corank; } } @@ -11851,15 +11983,17 @@ get_temp_from_expr (gfc_expr *e, gfc_namespace *ns) if (as->type == AS_DEFERRED) tmp->n.sym->attr.allocatable = 1; } - else if (e->rank && (e->expr_type == EXPR_ARRAY - || e->expr_type == EXPR_FUNCTION - || e->expr_type == EXPR_OP)) + else if ((e->rank || e->corank) + && (e->expr_type == EXPR_ARRAY || e->expr_type == EXPR_FUNCTION + || e->expr_type == EXPR_OP)) { tmp->n.sym->as = gfc_get_array_spec (); tmp->n.sym->as->type = AS_DEFERRED; tmp->n.sym->as->rank = e->rank; + tmp->n.sym->as->corank = e->corank; tmp->n.sym->attr.allocatable = 1; - tmp->n.sym->attr.dimension = 1; + tmp->n.sym->attr.dimension = e->rank ? 1 : 0; + tmp->n.sym->attr.codimension = e->corank ? 1 : 0; } else tmp->n.sym->attr.dimension = 0; @@ -13656,7 +13790,9 @@ resolve_fl_var_and_proc (gfc_symbol *sym, int mp_flag) /* Assume that use associated symbols were checked in the module ns. Class-variables that are associate-names are also something special and excepted from the test. */ - if (!sym->attr.class_ok && !sym->attr.use_assoc && !sym->assoc) + if (!sym->attr.class_ok && !sym->attr.use_assoc && !sym->assoc + && !sym->attr.select_type_temporary + && !sym->attr.select_rank_temporary) { gfc_error ("CLASS variable %qs at %L must be dummy, allocatable " "or pointer", sym->name, &sym->declared_at); @@ -16441,6 +16577,7 @@ resolve_symbol (gfc_symbol *sym) sym->ts = sym->result->ts; sym->as = gfc_copy_array_spec (sym->result->as); sym->attr.dimension = sym->result->attr.dimension; + sym->attr.codimension = sym->result->attr.codimension; sym->attr.pointer = sym->result->attr.pointer; sym->attr.allocatable = sym->result->attr.allocatable; sym->attr.contiguous = sym->result->attr.contiguous; diff --git a/gcc/fortran/symbol.cc b/gcc/fortran/symbol.cc index a8b623dd92a..dd209a22fc1 100644 --- a/gcc/fortran/symbol.cc +++ b/gcc/fortran/symbol.cc @@ -5410,7 +5410,8 @@ gfc_is_associate_pointer (gfc_symbol* sym) if (!sym->assoc->variable) return false; - if (sym->attr.dimension && sym->as->type != AS_EXPLICIT) + if ((sym->attr.dimension || sym->attr.codimension) + && sym->as->type != AS_EXPLICIT) return false; return true; diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 9fb0b2b398d..ea5fff2e0c2 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -7882,8 +7882,6 @@ walk_coarray (gfc_expr *e) { gfc_ss *ss; - gcc_assert (gfc_get_corank (e) > 0); - ss = gfc_walk_expr (e); /* Fix scalar coarray. */ @@ -7904,7 +7902,7 @@ walk_coarray (gfc_expr *e) gcc_assert (ref != NULL); if (ref->u.ar.type == AR_ELEMENT) ref->u.ar.type = AR_SECTION; - ss = gfc_reverse_ss (gfc_walk_array_ref (ss, e, ref)); + ss = gfc_reverse_ss (gfc_walk_array_ref (ss, e, ref, false)); } return ss; @@ -8005,7 +8003,7 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr) bool substr = false; gfc_expr *arg, *ss_expr; - if (se->want_coarray) + if (se->want_coarray || expr->rank == 0) ss = walk_coarray (expr); else ss = gfc_walk_expr (expr); @@ -8338,7 +8336,7 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr) { gfc_array_ref *ar = &info->ref->u.ar; - codim = gfc_get_corank (expr); + codim = expr->corank; for (n = 0; n < codim - 1; n++) { /* Make sure we are not lost somehow. */ @@ -8488,6 +8486,8 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr) /* The 1st element in the section. */ base = gfc_index_zero_node; + if (expr->ts.type == BT_CHARACTER && expr->rank == 0 && codim) + base = gfc_index_one_node; /* The offset from the 1st element in the section. */ offset = gfc_index_zero_node; @@ -8587,6 +8587,23 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr) gfc_conv_descriptor_offset_set (&loop.pre, parm, offset); + if (flag_coarray == GFC_FCOARRAY_LIB && expr->corank) + { + tmp = INDIRECT_REF_P (desc) ? TREE_OPERAND (desc, 0) : desc; + if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp))) + { + tmp = gfc_conv_descriptor_token (tmp); + } + else if (DECL_P (tmp) && DECL_LANG_SPECIFIC (tmp) + && GFC_DECL_TOKEN (tmp) != NULL_TREE) + tmp = GFC_DECL_TOKEN (tmp); + else + { + tmp = GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (tmp)); + } + + gfc_add_modify (&loop.pre, gfc_conv_descriptor_token (parm), tmp); + } desc = parm; } @@ -12110,9 +12127,8 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr) return gfc_walk_array_ref (ss, expr, ref); } - gfc_ss * -gfc_walk_array_ref (gfc_ss * ss, gfc_expr * expr, gfc_ref * ref) +gfc_walk_array_ref (gfc_ss *ss, gfc_expr *expr, gfc_ref *ref, bool array_only) { gfc_array_ref *ar; gfc_ss *newss; @@ -12128,7 +12144,8 @@ gfc_walk_array_ref (gfc_ss * ss, gfc_expr * expr, gfc_ref * ref) } /* We're only interested in array sections from now on. */ - if (ref->type != REF_ARRAY) + if (ref->type != REF_ARRAY + || (array_only && ref->u.ar.as && ref->u.ar.as->rank == 0)) continue; ar = &ref->u.ar; diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h index 29499a337c2..ab27f15cab2 100644 --- a/gcc/fortran/trans-array.h +++ b/gcc/fortran/trans-array.h @@ -89,7 +89,8 @@ gfc_ss *gfc_walk_expr (gfc_expr *); /* Workhorse for gfc_walk_expr. */ gfc_ss *gfc_walk_subexpr (gfc_ss *, gfc_expr *); /* Workhorse for gfc_walk_variable_expr. */ -gfc_ss *gfc_walk_array_ref (gfc_ss *, gfc_expr *, gfc_ref * ref); +gfc_ss *gfc_walk_array_ref (gfc_ss *, gfc_expr *, gfc_ref *ref, + bool = true); /* Walk the arguments of an elemental function. */ gfc_ss *gfc_walk_elemental_function_args (gfc_ss *, gfc_actual_arglist *, gfc_intrinsic_sym *, diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index 3677e49a356..9e4fba68550 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -147,7 +147,9 @@ tree gfc_get_ultimate_alloc_ptr_comps_caf_token (gfc_se *outerse, gfc_expr *expr) { gfc_symbol *sym = expr->symtree->n.sym; - bool is_coarray = sym->attr.codimension; + bool is_coarray = sym->ts.type == BT_CLASS + ? CLASS_DATA (sym)->attr.codimension + : sym->attr.codimension; gfc_expr *caf_expr = gfc_copy_expr (expr); gfc_ref *ref = caf_expr->ref, *last_caf_ref = NULL; @@ -173,6 +175,9 @@ gfc_get_ultimate_alloc_ptr_comps_caf_token (gfc_se *outerse, gfc_expr *expr) gfc_free_ref_list (last_caf_ref->next); last_caf_ref->next = NULL; caf_expr->rank = comp_ref ? 0 : last_caf_ref->u.c.component->as->rank; + caf_expr->corank = last_caf_ref->u.c.component->as + ? last_caf_ref->u.c.component->as->corank + : expr->corank; se.want_pointer = comp_ref; gfc_conv_expr (&se, caf_expr); gfc_add_block_to_block (&outerse->pre, &se.pre); diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc index 84a378ef310..8e1a2b04ed4 100644 --- a/gcc/fortran/trans-intrinsic.cc +++ b/gcc/fortran/trans-intrinsic.cc @@ -2407,7 +2407,7 @@ trans_this_image (gfc_se * se, gfc_expr *expr) /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */ type = gfc_get_int_type (gfc_default_integer_kind); - corank = gfc_get_corank (expr->value.function.actual->expr); + corank = expr->value.function.actual->expr->corank; rank = expr->value.function.actual->expr->rank; /* Obtain the descriptor of the COARRAY. */ @@ -2684,7 +2684,7 @@ trans_image_index (gfc_se * se, gfc_expr *expr) int rank, corank, codim; type = gfc_get_int_type (gfc_default_integer_kind); - corank = gfc_get_corank (expr->value.function.actual->expr); + corank = expr->value.function.actual->expr->corank; rank = expr->value.function.actual->expr->rank; /* Obtain the descriptor of the COARRAY. */ @@ -3162,7 +3162,7 @@ conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr) arg2 = arg->next; gcc_assert (arg->expr->expr_type == EXPR_VARIABLE); - corank = gfc_get_corank (arg->expr); + corank = arg->expr->corank; gfc_init_se (&argse, NULL); argse.want_coarray = 1; @@ -11723,13 +11723,13 @@ gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr, expr->value.function.isym, GFC_SS_SCALAR); - if (expr->rank == 0) + if (expr->rank == 0 && expr->corank == 0) return ss; if (gfc_inline_intrinsic_function_p (expr)) return walk_inline_intrinsic_function (ss, expr); - if (gfc_is_intrinsic_libcall (expr)) + if (expr->rank != 0 && gfc_is_intrinsic_libcall (expr)) return gfc_walk_intrinsic_libfunc (ss, expr); /* Special cases. */ @@ -12746,7 +12746,7 @@ conv_intrinsic_move_alloc (gfc_code *code) gfc_init_se (&to_se, NULL); gcc_assert (from_expr->ts.type != BT_CLASS || to_expr->ts.type == BT_CLASS); - coarray = gfc_get_corank (from_expr) != 0; + coarray = from_expr->corank != 0; from_is_class = from_expr->ts.type == BT_CLASS; from_is_scalar = from_expr->rank == 0 && !coarray; diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc index 41740ab762e..807fa8c6351 100644 --- a/gcc/fortran/trans-stmt.cc +++ b/gcc/fortran/trans-stmt.cc @@ -922,8 +922,8 @@ gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op op) if (gfc_expr_attr (code->expr1).dimension) { tree desc, tmp, extent, lbound, ubound; - gfc_array_ref *ar, ar2; - int i; + gfc_array_ref *ar, ar2; + int i, rank; /* TODO: Extend this, once DT components are supported. */ ar = &code->expr1->ref->u.ar; @@ -931,6 +931,8 @@ gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op op) memset (ar, '\0', sizeof (*ar)); ar->as = ar2.as; ar->type = AR_FULL; + rank = code->expr1->rank; + code->expr1->rank = ar->as->rank; gfc_init_se (&argse, NULL); argse.descriptor_only = 1; @@ -938,6 +940,7 @@ gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op op) gfc_add_block_to_block (&se.pre, &argse.pre); desc = argse.expr; *ar = ar2; + code->expr1->rank = rank; extent = build_one_cst (gfc_array_index_type); for (i = 0; i < ar->dimen; i++) @@ -1740,6 +1743,7 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block) tree charlen; bool need_len_assign; bool whole_array = true; + bool same_class; gfc_ref *ref; gfc_symbol *sym2; @@ -1750,13 +1754,14 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block) && e->ts.type == BT_CLASS && (gfc_is_class_scalar_expr (e) || gfc_is_class_array_ref (e, NULL)); + same_class = e->ts.type == BT_CLASS && sym->ts.type == BT_CLASS + && strcmp (sym->ts.u.derived->name, e->ts.u.derived->name) == 0; unlimited = UNLIMITED_POLY (e); for (ref = e->ref; ref; ref = ref->next) - if (ref->type == REF_ARRAY - && ref->u.ar.type == AR_FULL - && ref->next) + if (ref->type == REF_ARRAY && ref->u.ar.type == AR_FULL + && ref->u.ar.dimen != 0 && ref->next) { whole_array = false; break; @@ -1905,7 +1910,7 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block) gfc_add_init_cleanup (block, gfc_finish_block (&se.pre), tmp); } /* Now all the other kinds of associate variable. */ - else if (sym->attr.dimension && !class_target + else if ((sym->attr.dimension || sym->attr.codimension) && !class_target && (sym->as->type == AS_DEFERRED || sym->assoc->variable)) { gfc_se se; @@ -1931,6 +1936,9 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block) GFC_DECL_PTR_ARRAY_P (sym->backend_decl) = 1; } + if (sym->attr.codimension && !sym->attr.dimension) + se.want_coarray = 1; + gfc_conv_expr_descriptor (&se, e); if (sym->ts.type == BT_CHARACTER @@ -1994,7 +2002,7 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block) /* Temporaries, arising from TYPE IS, just need the descriptor of class arrays to be assigned directly. */ - else if (class_target && sym->attr.dimension + else if (class_target && (sym->attr.dimension || sym->attr.codimension) && (sym->ts.type == BT_DERIVED || unlimited)) { gfc_se se; @@ -2023,7 +2031,9 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block) gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (tmp))); } else - gfc_add_modify (&se.pre, sym->backend_decl, se.expr); + gfc_add_modify (&se.pre, sym->backend_decl, + build1 (VIEW_CONVERT_EXPR, + TREE_TYPE (sym->backend_decl), se.expr)); if (unlimited) { @@ -2043,7 +2053,7 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block) { gfc_se se; - gcc_assert (!sym->attr.dimension); + gcc_assert (!sym->attr.dimension && !sym->attr.codimension); gfc_init_se (&se, NULL); @@ -2123,6 +2133,14 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block) e->symtree->name); need_len_assign = false; } + else if (whole_array && (same_class || unlimited) + && e->ts.type == BT_CLASS && CLASS_DATA (e)->attr.codimension) + { + gfc_expr *class_e = gfc_find_and_cut_at_last_class_ref (e); + gfc_conv_expr (&se, class_e); + gfc_free_expr (class_e); + need_len_assign = false; + } else { /* For BT_CLASS and BT_DERIVED, this boils down to a pointer assign, @@ -2158,55 +2176,64 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block) tree ctree = gfc_get_class_from_expr (se.expr); tmp = TREE_TYPE (sym->backend_decl); - /* F2018:19.5.1.6 "If a selector has the POINTER attribute, - it shall be associated; the associate name is associated - with the target of the pointer and does not have the - POINTER attribute." */ - if (sym->ts.type == BT_CLASS - && e->ts.type == BT_CLASS && e->rank == 0 && ctree - && (!GFC_CLASS_TYPE_P (TREE_TYPE (se.expr)) - || CLASS_DATA (e)->attr.class_pointer)) + if (sym->ts.type == BT_CLASS && e->ts.type == BT_CLASS) { - tree stmp; - tree dtmp; - tree ctmp; + /* F2018:19.5.1.6 "If a selector has the POINTER attribute, + it shall be associated; the associate name is associated + with the target of the pointer and does not have the + POINTER attribute." */ + if (e->rank == 0 && ctree + && (!GFC_CLASS_TYPE_P (TREE_TYPE (se.expr)) + || CLASS_DATA (e)->attr.class_pointer)) + { + tree stmp; + tree dtmp; + tree ctmp; - ctmp = ctree; - dtmp = TREE_TYPE (TREE_TYPE (sym->backend_decl)); - ctree = gfc_create_var (dtmp, "class"); + ctmp = ctree; + dtmp = TREE_TYPE (TREE_TYPE (sym->backend_decl)); + ctree = gfc_create_var (dtmp, "class"); - if (IS_INFERRED_TYPE (e) - && !GFC_CLASS_TYPE_P (TREE_TYPE (se.expr))) - stmp = se.expr; - else - stmp = gfc_class_data_get (ctmp); - - /* Coarray scalar component expressions can emerge from - the front end as array elements of the _data field. */ - if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (stmp))) - stmp = gfc_conv_descriptor_data_get (stmp); - - if (!POINTER_TYPE_P (TREE_TYPE (stmp))) - stmp = gfc_build_addr_expr (NULL, stmp); - - dtmp = gfc_class_data_get (ctree); - stmp = fold_convert (TREE_TYPE (dtmp), stmp); - gfc_add_modify (&se.pre, dtmp, stmp); - stmp = gfc_class_vptr_get (ctmp); - dtmp = gfc_class_vptr_get (ctree); - stmp = fold_convert (TREE_TYPE (dtmp), stmp); - gfc_add_modify (&se.pre, dtmp, stmp); - if (UNLIMITED_POLY (sym)) - { - stmp = gfc_class_len_get (ctmp); - dtmp = gfc_class_len_get (ctree); + if (IS_INFERRED_TYPE (e) + && !GFC_CLASS_TYPE_P (TREE_TYPE (se.expr))) + stmp = se.expr; + else + stmp = gfc_class_data_get (ctmp); + + /* Coarray scalar component expressions can emerge from + the front end as array elements of the _data field. */ + if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (stmp))) + stmp = gfc_conv_descriptor_data_get (stmp); + + if (!POINTER_TYPE_P (TREE_TYPE (stmp))) + stmp = gfc_build_addr_expr (NULL, stmp); + + dtmp = gfc_class_data_get (ctree); + stmp = fold_convert (TREE_TYPE (dtmp), stmp); + gfc_add_modify (&se.pre, dtmp, stmp); + stmp = gfc_class_vptr_get (ctmp); + dtmp = gfc_class_vptr_get (ctree); stmp = fold_convert (TREE_TYPE (dtmp), stmp); gfc_add_modify (&se.pre, dtmp, stmp); - need_len_assign = false; + if (UNLIMITED_POLY (sym)) + { + stmp = gfc_class_len_get (ctmp); + dtmp = gfc_class_len_get (ctree); + stmp = fold_convert (TREE_TYPE (dtmp), stmp); + gfc_add_modify (&se.pre, dtmp, stmp); + need_len_assign = false; + } + se.expr = ctree; + } + else if (CLASS_DATA (sym)->attr.codimension) + { + gfc_conv_class_to_class (&se, e, sym->ts, false, false, false, + false); + tmp = se.expr; } - se.expr = ctree; } - tmp = gfc_build_addr_expr (tmp, se.expr); + if (!POINTER_TYPE_P (TREE_TYPE (se.expr))) + tmp = gfc_build_addr_expr (tmp, se.expr); } gfc_add_modify (&se.pre, sym->backend_decl, tmp); @@ -6708,6 +6735,7 @@ gfc_trans_allocate (gfc_code * code, gfc_omp_namelist *omp_allocate) newsym->n.sym->backend_decl = expr3; e3rhs = gfc_get_expr (); e3rhs->rank = code->expr3->rank; + e3rhs->corank = code->expr3->corank; e3rhs->symtree = newsym; /* Mark the symbol referenced or gfc_trans_assignment will bug. */ newsym->n.sym->attr.referenced = 1; @@ -6733,9 +6761,10 @@ gfc_trans_allocate (gfc_code * code, gfc_omp_namelist *omp_allocate) gfc_array_spec *arr; arr = gfc_get_array_spec (); arr->rank = e3rhs->rank; + arr->corank = e3rhs->corank; arr->type = AS_DEFERRED; /* Set the dimension and pointer attribute for arrays - to be on the safe side. */ + to be on the safe side. */ newsym->n.sym->attr.dimension = 1; newsym->n.sym->attr.pointer = 1; newsym->n.sym->as = arr; diff --git a/gcc/fortran/trans.cc b/gcc/fortran/trans.cc index d4c54093cbc..ce4618562b7 100644 --- a/gcc/fortran/trans.cc +++ b/gcc/fortran/trans.cc @@ -1404,11 +1404,12 @@ gfc_add_finalizer_call (stmtblock_t *block, gfc_expr *expr2, ref->next = NULL; } - if (expr->ts.type == BT_CLASS - && !expr2->rank - && !expr2->ref - && CLASS_DATA (expr2->symtree->n.sym)->as) - expr->rank = CLASS_DATA (expr2->symtree->n.sym)->as->rank; + if (expr->ts.type == BT_CLASS && (!expr2->rank || !expr2->corank) + && !expr2->ref && CLASS_DATA (expr2->symtree->n.sym)->as) + { + expr->rank = CLASS_DATA (expr2->symtree->n.sym)->as->rank; + expr->corank = CLASS_DATA (expr2->symtree->n.sym)->as->corank; + } stmtblock_t tmp_block; gfc_start_block (&tmp_block);