Compiler bug ? Passing explicit/assumed-shape dummy arrays

Compiler bug ? Passing explicit/assumed-shape dummy arrays

Simon's picture

Hello,

I just get confused about ifort behavior.

Here is a minimal sample program causing me trouble :

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

output :

0 1 2 3 4

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

 integer,dimension(nb),intent(out) :: vec
to an assumed-shape form :
 integer,dimension(:),intent(out) :: vec
the program behaves normally and the output is :
1 2 3 4 5
.

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

ifort version : 12.1.0 20111011

Regards,

Simon.

9 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.
Steve Lionel (Intel)'s picture
Best Reply

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).

Steve
Steve Lionel (Intel)'s picture

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.

Steve
Simon's picture

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.

Steve Lionel (Intel)'s picture

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.

Steve
jimdempseyatthecove's picture

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

www.quickthreadprogramming.com
Simon's picture

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.

jimdempseyatthecove's picture

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

www.quickthreadprogramming.com
Simon's picture

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.

Login to leave a comment.