aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/primary.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran/primary.c')
-rw-r--r--gcc/fortran/primary.c74
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);