diff options
Diffstat (limited to 'gcc/fortran/primary.c')
-rw-r--r-- | gcc/fortran/primary.c | 74 |
1 files changed, 60 insertions, 14 deletions
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c index f25de23..c0777c4 100644 --- a/gcc/fortran/primary.c +++ b/gcc/fortran/primary.c @@ -1733,7 +1733,9 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag, || (sym->attr.dimension && !sym->attr.proc_pointer && !gfc_is_proc_ptr_comp (primary, NULL) && !(gfc_matching_procptr_assignment - && sym->attr.flavor == FL_PROCEDURE))) + && sym->attr.flavor == FL_PROCEDURE)) + || (sym->ts.type == BT_CLASS + && sym->ts.u.derived->components->attr.dimension)) { /* In EQUIVALENCE, we don't know yet whether we are seeing an array, character variable or array of character @@ -1767,7 +1769,8 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag, && gfc_get_default_type (sym->name, sym->ns)->type == BT_DERIVED) gfc_set_default_type (sym, 0, sym->ns); - if (sym->ts.type != BT_DERIVED || gfc_match_char ('%') != MATCH_YES) + if ((sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS) + || gfc_match_char ('%') != MATCH_YES) goto check_substring; sym = sym->ts.u.derived; @@ -1865,8 +1868,21 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag, if (m != MATCH_YES) return m; } + else if (component->ts.type == BT_CLASS + && component->ts.u.derived->components->as != NULL + && !component->attr.proc_pointer) + { + tail = extend_ref (primary, tail); + tail->type = REF_ARRAY; - if (component->ts.type != BT_DERIVED + m = gfc_match_array_ref (&tail->u.ar, + component->ts.u.derived->components->as, + equiv_flag); + if (m != MATCH_YES) + return m; + } + + if ((component->ts.type != BT_DERIVED && component->ts.type != BT_CLASS) || gfc_match_char ('%') != MATCH_YES) break; @@ -1875,7 +1891,7 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag, check_substring: unknown = false; - if (primary->ts.type == BT_UNKNOWN) + if (primary->ts.type == BT_UNKNOWN && sym->attr.flavor != FL_DERIVED) { if (gfc_get_default_type (sym->name, sym->ns)->type == BT_CHARACTER) { @@ -1943,23 +1959,35 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts) int dimension, pointer, allocatable, target; symbol_attribute attr; gfc_ref *ref; + gfc_symbol *sym; + gfc_component *comp; if (expr->expr_type != EXPR_VARIABLE && expr->expr_type != EXPR_FUNCTION) gfc_internal_error ("gfc_variable_attr(): Expression isn't a variable"); ref = expr->ref; - attr = expr->symtree->n.sym->attr; + sym = expr->symtree->n.sym; + attr = sym->attr; - dimension = attr.dimension; - pointer = attr.pointer; - allocatable = attr.allocatable; + if (sym->ts.type == BT_CLASS) + { + dimension = sym->ts.u.derived->components->attr.dimension; + pointer = sym->ts.u.derived->components->attr.pointer; + allocatable = sym->ts.u.derived->components->attr.allocatable; + } + else + { + dimension = attr.dimension; + pointer = attr.pointer; + allocatable = attr.allocatable; + } target = attr.target; if (pointer || attr.proc_pointer) target = 1; if (ts != NULL && expr->ts.type == BT_UNKNOWN) - *ts = expr->symtree->n.sym->ts; + *ts = sym->ts; for (; ref; ref = ref->next) switch (ref->type) @@ -1988,10 +2016,11 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts) break; case REF_COMPONENT: - attr = ref->u.c.component->attr; + comp = ref->u.c.component; + attr = comp->attr; if (ts != NULL) { - *ts = ref->u.c.component->ts; + *ts = comp->ts; /* Don't set the string length if a substring reference follows. */ if (ts->type == BT_CHARACTER @@ -1999,8 +2028,16 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts) ts->u.cl = NULL; } - pointer = ref->u.c.component->attr.pointer; - allocatable = ref->u.c.component->attr.allocatable; + if (comp->ts.type == BT_CLASS) + { + pointer = comp->ts.u.derived->components->attr.pointer; + allocatable = comp->ts.u.derived->components->attr.allocatable; + } + else + { + pointer = comp->attr.pointer; + allocatable = comp->attr.allocatable; + } if (pointer || attr.proc_pointer) target = 1; @@ -2037,7 +2074,16 @@ gfc_expr_attr (gfc_expr *e) gfc_clear_attr (&attr); if (e->value.function.esym != NULL) - attr = e->value.function.esym->result->attr; + { + gfc_symbol *sym = e->value.function.esym->result; + attr = sym->attr; + if (sym->ts.type == BT_CLASS) + { + attr.dimension = sym->ts.u.derived->components->attr.dimension; + attr.pointer = sym->ts.u.derived->components->attr.pointer; + attr.allocatable = sym->ts.u.derived->components->attr.allocatable; + } + } else attr = gfc_variable_attr (e, NULL); |