This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug fortran/59560] New: Resolution generic procedure of derived types fail
- From: "klaas_giesbertz at hotmail dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Thu, 19 Dec 2013 13:29:09 +0000
- Subject: [Bug fortran/59560] New: Resolution generic procedure of derived types fail
- Auto-submitted: auto-generated
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59560
Bug ID: 59560
Summary: Resolution generic procedure of derived types fail
Product: gcc
Version: 4.8.2
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: fortran
Assignee: unassigned at gcc dot gnu.org
Reporter: klaas_giesbertz at hotmail dot com
I want to achieve some more complicated structure in fortran2008 and I am not
sure how to do it according to the standard. So I am even not sure if it is a
bug, or simply not possible with fortran2008.
I want to make a base class, preferably an abstract one, which promises a
subroutine which operates on TWO arguments of this base class. The derived
class should implement this and there is some other class using this procedure
which only knows about the base class. This was actually possible with gcc 4.7
by declaring both arguments of the subroutine as class. As an example, consider
the following program (sorry, quite lengthy due to the several classes):
module BaseModule
implicit none
private
type, public, abstract :: BaseClass
contains
procedure(FuncAbstr), deferred :: Func
end type
abstract interface
subroutine FuncAbstr(self, other)
import
class(BaseClass), intent(inout) :: self
class(BaseClass), intent(in) :: other
end subroutine
end interface
end module
module UseBaseModule
use BaseModule
implicit none
private
type, public :: UseBaseClass
class(BaseClass), pointer :: base => null()
contains
procedure :: Init
procedure :: CallFunc
end type
contains
subroutine Init(self, base)
class(UseBaseClass), intent(inout) :: self
class(BaseClass), pointer, intent(in) :: base
self%base => base
end subroutine
subroutine CallFunc(self)
class(UseBaseClass), intent(inout) :: self
class(BaseClass), allocatable :: newBase
allocate(newBase, mold=self%base)
call newBase%Func(self%base)
end subroutine
end module
module DerivedModule
use BaseModule
implicit none
private
type, public, extends(BaseClass) :: DerivedClass
real :: x
contains
procedure :: Func
end type
contains
subroutine Func(self, other)
class(DerivedClass), intent(inout) :: self
class(DerivedClass), intent(in) :: other
self%x = other%x
write(*,*) 'Derived Func called'
end subroutine
end module
program Test
use BaseModule
use UseBaseModule
use DerivedModule
implicit none
class(BaseClass), allocatable :: derived
type(UseBaseClass) :: useBase
allocate(DerivedClass :: derived)
call useBase%Init(derived)
call useBase%CallFunc()
end program
This code compiles and runs correctly with gcc4.7.3, but gcc4.8.2 gives the
following compile error:
Test1.f08:58.13:
procedure :: Func
1
Error: Argument mismatch for the overriding procedure 'func' at (1): Type/rank
mismatch in argument 'other'
and some more which are not relevant.
I actually do not even know if this code is supposed to compile, since it is
not clear to me if such kind of overloading is allowed by the fortran standard.
One way around this problem might be to give up the possibility to use an
abstract type and to use a generic interface with an explicit type for the 2nd
argument of the subroutine. The type is now required to facilite the resolution
of the generic subroutine. However, this generic subroutine is not correctly
resolved. As an example consider the following code (again quite lengthy,
sorry):
module BaseModule
implicit none
private
type, public :: BaseClass
contains
procedure :: BaseFunc
generic :: Func => BaseFunc
end type
contains
subroutine BaseFunc(self, other)
class(BaseClass), intent(inout) :: self
type(BaseClass), intent(in) :: other
write(*,*) 'Base Func called'
end subroutine
end module
module DerivedModule
use BaseModule
implicit none
private
type, public, extends(BaseClass) :: DerivedClass
real :: x
contains
procedure :: DerivedFunc
generic :: Func => DerivedFunc !Extend generic Func
end type
contains
subroutine DerivedFunc(self, other)
class(DerivedClass), intent(inout) :: self
type(DerivedClass), intent(in) :: other
self%x = other%x
write(*,*) 'Derived Func called'
end subroutine
end module
module UseBaseModule
use BaseModule
implicit none
private
type, public :: UseBaseClass
class(BaseClass), pointer :: base => null()
contains
procedure :: Init
procedure :: CallFunc
end type
contains
subroutine Init(self, base)
class(UseBaseClass), intent(inout) :: self
class(BaseClass), target, intent(in) :: base
self%base => base
end subroutine
subroutine CallFunc(self)
class(UseBaseClass), intent(in) :: self
class(BaseClass), allocatable :: newBase
allocate(newBase, mold=self%base)
call newBase%Func(self%base)
end subroutine
end module
program Test
use DerivedModule
use UseBaseModule
implicit none
type(DerivedClass) :: derived
type(UseBaseClass) :: useBase
call useBase%Init(derived)
call useBase%CallFunc()
end program
This code compiles both with gcc4.7.3 and gcc4.8.2 and gives in both cases the
incorrect output:
Base Func called
It should have called the DerivedFunc instead. Building a double block of
select types around it solves the problem, but the UseBase needs to know about
the Derived as well to do this, which is not desirable.
Hope someone can help me out.
Klaas Giesbertz