re PR fortran/18833 (ICE 'missing spec' on integer/char equivalence)
authorJakub Jelinek <jakub@redhat.com>
Sat, 6 Aug 2005 10:00:53 +0000 (12:00 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Sat, 6 Aug 2005 10:00:53 +0000 (12:00 +0200)
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

gcc/fortran/ChangeLog
gcc/fortran/primary.c
gcc/fortran/resolve.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/equiv_1.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/equiv_2.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.fortran-torture/execute/equiv_2.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.fortran-torture/execute/equiv_3.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.fortran-torture/execute/equiv_4.f90 [new file with mode: 0644]

index be0e9c992acad72b8f0d3e9ecd0188d0f358bcc1..49d9f1d5d8c9b1ac22d964300a81cc3852272e68 100644 (file)
@@ -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
index 888caffa5c281748b402eeefa2ceea9457f68e67..34cc908ce95b9a84cc25dad222e8db9aac36b970 100644 (file)
@@ -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;
 
index 8718f4d45291c2e284e9e16a5603e7a427b84ed1..5910a1b0aaf3ed67a843b581b756dd5cf5836d11 100644 (file)
@@ -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;
+       }
     }    
 }      
 
index 8b37d466490b6a36b29d93f9bf4c3075c7cbbc39..5f0466a84d01e79a43b69f5b41eba72fd4041022 100644 (file)
@@ -1,3 +1,13 @@
+2005-08-06  Jakub Jelinek  <jakub@redhat.com>
+
+       PR fortran/18833
+       PR fortran/20850
+       * 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.
+
 2005-08-05  James A. Morrison  <phython@gcc.gnu.org>
 
        * gcc.c-torture/execute/vrp-5.c: New test.
diff --git a/gcc/testsuite/gfortran.dg/equiv_1.f90 b/gcc/testsuite/gfortran.dg/equiv_1.f90
new file mode 100644 (file)
index 0000000..8a8a8b9
--- /dev/null
@@ -0,0 +1,9 @@
+      program broken_equiv
+      real d (2)       ! { dg-error "Inconsistent equivalence rules" "d" }
+      real e           ! { dg-error "Inconsistent equivalence rules" "e" }
+      equivalence (d (1), e), (d (2), e)
+
+      real f (2)       ! { dg-error "Inconsistent equivalence rules" "f" }
+      double precision g (2) ! { dg-error "Inconsistent equivalence rules" "g" }
+      equivalence (f (1), g (1)), (f (2), g (2)) ! Not standard conforming
+      end
diff --git a/gcc/testsuite/gfortran.dg/equiv_2.f90 b/gcc/testsuite/gfortran.dg/equiv_2.f90
new file mode 100644 (file)
index 0000000..4bcdca1
--- /dev/null
@@ -0,0 +1,17 @@
+      subroutine broken_equiv1
+      character*4 h
+      character*3 i
+      equivalence (h(1:3), i(2:1))     ! { dg-error "has length zero" }
+      end subroutine
+
+      subroutine broken_equiv2
+      character*4 j
+      character*2 k
+      equivalence (j(2:3), k(1:5))     ! { dg-error "out of bounds" }
+      end subroutine
+
+      subroutine broken_equiv3
+      character*4 l
+      character*2 m
+      equivalence (l(2:3:4), m(1:2))   ! { dg-error "\[Ss\]yntax error" }
+      end subroutine
diff --git a/gcc/testsuite/gfortran.fortran-torture/execute/equiv_2.f90 b/gcc/testsuite/gfortran.fortran-torture/execute/equiv_2.f90
new file mode 100644 (file)
index 0000000..1c88ff9
--- /dev/null
@@ -0,0 +1,46 @@
+      subroutine test1
+      character*8 c
+      character*1 d, f
+      dimension d(2), f(2)
+      character*4 e
+      equivalence (c(1:1), d(1)), (c(3:5), e(2:4)), (c(6:6), f(2))
+      c='abcdefgh'
+      if (c.ne.'abcdefgh'.or.d(1).ne.'a'.or.d(2).ne.'b') call abort
+      if (e.ne.'bcde'.or.f(1).ne.'e'.or.f(2).ne.'f') call abort
+      end subroutine test1
+      subroutine test2
+      equivalence (c(1:1), d(1)), (c(3:5), e(2:4)), (c(6:6), f(2))
+      character*8 c
+      character*1 d, f
+      dimension d(2), f(2)
+      character*4 e
+      c='abcdefgh'
+      if (c.ne.'abcdefgh'.or.d(1).ne.'a'.or.d(2).ne.'b') call abort
+      if (e.ne.'bcde'.or.f(1).ne.'e'.or.f(2).ne.'f') call abort
+      end subroutine test2
+      subroutine test3
+      character*8 c
+      character*1 d, f
+      character*4 e
+      equivalence (c(1:1), d(1)), (c(3:5), e(2:4)), (c(6:6), f(2))
+      dimension d(2), f(2)
+      c='abcdefgh'
+      if (c.ne.'abcdefgh'.or.d(1).ne.'a'.or.d(2).ne.'b') call abort
+      if (e.ne.'bcde'.or.f(1).ne.'e'.or.f(2).ne.'f') call abort
+      end subroutine test3
+      subroutine test4
+      dimension d(2), f(2)
+      equivalence (c(1:1), d(1)), (c(3:5), e(2:4)), (c(6:6), f(2))
+      character*8 c
+      character*1 d, f
+      character*4 e
+      c='abcdefgh'
+      if (c.ne.'abcdefgh'.or.d(1).ne.'a'.or.d(2).ne.'b') call abort
+      if (e.ne.'bcde'.or.f(1).ne.'e'.or.f(2).ne.'f') call abort
+      end subroutine test4
+      program main
+      call test1
+      call test2
+      call test3
+      call test4
+      end program main
diff --git a/gcc/testsuite/gfortran.fortran-torture/execute/equiv_3.f90 b/gcc/testsuite/gfortran.fortran-torture/execute/equiv_3.f90
new file mode 100644 (file)
index 0000000..75103e2
--- /dev/null
@@ -0,0 +1,13 @@
+      subroutine test1
+      type t
+      sequence
+      character(8) c
+      end type t
+      type(t) :: tc, td
+      equivalence (tc, td)
+      tc%c='abcdefgh'
+      if (tc%c.ne.'abcdefgh'.or.td%c(1:1).ne.'a') call abort
+      end subroutine test1
+      program main
+      call test1
+      end program main
diff --git a/gcc/testsuite/gfortran.fortran-torture/execute/equiv_4.f90 b/gcc/testsuite/gfortran.fortran-torture/execute/equiv_4.f90
new file mode 100644 (file)
index 0000000..9c23278
--- /dev/null
@@ -0,0 +1,54 @@
+      subroutine test1
+      character*8 c
+      character*2 d, f
+      dimension d(2), f(2)
+      character*4 e
+      equivalence (c(1:1), d(1)(2:)), (c(3:5), e(2:4))
+      equivalence (c(6:6), f(2)(:))
+      d(1)='AB'
+      c='abcdefgh'
+      if (c.ne.'abcdefgh'.or.d(1).ne.'Aa'.or.d(2).ne.'bc') call abort
+      if (e.ne.'bcde'.or.f(1).ne.'de'.or.f(2).ne.'fg') call abort
+      end subroutine test1
+      subroutine test2
+      equivalence (c(1:1), d(1)(2:2)), (c(3:5), e(2:4))
+      equivalence (c(6:6), f(2)(1:))
+      character*8 c
+      character*2 d, f
+      dimension d(2), f(2)
+      character*4 e
+      d(1)='AB'
+      c='abcdefgh'
+      if (c.ne.'abcdefgh'.or.d(1).ne.'Aa'.or.d(2).ne.'bc') call abort
+      if (e.ne.'bcde'.or.f(1).ne.'de'.or.f(2).ne.'fg') call abort
+      end subroutine test2
+      subroutine test3
+      character*8 c
+      character*2 d, f
+      character*4 e
+      equivalence (c(1:1), d(1)(2:)), (c(3:5), e(2:4))
+      equivalence (c(6:6), f(2)(:1))
+      dimension d(2), f(2)
+      d(1)='AB'
+      c='abcdefgh'
+      if (c.ne.'abcdefgh'.or.d(1).ne.'Aa'.or.d(2).ne.'bc') call abort
+      if (e.ne.'bcde'.or.f(1).ne.'de'.or.f(2).ne.'fg') call abort
+      end subroutine test3
+      subroutine test4
+      dimension d(2), f(2)
+      equivalence (c(1:1), d(1)(2:2)), (c(3:5), e(2:4))
+      equivalence (c(6:6), f(2)(1:2))
+      character*8 c
+      character*2 d, f
+      character*4 e
+      d(1)='AB'
+      c='abcdefgh'
+      if (c.ne.'abcdefgh'.or.d(1).ne.'Aa'.or.d(2).ne.'bc') call abort
+      if (e.ne.'bcde'.or.f(1).ne.'de'.or.f(2).ne.'fg') call abort
+      end subroutine test4
+      program main
+      call test1
+      call test2
+      call test3
+      call test4
+      end program main