- 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