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

Compiler bug ? Passing explicit/assumed-shape dummy arrays

Simon1
Beginner
1,443 Views

Hello,

I just get confused about ifort behavior.

Here is a minimal sample program causing me trouble :

[fortran]

program bug
implicit none
integer,parameter :: nb=1
integer,dimension(5,nb) :: array
integer :: n
    n=1
    do while (n<=size(array,1))
        call fill(2,array(n,:),n)
    end do
write(*,*) array
contains
    subroutine fill(nb,vec,n)
    integer,intent(in)::nb
    integer,dimension(nb),intent(out) :: vec
    integer,intent(inout) :: n
        vec=n
        n=n+1
    end subroutine fill
end program bug

[/fortran]

output : [bash]0 1 2 3 4[/bash]

And with -check all at compilation i got : "Subscript #1 of the array ARRAY has value 6 which is greater than the upper bound of 5"

Howerer, if i change [fortran] integer,dimension(nb),intent(out) :: vec[/fortran] to an assumed-shape form : [fortran] integer,dimension(:),intent(out) :: vec[/fortran] the program behaves normally and the output is : [bash]1 2 3 4 5[/bash].

This bug (?) does not appear when using gfortran instead of ifort.

ifort version : 12.1.0 20111011

Regards,

Simon.

0 Kudos
1 Solution
Steven_L_Intel1
Employee
1,443 Views

Very interesting. The issue is that because array(n,:) is not a contiguous slice, it has to do copy-in, copy-out, On return from fill, it is copying the result back but using the updated value of n as the subscript. It shouldn't do that. I will let the developers know.

You could make the vec argument in fill an assumed-shape array or reverse the dimensions so that the slice is contiguous (which would be faster).

View solution in original post

0 Kudos
8 Replies
Steven_L_Intel1
Employee
1,444 Views

Very interesting. The issue is that because array(n,:) is not a contiguous slice, it has to do copy-in, copy-out, On return from fill, it is copying the result back but using the updated value of n as the subscript. It shouldn't do that. I will let the developers know.

You could make the vec argument in fill an assumed-shape array or reverse the dimensions so that the slice is contiguous (which would be faster).

0 Kudos
Steven_L_Intel1
Employee
1,443 Views

Entered as issue DPD200249879. I have a nagging feeling that the standard prohibits what you're doing here but I can't yet find the words saying so.

0 Kudos
Simon1
Beginner
1,443 Views

Thank you for your answer Steve.

I have figured out that the non-contiguous slices and the copy-out involved, are the source of the probleme. But i am not certain to well understand why the assumed shape form doesn't involve non-contiguous slice and thus similar problems (no warning, with -CB compiler option and nb>1).

I am more worried about your remark about the standard. Let me know if you find out i'm doing something wrong that will eventually be forbidden in a next update. For now i'm using assumed-shape that fit better my needs (i can't simply reverse my indexes in my full code), but if my way of doing isn't allowed by the standard i will have to find another solution.

0 Kudos
Steven_L_Intel1
Employee
1,443 Views

Assumed-shape avoids the copies so there is no attempt to use the updated value of N after the call updates it. I would recommend your switching to that.

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,443 Views

integer,parameter :: nb=1 
integer,dimension(5,nb) :: array

The array is thus array(1:5,1:1)

size(array,1) is thus 5

call fill(2, array(n,:), n) ! call passes referenct to 1 element (array(n,1))

---
fill(nb, vec, n) ! receives (2, referece to one element array(n,1), n) ! n=1:5

integer,dimension(nb),intent(out) :: vec ! declares vec(1:2) !!! wrong size for call with array(5,1)

vec = n ! copies to two elements of callers array(n,1:2)

Note, in event that Fortran permits you to declare the contains routine dummy with larger than callers argument then bear in mind that when you call with n=5 that the statement v=1 writes to array(5,1) and whatever follows.

This is in error.

Jim Dempsey

0 Kudos
Simon1
Beginner
1,443 Views

Thank you Jim for your answer.

This is an error I saw after Stever answered, and thus cannot edit my code.

As it doesn't impact my code (this is specific for nb=1) I didn't mention it. Anyway you are right it should be corrected, especially since such error can make debugging very painful.

The line 8 should of course be : call fill(nb, array(n,:), n).

The wrong behavior of the compiler I underlined is unaffected by this correction.

Simon.

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,443 Views

The error will occur call whenever nb > size(array(n,:).

Since your pasted code was explicitly calling with nb=2 your above statement is correct....
Up until you copy and paste this into new code and change the first argument to something larger.
It is best not to leave something like this laying around to bite you (or someone else) later.
At least place an assert in there that is enabled in debug build.

Jim Dempsey

0 Kudos
Simon1
Beginner
1,443 Views

Since array is declared as dimension(5,nb), the situation nb > size(array(n,:),2) will never occur in this code.

I agree with you that the fill subroutine should either do some test in case of bad calling or change vec=n to a safer method.

But please, keep in mind that the code I past here has for only purpose the reproduction of a potentialy bug in ifort. Then, it is minimal and the routine it contains are not made ​​to be used elsewhere. It is a separate code, not representative of my actual code, that should not be reused in another context.

Simon.

0 Kudos
Reply