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

Compiler bug with F2003 features

MR
Beginner
880 Views
Hi,
the attached code shows two compiler bugs (unless I'm mistaken):
the first one is that the function inlt should not be allowed to be
PURE, since it references show, which is not PURE (ifort however
accepts the PURE attribute for inlt). The second one is that the input
argument y of inlt is modified by the call

call tmp%mlt( r , y )

which should not happen:

./prog
Show 1.000000 2.000000 3.000000 4.000000
Show 0.5000000 1.000000 1.500000 2.000000

As a reference, gfortran complains about the PURE attribute and
correctly displays

Show 1.00000000 2.00000000 3.00000000 4.00000000
Show 1.00000000 2.00000000 3.00000000 4.00000000

I'm using

ifort -V
Intel Fortran Intel 64 Compiler XE for applications running on Intel 64, Version 12.1.1.256 Build 20111011

Regards,
Marco Restelli

[fortran]module mod_stv implicit none public :: c_stv private type, abstract :: c_stv contains procedure(i_tims), deferred, pass(x) :: tims procedure, pass(x) :: inlt procedure(i_copy), deferred, pass(z) :: copy procedure, pass(z) :: mlt procedure(i_show), deferred, pass(x) :: show end type c_stv abstract interface pure subroutine i_incr(x,y) import :: c_stv implicit none class(c_stv), intent(in) :: y class(c_stv), intent(inout) :: x end subroutine i_incr end interface abstract interface pure subroutine i_tims(x,r) import :: c_stv implicit none real, intent(in) :: r class(c_stv), intent(inout) :: x end subroutine i_tims end interface abstract interface pure subroutine i_copy(z,x) import :: c_stv implicit none class(c_stv), intent(in) :: x class(c_stv), intent(inout) :: z end subroutine i_copy end interface abstract interface subroutine i_show(x) import :: c_stv implicit none class(c_stv), intent(in) :: x end subroutine i_show end interface contains ! Since show is not pure, inlt should be pure too, however ifort ! accepts the code. !pure subroutine inlt(x,r,y) subroutine inlt(x,r,y) real, intent(in) :: r class(c_stv), intent(in) :: y class(c_stv), intent(inout) :: x class(c_stv), allocatable :: tmp ! The following two allocations should be equivalent, however when ! using the first one the input variable y gets modified by the ! call to mlt. allocate(tmp,source=y) !allocate(tmp,source=x) call y%show() call tmp%mlt( r , y ) call y%show() deallocate(tmp) end subroutine inlt pure subroutine mlt(z,r,x) real, intent(in) :: r class(c_stv), intent(in) :: x class(c_stv), intent(inout) :: z call z%copy( x ) call z%tims( r ) end subroutine mlt end module mod_stv !----------------------------------------------------------------------- module mod_ext use mod_stv, only: c_stv implicit none public :: t_nf private type, extends(c_stv) :: t_nf real, allocatable :: x(:) contains procedure, pass(x) :: tims => nf_tims procedure, pass(z) :: copy => nf_copy procedure, pass(x) :: show => nf_show end type t_nf contains pure subroutine nf_tims(x,r) real, intent(in) :: r class(t_nf), intent(inout) :: x x%x = r*x%x end subroutine nf_tims pure subroutine nf_copy(z,x) class(c_stv), intent(in) :: x class(t_nf), intent(inout) :: z select type(x); type is(t_nf) z%x = x%x end select end subroutine nf_copy subroutine nf_show(x) class(t_nf), intent(in) :: x write(*,*) 'Show ', x%x end subroutine nf_show end module mod_ext !----------------------------------------------------------------------- module mod_sub use mod_stv, only: c_stv implicit none public :: sub private contains subroutine sub(x) class(c_stv), intent(in) :: x class(c_stv), allocatable :: w, v(:) allocate( w , source=x ) allocate( v(1) , source=x ) call w%inlt( 0.5 , v(1) ) deallocate( w , v ) end subroutine sub end module mod_sub !----------------------------------------------------------------------- program prog use mod_ext, only: t_nf use mod_sub, only: sub type(t_nf) :: v allocate(v%x(4)); v%x = (/ 1.0 , 2.0 , 3.0 , 4.0 /) call sub(v) end program prog [/fortran]
0 Kudos
7 Replies
Steven_L_Intel1
Employee
880 Views
Thanks - there are several curious aspects to how this program compiles and runs - I'm investigating now.
0 Kudos
MR
Beginner
880 Views
Hi Steve,
thank you for looking at this. I just noted that the abstract interface i_incr
should be eliminated (I missed it while preparing the reduced test case),
and the comment about the PURE attribute should be "Sinceshowisnotpure,
inltshould NOT bepuretoo..."

Regards,
Marco Restelli
0 Kudos
mecej4
Honored Contributor III
880 Views
Marco,

You are allowed to edit and correct your posts. Correcting text is very simple, but correcting code with highlighting needs a little more effort.

If for some reason, you want to leave the erroneous part in and show a correction, you can select the erroneous part with the mouse and click on "strikethrough" (the third tool button in the top row).
0 Kudos
Steven_L_Intel1
Employee
880 Views
The problem of y being modified is caused by the compiler incorrectly having tmp%x's storage be the same as y%x's storage. This does not happen when the source is x (the "this" argument). I have reported this to the developers as issue DPD200180295.

The lack of error when inlt is PURE has been reported as issue DPD200180297.

Thanks for bringing these to our attention.
0 Kudos
MR
Beginner
880 Views
Steve, mecej4,
thank you both!

Marco Restelli
0 Kudos
Steven_L_Intel1
Employee
880 Views
The lack of error for the call from the PURE procedure is already fixed for a release later this year.
0 Kudos
Steven_L_Intel1
Employee
880 Views
The incorrect results issue is fixed for a release later this year.
0 Kudos
Reply