- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hopefully you can get Intel staff to chime in along with other experts on Fortran, but I think as you have coded, it gets into one of those gray areas as far as the Fortran standard is concerned and things may be left up to the processor to decide. And what I mean by this is as follows: your deferred procedure getAllValues is indicated to have the explicit interface ValOut as opposed to an ABSTRACT interface; the linker used with Intel Fortran seems to think there is an external procedure corresponding to this interface and is raising an error when it cannot find it. I'll hold my comments on whether this is legit and leave it up to Intel support and others to comment.
But in the meantime, you can avoid the error by applying the ABSTRACT attribute on the ValOut interface which may be what you had in mind in the first place:
abstract interface
subroutine ValOut(self, valuesOut)
import :: Feature, real64
implicit none
class(Feature), intent(in):: self
real(real64), dimension(:):: valuesOut
end subroutine ValOut
end interface
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Changing it to ABSTRACT INTERFACE fixed my problem, thanks!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you for complete description of your issue and test case. I confirmed the findings with ifort and gfortran and submitted this to our Developers for their analysis. Both compilers use the same underlying linker so it appears ifort may not be handling this unique case properly. Our Developers are better suited to comment about the conformance of the code to the Fortran Standard so I'll lean on their expertise about that.
Thank you very much FortranFan for your expert comments and advice. Your contributions are always greatly appreciated.
(Internal tracking id: CMPLRS-43176)
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page