http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55057



             Bug #: 55057

           Summary: [OOP] wrong result with abstract type

    Classification: Unclassified

           Product: gcc

           Version: 4.8.0

            Status: UNCONFIRMED

          Severity: normal

          Priority: P3

         Component: fortran

        AssignedTo: unassig...@gcc.gnu.org

        ReportedBy: mreste...@gmail.com





The attached code compiles and runs, but the results are not correct.

Unfortunately the reduced test is not very much reduced, however I

think the problem is that in alt the storages of x, y and z overlap.



Notice that the problem is present only when calling alt through an

additional subroutine sub, as indicated by the comments.



gfortran --version

GNU Fortran (GCC) 4.8.0 20121024 (experimental)



./test 

 All the following values should be 2.0

   2.00000000    

   2.00000000    

   2.00000000    

 All the following values should be 2.0

   2.00000000    

   3.00000000    

   6.00000000    







module m



 implicit none



 public :: &

   at1, at2, t1, t2, sub



 private



 type, abstract :: at1

 contains

  procedure(i_copy), deferred, pass(z) :: copy

  procedure(i_incr), deferred, pass(x) :: incr

  procedure(i_tims), deferred, pass(x) :: tims

  procedure(i_show), deferred, pass(x) :: show

  procedure,                   pass(z) :: add

  procedure,                   pass(z) :: mlt

  procedure,                   pass(z) :: alt

 end type at1

 abstract interface

  pure subroutine i_copy(z,x)

   import :: at1

   implicit none

   class(at1), intent(in)    :: x

   class(at1), intent(inout) :: z

  end subroutine i_copy

 end interface

 abstract interface

  pure subroutine i_incr(x,y)

   import :: at1

   implicit none

   class(at1), intent(in)    :: y

   class(at1), intent(inout) :: x

  end subroutine i_incr

 end interface

 abstract interface

  pure subroutine i_tims(x,r)

   import :: at1

   implicit none

   real,       intent(in)    :: r

   class(at1), intent(inout) :: x

  end subroutine i_tims

 end interface

 abstract interface

  subroutine i_show(x)

   import :: at1

   implicit none

   class(at1), intent(in) :: x

  end subroutine i_show

 end interface



 type, abstract :: at2

  class(at1), allocatable :: work(:)

 end type at2



 type, extends(at1) :: t1

  real, allocatable :: f(:)

 contains

  procedure, pass(x) :: incr

  procedure, pass(x) :: tims

  procedure, pass(z) :: copy

  procedure, pass(x) :: show

 end type t1



 type, extends(at2) :: t2

 end type t2



contains



 subroutine alt(z,x,r,y)

  real,       intent(in) :: r

  class(at1), intent(in) :: x, y

  class(at1), intent(inout) :: z



   print *, 'All the following values should be 2.0'

   call y%show()

   call z%mlt(r,y)  ! z = r * y

   call y%show()

   call z%incr(x)   ! z = z + x

   call y%show()



 end subroutine alt



 pure subroutine add(z,x,y)

  class(at1), intent(in) :: x, y

  class(at1), intent(inout) :: z

   call z%copy( x )

   call z%incr( y )

 end subroutine add



 pure subroutine mlt(z,r,x)

  real, intent(in) :: r

  class(at1), intent(in) :: x

  class(at1), intent(inout) :: z

   call z%copy( x )

   call z%tims( r )

 end subroutine mlt



 pure subroutine copy(z,x)

  class(at1), intent(in)    :: x

  class(t1),  intent(inout) :: z



   select type(x); type is(t1)

   z%f = x%f

   end select

 end subroutine copy



 pure subroutine incr(x,y)

  class(at1), intent(in)    :: y

  class(t1),  intent(inout) :: x

   select type(y); type is(t1)

   x%f = x%f + y%f

   end select

 end subroutine incr



 pure subroutine tims(x,r)

  real,      intent(in)    :: r

  class(t1), intent(inout) :: x

   x%f = r*x%f

 end subroutine tims



 subroutine show(x)

  class(t1), intent(in) :: x

   write(*,*) x%f

 end subroutine show



 subroutine sub(var)

  class(at2), intent(inout) :: var

   call var%work(2)%alt(var%work(1),1.5,var%work(1))

 end subroutine sub



end module m





program p

 use m, only: t1, t2, sub

 implicit none

 integer :: i

 type(t2) :: aa



  allocate(t1::aa%work(2))

  select type(y=>aa%work); type is(t1)

  do i=1,2

    allocate(y(i)%f(1))

    y(i)%f = 2.0

  enddo

  end select

  ! This call to ALT works as expected

  call aa%work(2)%alt(aa%work(1),1.5,aa%work(1))

  ! Calling ALT from SUB however does not work

  call sub(aa)



end program p

Reply via email to