Consider the following class structure, which involves three separate modules:
!----------------------- in file a.f
module parent_body_mod
type :: face
class(parent_body), pointer :: bPtr
end type
type, abstract :: parent_body
integer i
type(face) :: f
end type
end module parent_body_mod
!------------------------ in file b.f
module body_mod
use parent_body_mod
type, extends(parent_body) :: body
end type
interface body
procedure :: new_body
end interface
contains
function new_body() result(b)
type(body), target :: b
b%i = 123
b%f%bPtr => b
end function
end module body_mod
!--------------------------- in file c.f
module body_group_mod
use body_mod
type :: body_group
type(body), allocatable :: b
end type
interface body_group
procedure :: new_body_group
end interface
contains
function new_body_group() result(bg)
type(body_group) :: bg
allocate(bg%b)
bg%b = body()
end function
end module body_group_mod
!------------------- The main program
use body_group_mod
type(body_group) :: my_bg
my_bg = body_group()
print *, my_bg%b%f%bPtr%i
end
!--------------------------------------
The expected output is 123, whereas the actual output is something random. The code is compiled using ifort version 18.0.1. Note that the same issue doesn't happen when using "body" class itself, i.e. the following works just fine:
type(body), allocatable :: my_b
allocate(my_b)
my_b = body()
print *, my_b%f%bPtr%i ! This produces 123 as expected.
Any help is appreciated.
The code is non conforming.
Pointers associated with unsaved local variables of a procedure become undefined when the execution of the procedure completes (F2008 16.5.2.5 (5)). The function result b
in function new_body
is considered such a local variable (F2008 1.3.154.1), hence the pointer component b%f%bPtr
becomes undefined after the function call.
Function results are a little special compare to other local unsaved variables, in that their value is available longer than the variable exists - see F2008 Note 12.41 for some discussion.
Another way of thinking of the problems is that with the statement bg%b = body()
, the body on the left hand side is a different object from the body on the right hand side. The assignment just copies the value of the right hand side object - once that assignment is complete, the right hand side object ceases to exist. Nowhere is there code to say that when the value of a body object is transferred - the pointer component needs to be updated to reference the left hand side variable being assigned to. Also note that the left hand side bg%b
does not have the TARGET attribute - so there is no way that a pointer can be validly associated with it anyway.