- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
the program below produces two different results depending on whether a type member variable is declared as "class" or "type":
module mod_tmp
type :: tmp
real, allocatable :: x(:,:)
end type tmp
type :: xx1
type(tmp), allocatable :: a
type(tmp), pointer :: b=>null()
end type xx1
type :: xx2
class(tmp), allocatable :: a
class(tmp), pointer :: b=>null()
end type xx2
end module mod_tmp
program test
use mod_tmp, only: xx1, xx2
implicit none
class(xx1), allocatable :: a1
class(xx2), allocatable :: a2
allocate(a1)
write(*,*) loc(a1%b),loc(a1%a)
allocate(a2)
write(*,*) loc(a2%b),loc(a2%a)
end program test
compiled with ifort version 19.0.5 or 19.1.2 the result is
0 0
15406432 15406304
whereas gfortran, version 10.2 gives
0 0
0 0
I would suggest that this is a bug but before I launch a support ticket I would like somebody literate in the standard to confirm.
op: Linux, kernel version 5.9.10, ifort version 19.0.5 and 19.1.2
Thanks.
BTW: the drop down list for inserting code does not show "FORTRAN" or "bash" any longer?! Found with firefox 83 and chromium 87.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
For anyone interested in the Fortran standard, the closest the standard language comes to a similar facility is the C_LOC module intrinsic function whose interface is defined in ISO_C_BINDING intrinsic module. As readers may know, C_LOC works in conjunction with a companion C processor.
For a situation similar to that by OP, a coder has to go through rigmarole to work with C_LOC e.g., the dummy argument must have TARGET attribute; if it is ALLOCATABLE, it must be allocated; and if a POINTER, it must be associated (i.e., it cannot be disassociated via => null() assignment), etc.
Here's an example which I contend is standard-conforming. In my experience with C interoperability features, Intel compiler works as expected:
module mod_tmp
type :: tmp
real, allocatable :: x(:,:)
end type tmp
type :: xx1
type(tmp), allocatable :: a
type(tmp), pointer :: b=>null()
end type xx1
type :: xx2
class(tmp), allocatable :: a
class(tmp), pointer :: b=>null()
end type xx2
contains
subroutine init_xx1( arg )
class(xx1), allocatable, intent(out) :: arg
allocate( arg )
allocate( arg%a, arg%b )
allocate( arg%a%x(1,1), arg%b%x(1,1) )
end subroutine
subroutine init_xx2( arg )
class(xx2), allocatable, intent(out) :: arg
allocate( arg )
allocate( arg%a, arg%b )
allocate( arg%a%x(1,1), arg%b%x(1,1) )
end subroutine
end module mod_tmp
program test
use, intrinsic :: iso_c_binding, only : c_loc, CS => c_size_t
use mod_tmp, only: xx1, xx2, init_xx1, init_xx2
implicit none
class(xx1), allocatable, target :: a1
class(xx2), allocatable, target :: a2
integer(kind=CS) :: addr_a, addr_b
call init_xx1(a1)
addr_a = transfer( source=c_loc(a1%a), mold=addr_a)
addr_b = transfer( source=c_loc(a1%a), mold=addr_a)
print "(g0,1x,z0,1x,z0)", "Address of a1 components: ", addr_a, addr_b
call init_xx2(a2)
addr_a = transfer( source=c_loc(a2%a), mold=addr_a)
addr_b = transfer( source=c_loc(a2%a), mold=addr_a)
print "(g0,1x,z0,1x,z0)", "Address of a2 components: ", addr_a, addr_b
end program test
Upon execution using Intel Fortran 19.1, Update 3, the output is as expected:
Address of a1 components: 16B667A45D0 16B667A45D0
Address of a2 components: 16B667ACEF0 16B667ACEF0
Press any key to continue . . .
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Two things:
1) loc is not standard Fortran it is a vendor extension. So it can behave however the compiler vendor wants it to.
2) doing anything with an unallocated variable is basically wrong IMO that is why we have the allocated(var) function.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@may_ka wrote:
.. I would like somebody literate in the standard to confirm..
LOC has nothing to do with the Fortran standard, rather it's an Intel facility.
So you can contact Intel support directly and inquire with them on details on how they intend their LOC function to work under your circumstance.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
For anyone interested in the Fortran standard, the closest the standard language comes to a similar facility is the C_LOC module intrinsic function whose interface is defined in ISO_C_BINDING intrinsic module. As readers may know, C_LOC works in conjunction with a companion C processor.
For a situation similar to that by OP, a coder has to go through rigmarole to work with C_LOC e.g., the dummy argument must have TARGET attribute; if it is ALLOCATABLE, it must be allocated; and if a POINTER, it must be associated (i.e., it cannot be disassociated via => null() assignment), etc.
Here's an example which I contend is standard-conforming. In my experience with C interoperability features, Intel compiler works as expected:
module mod_tmp
type :: tmp
real, allocatable :: x(:,:)
end type tmp
type :: xx1
type(tmp), allocatable :: a
type(tmp), pointer :: b=>null()
end type xx1
type :: xx2
class(tmp), allocatable :: a
class(tmp), pointer :: b=>null()
end type xx2
contains
subroutine init_xx1( arg )
class(xx1), allocatable, intent(out) :: arg
allocate( arg )
allocate( arg%a, arg%b )
allocate( arg%a%x(1,1), arg%b%x(1,1) )
end subroutine
subroutine init_xx2( arg )
class(xx2), allocatable, intent(out) :: arg
allocate( arg )
allocate( arg%a, arg%b )
allocate( arg%a%x(1,1), arg%b%x(1,1) )
end subroutine
end module mod_tmp
program test
use, intrinsic :: iso_c_binding, only : c_loc, CS => c_size_t
use mod_tmp, only: xx1, xx2, init_xx1, init_xx2
implicit none
class(xx1), allocatable, target :: a1
class(xx2), allocatable, target :: a2
integer(kind=CS) :: addr_a, addr_b
call init_xx1(a1)
addr_a = transfer( source=c_loc(a1%a), mold=addr_a)
addr_b = transfer( source=c_loc(a1%a), mold=addr_a)
print "(g0,1x,z0,1x,z0)", "Address of a1 components: ", addr_a, addr_b
call init_xx2(a2)
addr_a = transfer( source=c_loc(a2%a), mold=addr_a)
addr_b = transfer( source=c_loc(a2%a), mold=addr_a)
print "(g0,1x,z0,1x,z0)", "Address of a2 components: ", addr_a, addr_b
end program test
Upon execution using Intel Fortran 19.1, Update 3, the output is as expected:
Address of a1 components: 16B667A45D0 16B667A45D0
Address of a2 components: 16B667ACEF0 16B667ACEF0
Press any key to continue . . .
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@may_ka ,
To the extent your interest is in Fortran generally including its standard, you may also want to post your queries at this Fortran Discourse site for broader community feedback:
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page