Dear All,

Once found, the fix for this PR is trivial. The generic name is only
to be found in the parent derived type. Since this is over-ridden in
the type extension, not only is the wrong symbol selected for the dtio
procedure but, being abstract, the procedure does not exist. The
mechanism is borrowed from resolve.c(resolve_typebound_generic_call).
This goes back with the generic procedure name and looks again for the
procedure in the type extension. The testcase is a dejagnuified
version of the original.

Bootstraps and regtests on x86_64/FC21 - OK for trunk?

Paul

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

    PR fortran/77657

    * interface.c (gfc_find_specific_dtio_proc): Borrow trick from
    resolve_typebound_generic_call to find dtio procedures that
    over-ride those in the declared type.

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

    PR fortran/77657
    * gfortran.dg/dtio_12.f90: New test.
Index: gcc/fortran/interface.c
===================================================================
*** gcc/fortran/interface.c     (revision 240270)
--- gcc/fortran/interface.c     (working copy)
*************** gfc_find_specific_dtio_proc (gfc_symbol
*** 4792,4797 ****
--- 4792,4800 ----
  
    if (tb_io_st != NULL)
      {
+       const char *genname;
+       gfc_symtree *st;
+ 
        tb_io_proc = tb_io_st->n.tb;
        gcc_assert (tb_io_proc != NULL);
        gcc_assert (tb_io_proc->is_generic);
*************** gfc_find_specific_dtio_proc (gfc_symbol
*** 4800,4806 ****
        specific_proc = tb_io_proc->u.generic->specific;
        gcc_assert (!specific_proc->is_generic);
  
!       dtio_sub = specific_proc->u.specific->n.sym;
      }
  
    if (tb_io_st != NULL)
--- 4803,4818 ----
        specific_proc = tb_io_proc->u.generic->specific;
        gcc_assert (!specific_proc->is_generic);
  
!       /* Go back and make sure that we have the right specific procedure.
!        Here we most likely have a procedure from the parent type, which
!        can be overridden in extensions.  */
!       genname = tb_io_proc->u.generic->specific_st->name;
!       st = gfc_find_typebound_proc (derived, NULL, genname,
!                                   true, &tb_io_proc->where);
!       if (st)
!       dtio_sub = st->n.tb->u.specific->n.sym;
!       else
!       dtio_sub = specific_proc->u.specific->n.sym;
      }
  
    if (tb_io_st != NULL)
Index: gcc/testsuite/gfortran.dg/dtio_12.f90
===================================================================
*** gcc/testsuite/gfortran.dg/dtio_12.f90       (revision 0)
--- gcc/testsuite/gfortran.dg/dtio_12.f90       (working copy)
***************
*** 0 ****
--- 1,74 ----
+ ! { dg-do run }
+ !
+ ! Test the fix for PR77657 in which the DTIO subroutine was not found,
+ ! which led to an error in attempting to link to the abstract interface.
+ !
+ ! Contributed by Damian Rouson  <dam...@sourceryinstitute.org>
+ !
+ MODULE abstract_parent
+   implicit none
+ 
+   type, abstract :: parent
+   contains
+     procedure(write_formatted_interface), deferred :: write_formatted
+     generic :: write(formatted) => write_formatted
+   end type parent
+ 
+   abstract interface
+     subroutine write_formatted_interface(this,unit,iotype,vlist,iostat,iomsg)
+       import parent
+       class(parent), intent(in) :: this
+       integer, intent(in) :: unit
+       character (len=*), intent(in) :: iotype
+       integer, intent(in) :: vlist(:)
+       integer, intent(out) :: iostat
+       character (len=*), intent(inout) :: iomsg
+     end subroutine
+   end interface
+ 
+ end module
+ 
+ module child_module
+   use abstract_parent, only : parent
+   implicit none
+ 
+   type, extends(parent) :: child
+     integer :: i = 99
+   contains
+     procedure :: write_formatted
+   end type
+ contains
+   subroutine write_formatted(this,unit,iotype,vlist,iostat,iomsg)
+     class(child), intent(in) :: this
+     integer, intent(in) :: unit
+     character (len=*), intent(in) :: iotype
+     integer, intent(in) :: vlist(:)
+     integer, intent(out) :: iostat
+     character (len=*), intent(inout) :: iomsg
+     write (unit, "(i4)") this%i
+   end subroutine
+ end module
+ 
+   use child_module, only : child
+   implicit none
+   type (child) :: baby
+   integer :: v(1), istat
+   character(20) :: msg
+   open (10, status = "scratch")
+   call baby%write_formatted(10, "abcd", v, istat, msg) ! Call the dtio proc 
directly
+   rewind (10)
+   read (10, *) msg
+   if (trim (msg) .ne. "99") call abort
+   rewind (10)
+   baby%i = 42
+   write (10,"(DT)") baby                               ! Call the dtio proc 
via the library
+   rewind (10)
+   read (10, *) msg
+   if (trim (msg) .ne. "42") call abort
+   rewind (10)
+   write (10,"(DT)") child (77)                         ! The original testcase
+   rewind (10)
+   read (10, *) msg
+   if (trim (msg) .ne. "77") call abort
+   close(10)
+ end

Reply via email to