Dear All,

Please find attached a patch to clean up the various issues with
errors in DTIO procedures. The tests were all provided by Gerhard
Steinmetz for which thanks are due.

I intend to commit this patch as 'obvious' tomorrow morning unless
there are any objections in the meantime.

Bootstrapped and regtested on x86_64/FC21 - OK for trunk?

Paul

2016-09-21  Paul Thomas  <pa...@gcc.gnu.org>

    * interface.c (check_dtio_interface1): Introduce errors for
    alternate returns and incorrect numbers of arguments.
    (gfc_find_specific_dtio_proc): Return cleanly if the derived
    type either doesn't exist or has no namespace.

2016-09-21  Paul Thomas  <pa...@gcc.gnu.org>

    * gfortran.dg/dtio_13.f90: New test.
Index: gcc/fortran/interface.c
===================================================================
*** gcc/fortran/interface.c     (revision 240301)
--- gcc/fortran/interface.c     (working copy)
*************** check_dtio_interface1 (gfc_symbol *deriv
*** 4629,4635 ****
  
        for (intr = tb_io_st->n.sym->generic; intr; intr = intr->next)
        {
!         if (intr->sym && intr->sym->formal
              && ((intr->sym->formal->sym->ts.type == BT_CLASS
                   && CLASS_DATA (intr->sym->formal->sym)->ts.u.derived
                                                             == derived)
--- 4629,4635 ----
  
        for (intr = tb_io_st->n.sym->generic; intr; intr = intr->next)
        {
!         if (intr->sym && intr->sym->formal && intr->sym->formal->sym
              && ((intr->sym->formal->sym->ts.type == BT_CLASS
                   && CLASS_DATA (intr->sym->formal->sym)->ts.u.derived
                                                             == derived)
*************** check_dtio_interface1 (gfc_symbol *deriv
*** 4639,4644 ****
--- 4639,4650 ----
              dtio_sub = intr->sym;
              break;
            }
+         else if (intr->sym && intr->sym->formal && !intr->sym->formal->sym)
+           {
+             gfc_error ("Alternate return at %L is not permitted in a DTIO "
+                        "procedure", &intr->sym->declared_at);
+             return;
+           }
        }
  
        if (dtio_sub == NULL)
*************** check_dtio_interface1 (gfc_symbol *deriv
*** 4647,4655 ****
  
    gcc_assert (dtio_sub);
    if (!dtio_sub->attr.subroutine)
!     gfc_error ("DTIO procedure %s at %L must be a subroutine",
               dtio_sub->name, &dtio_sub->declared_at);
  
    /* Now go through the formal arglist.  */
    arg_num = 1;
    for (formal = dtio_sub->formal; formal; formal = formal->next, arg_num++)
--- 4653,4680 ----
  
    gcc_assert (dtio_sub);
    if (!dtio_sub->attr.subroutine)
!     gfc_error ("DTIO procedure '%s' at %L must be a subroutine",
               dtio_sub->name, &dtio_sub->declared_at);
  
+   arg_num = 0;
+   for (formal = dtio_sub->formal; formal; formal = formal->next)
+     arg_num++;
+ 
+   if (arg_num < (formatted ? 6 : 4))
+     {
+       gfc_error ("Too few dummy arguments in DTIO procedure '%s' at %L",
+                dtio_sub->name, &dtio_sub->declared_at);
+       return;
+     }
+ 
+   if (arg_num > (formatted ? 6 : 4))
+     {
+       gfc_error ("Too many dummy arguments in DTIO procedure '%s' at %L",
+                dtio_sub->name, &dtio_sub->declared_at);
+       return;
+     }
+ 
+ 
    /* Now go through the formal arglist.  */
    arg_num = 1;
    for (formal = dtio_sub->formal; formal; formal = formal->next, arg_num++)
*************** check_dtio_interface1 (gfc_symbol *deriv
*** 4657,4662 ****
--- 4682,4695 ----
        if (!formatted && arg_num == 3)
        arg_num = 5;
        fsym = formal->sym;
+ 
+       if (fsym == NULL)
+       {
+         gfc_error ("Alternate return at %L is not permitted in a DTIO "
+                    "procedure", &dtio_sub->declared_at);
+         return;
+       }
+ 
        switch (arg_num)
        {
        case(1):                        /* DTV  */
*************** gfc_find_specific_dtio_proc (gfc_symbol
*** 4823,4828 ****
--- 4856,4864 ----
    for (extended = derived; extended;
         extended = gfc_get_derived_super_type (extended))
      {
+       if (extended == NULL || extended->ns == NULL)
+       return NULL;
+ 
        if (formatted == true)
        {
          if (write == true)
Index: gcc/testsuite/gfortran.dg/dtio_13.f90
===================================================================
*** gcc/testsuite/gfortran.dg/dtio_13.f90       (revision 0)
--- gcc/testsuite/gfortran.dg/dtio_13.f90       (working copy)
***************
*** 0 ****
--- 1,144 ----
+ ! { dg-do compile }
+ ! { dg-options -std=legacy }
+ !
+ ! Test elimination of various segfaults and ICEs on error recovery.
+ !
+ ! Contributed by Gerhard Steinmetz  <gerhard.steinmetz.fort...@t-online.de>
+ !
+ module m1
+    type t
+    end type
+    interface write(formatted)
+       module procedure s
+    end interface
+ contains
+    subroutine s(dtv,unit,iotype,vlist,extra,iostat,iomsg) ! { dg-error "Too 
many dummy arguments" }
+       class(t), intent(in) :: dtv
+       integer, intent(in) :: unit
+       character(len=*), intent(in) :: iotype
+       integer, intent(in) :: vlist(:)
+       integer, intent(out) :: iostat
+       character(len=*), intent(inout) :: iomsg
+    end
+ end
+ 
+ module m2
+    type t
+    end type
+    interface read(formatted)
+       module procedure s
+    end interface
+ contains
+    subroutine s(dtv,unit,iotype,vlist,iostat,iomsg,extra) ! { dg-error "Too 
many dummy arguments" }
+       class(t), intent(inout) :: dtv
+       integer, intent(in) :: unit
+       character(len=*), intent(in) :: iotype
+       integer, intent(in) :: vlist(:)
+       integer, intent(out) :: iostat
+       character(len=*), intent(inout) :: iomsg
+    end
+ end
+ 
+ module m3
+    type t
+    end type
+    interface read(formatted)
+       module procedure s
+    end interface
+ contains
+    subroutine s(dtv,extra,unit,iotype,vlist,iostat,iomsg) ! { dg-error "Too 
many dummy arguments" }
+       class(t), intent(inout) :: dtv
+       integer, intent(in) :: unit
+       character(len=*), intent(in) :: iotype
+       integer, intent(in) :: vlist(:)
+       integer, intent(out) :: iostat
+       character(len=*), intent(inout) :: iomsg
+    end
+ end
+ 
+ module m4
+    type t
+    end type
+    interface write(unformatted)
+       module procedure s
+    end interface
+ contains
+    subroutine s(*) ! { dg-error "Alternate return" }
+    end
+ end
+ 
+ module m5
+    type t
+    contains
+       procedure :: s
+       generic :: write(unformatted) => s
+    end type
+ contains
+    subroutine s(dtv, *) ! { dg-error "Too few dummy arguments" }
+       class(t), intent(out) :: dtv
+    end
+ end
+ 
+ module m6
+    type t
+       character(len=20) :: name
+       integer(4) :: age
+    contains
+       procedure :: pruf
+       generic :: read(unformatted) => pruf
+    end type
+ contains
+    subroutine pruf (dtv,unit,*,iomsg) ! { dg-error "Alternate return" }
+       class(t), intent(inout) :: dtv
+       integer, intent(in) :: unit
+       character(len=*), intent(inout) :: iomsg
+       write (unit=unit, iostat=iostat, iomsg=iomsg) dtv%name, dtv%age
+    end
+ end
+ 
+ module m7
+    type t
+       character(len=20) :: name
+       integer(4) :: age
+    contains
+       procedure :: pruf
+       generic :: read(unformatted) => pruf
+    end type
+ contains
+    subroutine pruf (dtv,unit,iostat) ! { dg-error "Too few dummy arguments" }
+       class(t), intent(inout) :: dtv
+       integer, intent(in) :: unit
+       integer, intent(out) :: iostat
+       character(len=1) :: iomsg
+       write (unit=unit, iostat=iostat, iomsg=iomsg) dtv%name, dtv%age
+    end
+ end
+ 
+ module m
+    type t
+       character(len=20) :: name
+       integer(4) :: age
+    contains
+       procedure :: pruf
+       generic :: read(unformatted) => pruf
+    end type
+ contains
+    subroutine pruf (dtv,unit,iostat,iomsg)
+       class(t), intent(inout) :: dtv
+       integer, intent(in) :: unit
+       integer, intent(out) :: iostat
+       character(len=*), intent(inout) :: iomsg
+       write (unit=unit, iostat=iostat, iomsg=iomsg) dtv%name, dtv%age
+    end
+ end
+ program test
+    use m
+    character(3) :: a, b
+    class(t) :: chairman ! { dg-error "must be dummy, allocatable or pointer" }
+    open (unit=71, file='myunformatted_data.dat', form='unformatted')
+ ! The following error is spurious and is eliminated if previous error is 
corrected.
+ ! TODO Although better than an ICE, fix me.
+    read (71) a, chairman, b ! { dg-error "cannot be polymorphic" }
+    close (unit=71)
+ end
+ 

Reply via email to