diff options
author | Jakub Jelinek <jakub@redhat.com> | 2005-08-06 12:00:53 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2005-08-06 12:00:53 +0200 |
commit | a8006d0933c8c954b134152c1fb60a379c7fb846 (patch) | |
tree | 51307a287fe8c7944a34211fdcee41233244ad4a /gcc/fortran | |
parent | b17775aba4c709c1fc3f19af33d50b025e3891f4 (diff) | |
download | gcc-a8006d0933c8c954b134152c1fb60a379c7fb846.zip gcc-a8006d0933c8c954b134152c1fb60a379c7fb846.tar.gz gcc-a8006d0933c8c954b134152c1fb60a379c7fb846.tar.bz2 |
re PR fortran/18833 (ICE 'missing spec' on integer/char equivalence)
PR fortran/18833
PR fortran/20850
* primary.c (match_varspec): If equiv_flag, don't look at sym's
attributes, call gfc_match_array_ref up to twice and don't do any
substring or component processing.
* resolve.c (resolve_equivalence): Transform REF_ARRAY into
REF_SUBSTRING or nothing if needed. Check that substrings
don't have zero length.
* gfortran.dg/equiv_1.f90: New test.
* gfortran.dg/equiv_2.f90: New test.
* gfortran.fortran-torture/execute/equiv_2.f90: New test.
* gfortran.fortran-torture/execute/equiv_3.f90: New test.
* gfortran.fortran-torture/execute/equiv_4.f90: New test.
From-SVN: r102801
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/fortran/primary.c | 30 | ||||
-rw-r--r-- | gcc/fortran/resolve.c | 96 |
3 files changed, 118 insertions, 19 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index be0e9c9..49d9f1d 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,14 @@ +2005-08-06 Jakub Jelinek <jakub@redhat.com> + + PR fortran/18833 + PR fortran/20850 + * primary.c (match_varspec): If equiv_flag, don't look at sym's + attributes, call gfc_match_array_ref up to twice and don't do any + substring or component processing. + * resolve.c (resolve_equivalence): Transform REF_ARRAY into + REF_SUBSTRING or nothing if needed. Check that substrings + don't have zero length. + 2005-08-05 Thomas Koenig <Thomas.Koenig@online.de> * trans-expr.c (gfc_build_builtin_function_decls): Mark diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c index 888caff..34cc908 100644 --- a/gcc/fortran/primary.c +++ b/gcc/fortran/primary.c @@ -1517,28 +1517,42 @@ match_varspec (gfc_expr * primary, int equiv_flag) char name[GFC_MAX_SYMBOL_LEN + 1]; gfc_ref *substring, *tail; gfc_component *component; - gfc_symbol *sym; + gfc_symbol *sym = primary->symtree->n.sym; match m; tail = NULL; - if (primary->symtree->n.sym->attr.dimension - || (equiv_flag - && gfc_peek_char () == '(')) + if ((equiv_flag && gfc_peek_char () == '(') + || sym->attr.dimension) { - + /* In EQUIVALENCE, we don't know yet whether we are seeing + an array, character variable or array of character + variables. We'll leave the decision till resolve + time. */ tail = extend_ref (primary, tail); tail->type = REF_ARRAY; - m = gfc_match_array_ref (&tail->u.ar, primary->symtree->n.sym->as, - equiv_flag); + m = gfc_match_array_ref (&tail->u.ar, equiv_flag ? NULL : sym->as, + equiv_flag); if (m != MATCH_YES) return m; + + if (equiv_flag && gfc_peek_char () == '(') + { + tail = extend_ref (primary, tail); + tail->type = REF_ARRAY; + + m = gfc_match_array_ref (&tail->u.ar, NULL, equiv_flag); + if (m != MATCH_YES) + return m; + } } - sym = primary->symtree->n.sym; primary->ts = sym->ts; + if (equiv_flag) + return MATCH_YES; + if (sym->ts.type != BT_DERIVED || gfc_match_char ('%') != MATCH_YES) goto check_substring; diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 8718f4d..5910a1b 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -4757,7 +4757,7 @@ resolve_equivalence_derived (gfc_symbol *derived, gfc_symbol *sym, gfc_expr *e) sequence derived type containing a pointer at any level of component selection, an automatic object, a function name, an entry name, a result name, a named constant, a structure component, or a subobject of any of - the preceding objects. */ + the preceding objects. A substring shall not have length zero. */ static void resolve_equivalence (gfc_equiv *eq) @@ -4770,6 +4770,69 @@ resolve_equivalence (gfc_equiv *eq) for (; eq; eq = eq->eq) { e = eq->expr; + + e->ts = e->symtree->n.sym->ts; + /* match_varspec might not know yet if it is seeing + array reference or substring reference, as it doesn't + know the types. */ + if (e->ref && e->ref->type == REF_ARRAY) + { + gfc_ref *ref = e->ref; + sym = e->symtree->n.sym; + + if (sym->attr.dimension) + { + ref->u.ar.as = sym->as; + ref = ref->next; + } + + /* For substrings, convert REF_ARRAY into REF_SUBSTRING. */ + if (e->ts.type == BT_CHARACTER + && ref + && ref->type == REF_ARRAY + && ref->u.ar.dimen == 1 + && ref->u.ar.dimen_type[0] == DIMEN_RANGE + && ref->u.ar.stride[0] == NULL) + { + gfc_expr *start = ref->u.ar.start[0]; + gfc_expr *end = ref->u.ar.end[0]; + void *mem = NULL; + + /* Optimize away the (:) reference. */ + if (start == NULL && end == NULL) + { + if (e->ref == ref) + e->ref = ref->next; + else + e->ref->next = ref->next; + mem = ref; + } + else + { + ref->type = REF_SUBSTRING; + if (start == NULL) + start = gfc_int_expr (1); + ref->u.ss.start = start; + if (end == NULL && e->ts.cl) + end = gfc_copy_expr (e->ts.cl->length); + ref->u.ss.end = end; + ref->u.ss.length = e->ts.cl; + e->ts.cl = NULL; + } + ref = ref->next; + gfc_free (mem); + } + + /* Any further ref is an error. */ + if (ref) + { + gcc_assert (ref->type == REF_ARRAY); + gfc_error ("Syntax error in EQUIVALENCE statement at %L", + &ref->u.ar.where); + continue; + } + } + if (gfc_resolve_expr (e) == FAILURE) continue; @@ -4832,19 +4895,30 @@ resolve_equivalence (gfc_equiv *eq) continue; } - /* Shall not be a structure component. */ r = e->ref; while (r) { - if (r->type == REF_COMPONENT) - { - gfc_error ("Structure component '%s' at %L cannot be an " - "EQUIVALENCE object", - r->u.c.component->name, &e->where); - break; - } - r = r->next; - } + /* Shall not be a structure component. */ + if (r->type == REF_COMPONENT) + { + gfc_error ("Structure component '%s' at %L cannot be an " + "EQUIVALENCE object", + r->u.c.component->name, &e->where); + break; + } + + /* A substring shall not have length zero. */ + if (r->type == REF_SUBSTRING) + { + if (compare_bound (r->u.ss.start, r->u.ss.end) == CMP_GT) + { + gfc_error ("Substring at %L has length zero", + &r->u.ss.start->where); + break; + } + } + r = r->next; + } } } |