I am trying to use the object orientated features of Fortran (Essentially, what I want to be able to do is to get an array of arraies, where each element of the outer array has a different size), and I have run into the following error,Is this a bug?>
Undefined symbols for architecture x86_64:"_valout_", referenced from: _TBPLIST_PACK_3.0.1 in ifortgrMMR7.o ld: symbol(s) not found for architecture x86_640
I know that I have defined ValOut, and this appears to be a bug with the compiler when you extend an extended type which has allocatable components inside.
I have attached below the code to show this, together with the compilation command. I am using ifort version 17.0.2. I have tested it against ifort version 17.0.2 and ifort version 16.0.0, both of which give the same error. However, when I tested it with gfortran (gcc version 6.1.0) it worked.
What the code is is an abstract type (a Feature) which has a deferred procedure (ValOut). This takes as input the class (Feature) and a set of real values (vauesOut).
module FeatureMod use iso_fortran_env type, abstract:: feature character(len=:), allocatable:: name contains procedure (ValOut), deferred :: getAllValues end type interface subroutine ValOut(self, valuesOut) use iso_fortran_env import Feature class(Feature), intent(in):: self real(real64), dimension(:):: valuesOut end subroutine ValOut end interface contains end module FeatureMod
I now define an extension of the type Feature where I override ValOut. For this extension, I set ValOut to be 1.
module FirstFeatureMod use iso_fortran_env use FeatureMod implicit none type, extends(feature):: secondType real, dimension(:), allocatable::r contains procedure:: getAllValues => getAllValuesSecond end type secondType contains subroutine getAllValuesSecond(self, valuesOut) class(secondType), intent(in):: self real(real64), dimension(:):: valuesOut valuesOut = 1 end subroutine end module FirstFeatureMod
I also define a thirdType (extending second type), and a fifthType(extending secondType). For these functions, I override ValOut to set the output to be 3 and 5 respectively.
module SecondFeatureMod use FirstFeatureMod type, extends(secondType):: thirdType integer:: k=6 contains procedure:: getAllValues => getAllValuesThird end type thirdType type, extends(secondType):: fifthType integer:: l=22 contains procedure:: getAllValues => getAllValuesFifth end type contains subroutine getAllValuesThird(self, valuesOut) class(thirdType), intent(in):: self real(real64), dimension(:):: valuesOut valuesOut = 3 end subroutine subroutine getAllValuesFifth(self, valuesOut) class(fifthType), intent(in):: self real(real64), dimension(:):: valuesOut valuesOut = 5 end subroutine end module SecondFeatureMod
Because I want an array of these, I define class which holds a pointer to a Feature class. This allows me to get an array of these arrays by defining ar array of the type holding the pointer.
module ListFeatureMod use FeatureMod use FirstFeatureMod type:: checkType class(feature), pointer:: l contains procedure:: setType end type type:: listOfCheck type(checkType), dimension(:), allocatable:: list contains procedure, pass:: allocateTypes end type contains subroutine allocateTypes(self, intIn) class(listOfCheck), intent(inout):: self integer, intent(in):: intIn allocate(self%list(intIn)) end subroutine allocateTypes subroutine setType(self, typeIn) class(checkType), intent(inout):: self class(feature), intent(in):: typeIn allocate(self%l, source=typeIn) end subroutine setType end module
Finally, I wrote a short program to test this, where I define an array of length 3, I set each element of the array to be a different derived type, and I write out the results. The expected results are simply 3,3,3\n1,1,1\n5,5,5.
program test use FeatureMod use FirstFeatureMod use SecondFeatureMod use ListFeatureMod integer:: N, i type(thirdType), target:: b type(secondType), target:: c type(fifthType), target:: e type(listOfCheck):: k real(real64), dimension(3)::r call k%allocateTypes(3) call k%list(1)%setType(b) call k%list(2)%setType(c) call k%list(3)%setType(e) do i = 1, 3 call k%list(i)%l%getAllValues(r) write(*,*) r end do contains end program
But this doesn't compile. I am trying to compile with no special flags
ifort Feature.f90 FirstFeature.f90 SecondFeature.f90 ListFeature.f90 FeatureContainer.f90
Is this a bug? Does Fortran allow me to do what I want to do? If not, is there another way to get this to work?
This bug doesn't appear if none of the types have allocatable components, so it might be possible to get around it by using something like
type, abstract:: feature(length) integer, len:: length contains . . end type type, extends(feature):: secondFeature real(real64), dimension(lenght):: values contains . . . end type
But I have had some serious issues trying to get the integer, len:: features of ifort to work.
Any help would be much appreciated.