- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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]
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]
Link Copied
7 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks - there are several curious aspects to how this program compiles and runs - I'm investigating now.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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).
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).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
The lack of error when inlt is PURE has been reported as issue DPD200180297.
Thanks for bringing these to our attention.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve, mecej4,
thank you both!
Marco Restelli
thank you both!
Marco Restelli
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The lack of error for the call from the PURE procedure is already fixed for a release later this year.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The incorrect results issue is fixed for a release later this year.

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