- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi everybody,
Recently I have been facing terrible problems with FORTRAN classes. I don't know if I am implementing it in the wrong way of if simply the features are not implemented yet. As my code is quite big, I will post here a small example in which I have the problem that I consider to be the core of my other problems.
[fortran]module m_first
implicit none
private
public :: c_first
type, abstract :: c_first
integer :: a, b
contains
procedure(proc_abstract), deferred :: proc
procedure, pass(self) :: print_info
end type c_first
abstract interface
function proc_abstract(self) result(int_out)
import :: c_first
class(c_first), intent(inout) :: self
integer :: int_out
end function proc_abstract
end interface
contains
subroutine print_info(self)
class(c_first), intent(in) :: self
print *,'==== from c_first: ', self%a
end subroutine print_info
end module m_first
[/fortran] [fxfortran]module m_second
use m_first
implicit none
private
public :: c_second
type, abstract, extends(c_first) :: c_second
real :: c
contains
procedure(scream_abstract), deferred :: scream
end type c_second
abstract interface
subroutine scream_abstract(self)
import :: c_second
class(c_second), intent(inout) :: self
end subroutine scream_abstract
end interface
end module m_second[/fxfortran] [fortran]module m_thirdA
use m_second
implicit none
private
public :: c_thirdA
type, extends(c_second) :: c_thirdA
real :: d
contains
procedure, pass(self) :: scream
procedure, pass(self) :: proc
procedure, pass(self) :: print_info
end type c_thirdA
contains
function proc(self) result(int_out)
class(c_thirdA), intent(inout) :: self
integer :: int_out
int_out=1
self%d = float(42/666)
end function proc
subroutine scream(self)
class(c_thirdA), intent(inout) :: self
print *, 'AAAAAAAAAAAAAH ',self%a+self%b,' - c_thirdA'
end subroutine scream
subroutine print_info(self)
class(c_thirdA), intent(in) :: self
print *,'I am c_thirdA. Proof? My d is ', self%d
end subroutine print_info
end module m_thirdA [/fortran] [fortran]module m_thirdB
use m_second
implicit none
private
public :: c_thirdB
type, extends(c_second) :: c_thirdB
character*512 :: d
contains
procedure, pass(self) :: scream
procedure, pass(self) :: proc
procedure, pass(self) :: print_info
end type c_thirdB
contains
function proc(self) result(int_out)
class(c_thirdB), intent(inout) :: self
integer :: int_out
int_out=-1
self%d = 'BAZINGA'
end function proc
subroutine scream(self)
class(c_thirdB), intent(inout) :: self
print *, 'AAAAAAAAAAAAAH ',self%a+self%b,' - c_thirdB'
end subroutine scream
subroutine print_info(self)
class(c_thirdB), intent(in) :: self
print *,'I am c_thirdB. Proof? My d is ', self%d
end subroutine print_info
end module m_thirdB [/fortran] [fortran]program main_multinh
use m_thirdA
use m_thirdB
use m_second
implicit none
class(c_second), pointer :: obj
integer :: err
! This should be c_thirdA
call choose_class(obj,1)
err = obj%proc()
call obj%scream()
call obj%print_info()
! This should be c_thirdB
call choose_class(obj,-1)
err = obj%proc()
call obj%scream()
call obj%print_info()
contains
subroutine choose_class(obj_second,switch)
class(c_second), intent(inout), pointer :: obj_second
integer, intent(in) :: switch
type(c_thirdA) :: obj_thirdA
type(c_thirdB) :: obj_thirdB
obj_thirdA%a=1
obj_thirdA%b=2
obj_thirdB%a=4
obj_thirdB%b=8
if (switch>0) then
allocate(obj_second, source=obj_thirdA)
else
allocate(obj_second, source=obj_thirdB)
end if
end subroutine
end program main_multinh[/fortran] So, when compiling this very code I get the following error:
[bash] perjanus Area51 $ make multinh ifort -I. -c m_first.f90 ifort -I. -c m_second.f90 ifort -I. -c m_thirdA.f90 ifort -I. -c m_thirdB.f90 ifort -I. -c main_multinh.f90 ifort -I. m_first.o m_second.o m_thirdA.o m_thirdB.o main_multinh.o -o multinh.exe main_multinh.o: In function `MAIN__': main_multinh.f90:(.text+0xf3): undefined reference to `proc_abstract_' main_multinh.f90:(.text+0x1fc): undefined reference to `proc_abstract_' make: *** [multinh] Error 1 perjanus Area51 $ [/bash]
Apparentely the compiler has problems finding the abstract interface for proc_abstract which is defined in m_first, and is private. Well, I've tried making it public, it didn't help so I got lost again. Is this expected? What is the CORRECT way to avoid this? Apparentely the compiler has problems to deal with DEFERRED procedures which were DEFERRED more than once in child classes.
Nevertheless, I've found a not-so-elegant workaround. I've added the proc_abstract to m_second.f90's abstract interface, changing only the line class(c_first) by class(c_second), and then re-declared "procedure(proc_abstract), deferred :: proc" in c_second class "contains" section. Now it compiled fine, but didn't work fine.
When I run the executable, I get:
[bash] perjanus Area51 $ ./multinh.exe AAAAAAAAAAAAAH 3 - c_thirdA ==== from c_first: 1 AAAAAAAAAAAAAH 12 - c_thirdB ==== from c_first: 4 perjanus Area51 $ [/bash]Simply the print_info procedure is not being overriden. This is a small example, in my original code things are a little more complex (we have 4 or 5 inheritance levels sometimes).
Am I doing anything wrong? Is there any concept that I am missing? Is there any feature that is needed for this to work yet is not implemented yet? Is that not supposed to work at all?
Thanks in advance.
1 Solution
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Link Copied
18 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Forgot to mention that I'm using intel fortran compiler 12.0.4.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
With 12.1.0.233 the code compiles fine and produces the output
AAAAAAAAAAAAAH 3 - c_thirdA
I am c_thirdA. Proof? My d is 0.0000000E+00
AAAAAAAAAAAAAH 12 - c_thirdB
I am c_thirdB. Proof? My d is
BAZINGA
Regards
Reinhold
AAAAAAAAAAAAAH 3 - c_thirdA
I am c_thirdA. Proof? My d is 0.0000000E+00
AAAAAAAAAAAAAH 12 - c_thirdB
I am c_thirdB. Proof? My d is
BAZINGA
Regards
Reinhold
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That is indeed interesting.
I have tried to compile with 12.1 right after posting this here and received
[bash]ifort -I. m_first.o m_second.o m_thirdA.o m_thirdB.o main_multinh.o -o multinh.exe main_multinh.o:(.rodata+0x88): undefined reference to `proc_abstract_' main_multinh.o:(.rodata+0x108): undefined reference to `proc_abstract_' make: *** [multinh] Error 1 [/bash]That is, however, if I include proc_abstract in c_second and re-defer it. If I remove this, it compiles fine! Just making it clear, the undefined reference error happens in 12.0.4 when the deferred proc_abstract is not in c_second, whereas the same error happens in 12.1 if the deferred proc_abstract IS IN c_second.
Is there any known bug related to this? My big code compiles with 12.0.4 (when I re-declare all deferred procedures) just presenting some weird behavior eventually; for instance, supose I have a (polymorphic) object beloning to another class (c_other, let's say) which has a pointer to a c_second. It may happen that I am trying to call obj_other%obj_second%proc() and I receive an error at compilation time regarding "undefined reference to proc_abstract". I can workaround it by defining
class(c_second), pointer :: tmp_obj
tmp_obj =>obj_other%obj_second
call tmp_obj%proc()
Interesting enough, with 12.1, I cannot compile, regardless if I'm using such workaround or not, and regardless if I am re-declaring deferred procedures.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There was a bug in 12.0.5 where the compiler would inappropriately put out an external reference to an abstract interface. In 12.1 we fixed most occurrences of this, and, like Reinhold, I can't get the error to occur in 12.1 (I tried Update 6 and Update 7 to Composer XE 2011) for your sources, though I see exactly the error you report using 12.0.5.
Please show us the output adding -V to display the compiler version.
Please show us the output adding -V to display the compiler version.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Steve, thank you for your answer. The code I've posted previously compiles with no error in 12.1. However, my big code wouldn't. I've tried to make a structure of classes which resembles the one from my big code, the files follow attached with a simple makefile (this is still a simplified version, since my other code relies moslty on pointers like ptr_secondB which you can find in c_secondA).Attempting to compile gives
[bash] perjanus Area51 $ make ifort -I. -c m_first.f90 ifort -I. -c m_secondB.f90 ifort -I. -c m_secondA.f90 ifort -I. -c m_thirdA.f90 ifort -I. -c m_thirdB.f90 ifort -I. -c m_forthA.f90 ifort -I. -c m_forthB.f90 ifort -I. -c main_multinh.f90 ifort -I. m_first.o m_secondB.o m_secondA.o m_thirdA.o m_thirdB.o m_forthA.o m_forthB.o main_multinh.o -o multinh.exe main_multinh.o:(.rodata+0x1a8): undefined reference to `func_seconda1_abstract_' make: *** [multinh] Error 1 perjanus Area51 $ ifort -V Intel Fortran Intel 64 Compiler XE for applications running on Intel 64, Version 12.1.0.233 Build 20110811 Copyright (C) 1985-2011 Intel Corporation. All rights reserved. FOR NON-COMMERCIAL USE ONLY perjanus Area51 $ [/bash]
Can you see anything I've missed?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I get no errors building this with Update 7. You're using Update 6, so please try Update 7 and see what happens.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you. Done again and the small sample works whereas the big one still doesn't compile with the very same error. I will keep building the example until it stumbles on the same stone as the big one. I'll post when I get it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Got it. I've simplified the code as much as I could. Follows attached with a simple makefile. Just to make sure, this is the version of the compiler I'm using:
[bash] perjanus Area51 $ ifort -V Intel Fortran Intel 64 Compiler XE for applications running on Intel 64, Version 12.1.1.256 Build 20111011 Copyright (C) 1985-2011 Intel Corporation. All rights reserved. FOR NON-COMMERCIAL USE ONLY perjanus Area51 $ [/bash]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Was anyone able to reproduce the error?
[bash] perjanus Area51 $ make cd Class;make make[1]: Entering directory `/Lago/Projetos/Area51/Class' ifort -I. -c m_class.f90 ar cr libclass.a m_class.o make[1]: Leaving directory `/Lago/Projetos/Area51/Class' cd Operator;make make[1]: Entering directory `/Lago/Projetos/Area51/Operator' ifort -I. -I../mod -c m_operator.f90 ifort -I. -I../mod -c m_opextension.f90 ifort -I. -I../mod -c m_opimplt_a.f90 ifort -I. -I../mod -c m_opimplt_b.f90 ar cr liboperator.a m_operator.o m_opextension.o m_opimplt_a.o m_opimplt_b.o make[1]: Leaving directory `/Lago/Projetos/Area51/Operator' cd TestClass;make make[1]: Entering directory `/Lago/Projetos/Area51/TestClass' ifort -I../mod/ -module ../mod -c main.f90 ifort -I../mod/ -module ../mod main.o -L../lib/ -loperator -lclass -o TestClass.exe main.o:(.rodata+0x8): undefined reference to `initialize_abstract_' main.o:(.rodata+0x68): undefined reference to `initialize_abstract_' main.o:(.rodata+0x148): undefined reference to `initialize_abstract_' make[1]: *** [all] Error 1 make[1]: Leaving directory `/Lago/Projetos/Area51/TestClass' make: *** [all] Error 2 perjanus Area51 $ [/bash]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I could reproduce it in Update 7 but not update 8, which is available now. Please try it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Steve Lionel,
First of all, sorry for taking so long to reply. Second, I found it a little confusing because I am trying to use Intel Parallel Studio XE and I have just realised that the lastest version of IPS doesn't necessarly contains the lastest version of ifc and/or icc. Anyways, I have both installed.
So I am using Update 9 now. It compiles fine, but it gives segmentation fault upon running.
[bash] perjanus TestClass $ ifort -V Intel Fortran Intel 64 Compiler XE for applications running on Intel 64, Version 12.1.3.293 Build 20120212 Copyright (C) 1985-2012 Intel Corporation. All rights reserved. FOR NON-COMMERCIAL USE ONLY perjanus TestClass $ ./TestClass.exe Which one you choose?: 1 forrtl: severe (174): SIGSEGV, segmentation fault occurred Image PC Routine Line Source TestClass.exe 0000000000403157 Unknown Unknown Unknown TestClass.exe 0000000000402C4C Unknown Unknown Unknown libc.so.6 00007F80BBBC122D Unknown Unknown Unknown TestClass.exe 0000000000402B49 Unknown Unknown Unknown perjanus TestClass $ ./TestClass.exe Which one you choose?: 2 forrtl: severe (174): SIGSEGV, segmentation fault occurred Image PC Routine Line Source TestClass.exe 0000000000403157 Unknown Unknown Unknown TestClass.exe 0000000000402C4C Unknown Unknown Unknown libc.so.6 00007F30ADA4D22D Unknown Unknown Unknown TestClass.exe 0000000000402B49 Unknown Unknown Unknown perjanus TestClass $ ./TestClass.exe Which one you choose?: 0000000000000000000000000000000000 forrtl: severe (174): SIGSEGV, segmentation fault occurred Image PC Routine Line Source TestClass.exe 0000000000403157 Unknown Unknown Unknown TestClass.exe 0000000000402C4C Unknown Unknown Unknown libc.so.6 00007F240351822D Unknown Unknown Unknown TestClass.exe 0000000000402B49 Unknown Unknown Unknown perjanus TestClass $ [/bash]
EDIT#1: Using Update 8 also compiles fine but gives segmentation fault while running.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I had not tried running it before. Let me take another look...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I can reproduce the problem. The ALLOCATE (SOURCE=) isn't doing everything right to set up the type-bound procedures. If you assign to obj_operator separately, it works. But to do that you have to do the assignment inside a SELECT TYPE construct.
I will report this to the developers and let you know of any progress.
I will report this to the developers and let you know of any progress.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Okay, thank you very much!
I've tried to have defined "type(C_opimplt_A), pointer :: obj_opimplt_A"and then use it to receive the object fromnew_opimplt_a function, and then finally pass it as obj_operator =>obj_opimplt_A. That works fine, but is a little "inelegant" if you have many possible different types.
Also, something that I thought that should work just fine is to change the output ofnew_opimplt_a to "TYPE(C_OPImplt_A), POINTER :: self" to attemp to set it just as "obj_operator =>new_opimplt_a(...)" but it also gives a segmentation fault. Apparentely I NEED an intermediateobj_opimplt_A for doing this.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Issue ID is DPD200179385
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This problem has been fixed for a release later this year.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you for the update. Any estimative for the release date?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Third quarter.
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page