Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28997 Discussions

deallocation of allocatable components of intent(out) optional dummy argument

MR
Beginner
1,062 Views
Hi,
the attached code does not work, apparently because the allocatable
component does not get deallocated on entry in the subroutine s1
(i.e., where the dummy argument is optional). Is this a bug in the
compiler? (the same code runs when compiled with gfortran).

The error is

ifort -O0 -traceback abc.f90 -o abc
./abc
s2 works
forrtl: severe (151): allocatable array is already allocated
Image PC Routine Line Source
abc 000000000047127D Unknown Unknown Unknown
abc 000000000046FD85 Unknown Unknown Unknown
abc 0000000000446E30 Unknown Unknown Unknown
abc 0000000000433DBF Unknown Unknown Unknown
abc 000000000040FCEB Unknown Unknown Unknown
abc 0000000000402D06 m1_mp_s1_ 9 abc.f90
abc 0000000000402EBE MAIN__ 25 abc.f90
abc 0000000000402C4C Unknown Unknown Unknown
libc.so.6 00007FF1708E6BBD Unknown Unknown Unknown
abc 0000000000402B49 Unknown Unknown Unknown

ifort -V
Intel Fortran Intel 64 Compiler Professional for applications running on Intel 64, Version 11.1 Build 20100414 Package ID: l_fcompxe_2011.2.137

(this is an old version, I don't have access to the latest one).

Thank you,
Marco


[fortran]module m1
 implicit none
 type tt
   integer, allocatable :: i(:)
 end type tt
contains
 pure subroutine s1(x)
  type(tt), intent(out), optional :: x
   if(present(x)) allocate(x%i(3))
 end subroutine s1
 pure subroutine s2(x)
  type(tt), intent(out) :: x
   allocate(x%i(3))
 end subroutine s2
end module m1

program p
 use m1
 implicit none
 type(tt) :: y

 call s2(y)
 call s2(y)
 write(*,*) "s2 works"
 call s1(y)
 call s1(y)
 write(*,*) "s1 works"
end program p
[/fortran]
0 Kudos
7 Replies
jimdempseyatthecove
Honored Contributor III
1,062 Views
try using intent( inout ), although I do not think this will fix your problem.

Jim
0 Kudos
MR
Beginner
1,062 Views
Jim,
do you mean

[fortran] pure subroutine s1(x)
  type(tt), intent(inout), optional :: x
   if(present(x)) then
     if(allocated(x%i)) deallocate(x%i)
     allocate(x%i(3))
   endif
 end subroutine s1
[/fortran]

Yes, this is a woraround, but I think that the first version should
also work, and it seems much more logical to me.

Marco
0 Kudos
Steven_L_Intel1
Employee
1,062 Views
Yes, this is a compiler bug. I have escalated it as DPD200169598. Thanks for reporting it.
0 Kudos
MR
Beginner
1,062 Views
OK, thank you Steve.

Marco
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,062 Views
Steve may be able to comment on this issue as it relates to the FORTRAN standards.

IMHO intent(INOUT) is required because the original contents of the array descriptor for x is being passed into the subroutine for use, inyour specificcase the use is to deallocate the array (when argument is present).

Consider the following minor change to your subroutine:

pure subroutine s1(x)
type(tt), intent(inout), optional :: x
if(present(x)) then
if(size(x%i) .eq. 3) return
deallocate(x&i)
allocate(x%i(3))
endif
end subroutine s1


The above is functionally equivalent to the original subroutine s1 with the exception of bypassing the deallocate/allocate if the size of the array is the same as the one you need (want) to allocate.

In this case, you are reading the contents of the array descriptor. So, ask yourself,are you not passing something related to the array into the subroutine?

Jim Dempsey
0 Kudos
Steven_L_Intel1
Employee
1,062 Views
There are various workarounds, to be sure, but the compiler is supposed to ensure that, if the argument is present, all ALLOCATABLE components are deallocated on entry. If you want to work around the bug, there are optimizations one can use such as Jim suggests.
0 Kudos
Steven_L_Intel1
Employee
1,062 Views
This is fixed in Update 6, scheduled for early September.
0 Kudos
Reply