diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc index 663fe63dea6..c668baeef8c 100644 --- a/gcc/fortran/expr.cc +++ b/gcc/fortran/expr.cc @@ -6474,7 +6474,8 @@ gfc_check_vardef_context (gfc_expr* e, bool pointer, bool alloc_obj, { if (context) { - if (assoc->target->expr_type == EXPR_VARIABLE) + if (assoc->target->expr_type == EXPR_VARIABLE + && gfc_has_vector_index (assoc->target)) gfc_error ("%qs at %L associated to vector-indexed target" " cannot be used in a variable definition" " context (%s)", diff --git a/gcc/fortran/match.cc b/gcc/fortran/match.cc index c926f38058f..05995c6f97f 100644 --- a/gcc/fortran/match.cc +++ b/gcc/fortran/match.cc @@ -6341,12 +6341,13 @@ copy_ts_from_selector_to_associate (gfc_expr *associate, gfc_expr *selector) else if (selector->ts.type == BT_CLASS && CLASS_DATA (selector) && CLASS_DATA (selector)->as - && ref && ref->type == REF_ARRAY) + && ((ref && ref->type == REF_ARRAY) + || selector->expr_type == EXPR_OP)) { /* Ensure that the array reference type is set. We cannot use gfc_resolve_expr at this point, so the usable parts of resolve.cc(resolve_array_ref) are employed to do it. */ - if (ref->u.ar.type == AR_UNKNOWN) + if (ref && ref->u.ar.type == AR_UNKNOWN) { ref->u.ar.type = AR_ELEMENT; for (int i = 0; i < ref->u.ar.dimen + ref->u.ar.codimen; i++) @@ -6360,7 +6361,7 @@ copy_ts_from_selector_to_associate (gfc_expr *associate, gfc_expr *selector) } } - if (ref->u.ar.type == AR_FULL) + if (!ref || ref->u.ar.type == AR_FULL) selector->rank = CLASS_DATA (selector)->as->rank; else if (ref->u.ar.type == AR_SECTION) selector->rank = ref->u.ar.dimen; @@ -6372,12 +6373,15 @@ copy_ts_from_selector_to_associate (gfc_expr *associate, gfc_expr *selector) if (rank) { - for (int i = 0; i < ref->u.ar.dimen + ref->u.ar.codimen; i++) - if (ref->u.ar.dimen_type[i] == DIMEN_ELEMENT - || (ref->u.ar.dimen_type[i] == DIMEN_UNKNOWN - && ref->u.ar.end[i] == NULL - && ref->u.ar.stride[i] == NULL)) - rank--; + if (ref) + { + for (int i = 0; i < ref->u.ar.dimen + ref->u.ar.codimen; i++) + if (ref->u.ar.dimen_type[i] == DIMEN_ELEMENT + || (ref->u.ar.dimen_type[i] == DIMEN_UNKNOWN + && ref->u.ar.end[i] == NULL + && ref->u.ar.stride[i] == NULL)) + rank--; + } if (rank) { diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc index 861f69ac20f..9f4dc072645 100644 --- a/gcc/fortran/resolve.cc +++ b/gcc/fortran/resolve.cc @@ -4138,6 +4138,16 @@ resolve_operator (gfc_expr *e) bool dual_locus_error; bool t = true; + /* Reduce stacked parentheses to single pair */ + while (e->expr_type == EXPR_OP + && e->value.op.op == INTRINSIC_PARENTHESES + && e->value.op.op1->expr_type == EXPR_OP + && e->value.op.op1->value.op.op == INTRINSIC_PARENTHESES) + { + gfc_expr *tmp = gfc_copy_expr (e->value.op.op1); + gfc_replace_expr (e, tmp); + } + /* Resolve all subnodes-- give them types. */ switch (e->value.op.op) @@ -9451,8 +9461,25 @@ fixup_array_ref (gfc_expr **expr1, gfc_expr *expr2, { gfc_ref *nref = (*expr1)->ref; gfc_symbol *sym1 = (*expr1)->symtree->n.sym; - gfc_symbol *sym2 = expr2 ? expr2->symtree->n.sym : NULL; + gfc_symbol *sym2; + gfc_expr *selector = gfc_copy_expr (expr2); + (*expr1)->rank = rank; + if (selector) + { + gfc_resolve_expr (selector); + if (selector->expr_type == EXPR_OP + && selector->value.op.op == INTRINSIC_PARENTHESES) + sym2 = selector->value.op.op1->symtree->n.sym; + else if (selector->expr_type == EXPR_VARIABLE + || selector->expr_type == EXPR_FUNCTION) + sym2 = selector->symtree->n.sym; + else + gcc_unreachable (); + } + else + sym2 = NULL; + if (sym1->ts.type == BT_CLASS) { if ((*expr1)->ts.type != BT_CLASS) diff --git a/gcc/testsuite/gfortran.dg/associate_55.f90 b/gcc/testsuite/gfortran.dg/associate_55.f90 index 2b9e8c727f9..245dbfc7218 100644 --- a/gcc/testsuite/gfortran.dg/associate_55.f90 +++ b/gcc/testsuite/gfortran.dg/associate_55.f90 @@ -26,7 +26,7 @@ contains class(test_t), intent(inout) :: obj integer, intent(in) :: a associate (state => obj%state(TEST_STATES)) ! { dg-error "no IMPLICIT type" } - state = a ! { dg-error "vector-indexed target" } + state = a ! { dg-error "cannot be used in a variable definition context" } ! state(TEST_STATE) = a end associate end subroutine test_alter_state2