Erratic behavior of different versions for LHS reallocation (Possible regression)

Erratic behavior of different versions for LHS reallocation (Possible regression)

Hi,

I have tested different versions of ifort on different platforms, and the results I get are very irreproducible. The source code is given at the bottom.

The expected output (I think) is
          -3 :           3
          -3 :           3

The expected output for the second line follows the strict interpretation of the standard, as LHS should not be reallocated and hence the bounds should not change. If the bounds are changed to match RHS, the output should be
          -3 :           3
          -2 :           4

-----------------------------------------------

Here are the results:

Platform 1 (x86_64)

v. 11.1.064
          -3 :           3
          -2 :           4

v. 12.0.4
           1 :           7
          -2 :           4

Another platform (also x86_64)

v 12.0.0
           1 :           7
          -2 :           4

v 12.0.1
           1 :           7
           1 :           7

I tested v 13 something on another platform, but it is down for maintenance right now. I think the result was also
           1 :           7
           1 :           7

-------------------------------------------------------------------------------------

The source code:

program return_allocatable
    implicit none

    real, allocatable :: a(:)

    real, parameter :: b(-2:4)=[1,2,3,4,5,6,7]

    a=foo(3)
    print*,lbound(a),':',ubound(a)

    a=b
    print*,lbound(a),':',ubound(a)

contains
    function foo(n)
        integer :: n
        real, allocatable :: foo(:)

        allocate(foo(-3:n))

        foo=n
    end function
end program

 

10 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Thanks, we'll take a look.

Steve - Intel Developer Support

The two cases are different. I maintain that we get the function reference right, but after 12.0, broke the variable/parameter case (the parameter aspect turns out to not be relevant.)

For the a=foo(3) case, you have to ask what the bounds of foo(3) are. Here's the relevant words from the standard:

12.3.3 Characteristics of function results

The characteristics of a function result are its type, type parameters (if any), rank, whether it is polymorphic, whether it is allocatable, whether it is a pointer, whether it has the CONTIGUOUS attribute, and whether it is a procedure pointer. If a function result is an array that is not an allocatable or pointer, its shape is a characteristic.

Note that nowhere in here does it say anything about lower and upper bounds. Shape, even for non-allocatable/pointer arrays, refers to extent (number of elements.) So the bounds of the result variable as allocated in the function don't carry over into the result when used in the expression. In this case, the bounds are 1:7 and the compiler is correct.

The second case is clearly a bug and I will report it to the developers.

Steve - Intel Developer Support

On further investigation, the second case is not a bug. What I missed earlier was that the standard differentiates regarding whether a gets reallocated or not.

As long as the shapes of a and b are the same, a does not get reallocated.  Shape is rank and number of elements, NOT lower and upper bounds. Only if a gets (re)allocated does its bounds get taken from the expression (b here). Then a simple element-by-element copy is done.

No bug in recent versions.

Steve - Intel Developer Support

Hi Steve, and thanks,

Well, I guess that this 7.2.1.3 (3):
"If the variable is or becomes an unallocated allocatable variable, it is then allocated with

if expr is an array, the shape of expr with each lower bound equal to the corresponding element of
LBOUND (expr )."

is then pointless. In other words, and allocatable-array valued function can never return arrays with lower bounds different than 1. I think this is very arbirtrary, when Fortran permits defining custom lower bounds...

By the way, right after the snippet you quoted from 12.3.3, this text appears:

"If a type parameter of a function result or a bound of a function result array is not a constant expression, the
exact dependence on the entities in the expression is a characteristic."

I have some trouble with the wording, so I am not quite sure if this is relevant.

For the moment, I am staying clear of returning arrays with lower bounds different than 1, but I think this breaks the spirit of Fortran arrays...

You are correct that the allocatable array function result always has lower bound 1. You get much the same behavior if you pass an array to an assumed-shape dummy argument - the lower bound is 1. On assignment to pointer arrays, you can use bounds remapping.

That second quote is indeed a bit obscure - but this refers to the computation of the extent of the result.

Steve - Intel Developer Support

Interesting. Is there any reason for this? The take-home message seems to be "stay clear of declaring lower bounds different than 1!"...

The part about dependence is important in generic resolution.

The reason for the language rules regarding lower bounds is that it allows you to write code that makes no assumptions about the lower bound of what you receive. In the case of dummy arguments, there is no obvious value for the lower bound of an array expression with vector subscript, or with a slice in reverse order, etc. But I admit that the "was it allocated before to the same shape" rule certainly introduces some perhaps unnecessary complexity. My guess is that it was added as an optimization aid.

Steve - Intel Developer Support

Backwards compatibility with F95?

Here's one for the philosophers... the right hand side of an assignment is an expression.  That expression might be simply comprised of a single primary that is a variable, but the right hand side thing is still an expression.  Why does that sort of expression get special lower bound treatment in an assignment versus any other expression?  If you have defined assignment, the language even treats the right hand side as a parenthesised thing, which is categorically different to a thing.

I think it would have been more consistent for a reallocated lhs to be given a lower bound of one, regardless of what was on the right hand side.

Agreed, IanH. Otherwise the plethora of cases makes it extremely confusing...

Leave a Comment

Please sign in to add a comment. Not a member? Join today