diff options
Diffstat (limited to 'gcc/fortran/resolve.c')
-rw-r--r-- | gcc/fortran/resolve.c | 127 |
1 files changed, 86 insertions, 41 deletions
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 81d5ed8..4ab9df6 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -2034,16 +2034,16 @@ is_scalar_expr_ptr (gfc_expr *expr) } else { - /* We have constant lower and upper bounds. If the - difference between is 1, it can be considered a - scalar. */ - start = (int) mpz_get_si - (ref->u.ar.as->lower[0]->value.integer); - end = (int) mpz_get_si - (ref->u.ar.as->upper[0]->value.integer); - if (end - start + 1 != 1) - retval = FAILURE; - } + /* We have constant lower and upper bounds. If the + difference between is 1, it can be considered a + scalar. */ + start = (int) mpz_get_si + (ref->u.ar.as->lower[0]->value.integer); + end = (int) mpz_get_si + (ref->u.ar.as->upper[0]->value.integer); + if (end - start + 1 != 1) + retval = FAILURE; + } } else retval = FAILURE; @@ -5181,8 +5181,8 @@ resolve_deallocate_expr (gfc_expr *e) if (allocatable == 0 && attr.pointer == 0) { bad: - gfc_error ("Expression in DEALLOCATE statement at %L must be " - "ALLOCATABLE or a POINTER", &e->where); + gfc_error ("Allocate-object at %L must be ALLOCATABLE or a POINTER", + &e->where); } if (check_intent_in @@ -5267,11 +5267,6 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code) if (gfc_resolve_expr (e) == FAILURE) return FAILURE; - if (code->expr && code->expr->expr_type == EXPR_VARIABLE) - sym = code->expr->symtree->n.sym; - else - sym = NULL; - /* Make sure the expression is allocatable or a pointer. If it is pointer, the next-to-last reference must be a pointer. */ @@ -5290,14 +5285,6 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code) pointer = e->symtree->n.sym->attr.pointer; dimension = e->symtree->n.sym->attr.dimension; - if (sym == e->symtree->n.sym && sym->ts.type != BT_DERIVED) - { - gfc_error ("The STAT variable '%s' in an ALLOCATE statement must " - "not be allocated in the same statement at %L", - sym->name, &e->where); - return FAILURE; - } - for (ref = e->ref; ref; ref2 = ref, ref = ref->next) { if (pointer) @@ -5328,8 +5315,8 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code) if (allocatable == 0 && pointer == 0) { - gfc_error ("Expression in ALLOCATE statement at %L must be " - "ALLOCATABLE or a POINTER", &e->where); + gfc_error ("Allocate-object at %L must be ALLOCATABLE or a POINTER", + &e->where); return FAILURE; } @@ -5424,26 +5411,83 @@ check_symbols: static void resolve_allocate_deallocate (gfc_code *code, const char *fcn) { - gfc_symbol *s = NULL; - gfc_alloc *a; + gfc_expr *stat, *errmsg, *pe, *qe; + gfc_alloc *a, *p, *q; + + stat = code->expr ? code->expr : NULL; - if (code->expr) - s = code->expr->symtree->n.sym; + errmsg = code->expr2 ? code->expr2 : NULL; - if (s) + /* Check the stat variable. */ + if (stat) { - if (s->attr.intent == INTENT_IN) - gfc_error ("STAT variable '%s' of %s statement at %C cannot " - "be INTENT(IN)", s->name, fcn); + if (stat->symtree->n.sym->attr.intent == INTENT_IN) + gfc_error ("Stat-variable '%s' at %L cannot be INTENT(IN)", + stat->symtree->n.sym->name, &stat->where); - if (gfc_pure (NULL) && gfc_impure_variable (s)) - gfc_error ("Illegal STAT variable in %s statement at %C " - "for a PURE procedure", fcn); + if (gfc_pure (NULL) && gfc_impure_variable (stat->symtree->n.sym)) + gfc_error ("Illegal stat-variable at %L for a PURE procedure", + &stat->where); + + if (stat->ts.type != BT_INTEGER + && !(stat->ref && (stat->ref->type == REF_ARRAY + || stat->ref->type == REF_COMPONENT))) + gfc_error ("Stat-variable at %L must be a scalar INTEGER " + "variable", &stat->where); + + for (p = code->ext.alloc_list; p; p = p->next) + if (p->expr->symtree->n.sym->name == stat->symtree->n.sym->name) + gfc_error ("Stat-variable at %L shall not be %sd within " + "the same %s statement", &stat->where, fcn, fcn); } - if (s && code->expr->ts.type != BT_INTEGER) - gfc_error ("STAT tag in %s statement at %L must be " - "of type INTEGER", fcn, &code->expr->where); + /* Check the errmsg variable. */ + if (errmsg) + { + if (!stat) + gfc_warning ("ERRMSG at %L is useless without a STAT tag", + &errmsg->where); + + if (errmsg->symtree->n.sym->attr.intent == INTENT_IN) + gfc_error ("Errmsg-variable '%s' at %L cannot be INTENT(IN)", + errmsg->symtree->n.sym->name, &errmsg->where); + + if (gfc_pure (NULL) && gfc_impure_variable (errmsg->symtree->n.sym)) + gfc_error ("Illegal errmsg-variable at %L for a PURE procedure", + &errmsg->where); + + if (errmsg->ts.type != BT_CHARACTER + && !(errmsg->ref + && (errmsg->ref->type == REF_ARRAY + || errmsg->ref->type == REF_COMPONENT))) + gfc_error ("Errmsg-variable at %L must be a scalar CHARACTER " + "variable", &errmsg->where); + + for (p = code->ext.alloc_list; p; p = p->next) + if (p->expr->symtree->n.sym->name == errmsg->symtree->n.sym->name) + gfc_error ("Errmsg-variable at %L shall not be %sd within " + "the same %s statement", &errmsg->where, fcn, fcn); + } + + /* Check that an allocate-object appears only once in the statement. + FIXME: Checking derived types is disabled. */ + for (p = code->ext.alloc_list; p; p = p->next) + { + pe = p->expr; + if ((pe->ref && pe->ref->type != REF_COMPONENT) + && (pe->symtree->n.sym->ts.type != BT_DERIVED)) + { + for (q = p->next; q; q = q->next) + { + qe = q->expr; + if ((qe->ref && qe->ref->type != REF_COMPONENT) + && (qe->symtree->n.sym->ts.type != BT_DERIVED) + && (pe->symtree->n.sym->name == qe->symtree->n.sym->name)) + gfc_error ("Allocate-object at %L also appears at %L", + &pe->where, &qe->where); + } + } + } if (strcmp (fcn, "ALLOCATE") == 0) { @@ -5457,6 +5501,7 @@ resolve_allocate_deallocate (gfc_code *code, const char *fcn) } } + /************ SELECT CASE resolution subroutines ************/ /* Callback function for our mergesort variant. Determines interval |