j3-fortran / fortran_proposals

Proposals for the Fortran Standard Committee
178 stars 15 forks source link

Explicit lower bounds should be respected #254

Open klausler opened 2 years ago

klausler commented 2 years ago
subroutine gotcha(a)
  real, intent(in) :: a(42:)
  print *, lbound(a, dim=1)
end subroutine

can print 42 or 1 depending on the size of the assumed-shape dummy argument.

This behavior is needlessly confusing, prevents a compiler from accepting some usage of LBOUND() in constant expressions, and raises obvious questions about underspecified semantics in the CFI_xxx APIs that establish lower bounds.

Either LBOUND() should be adjusted or a new intrinsic function that is LBOUND() without the astonishing semantics should be added, and the semantics of lower bounds in the CFI_xxx APIs clarified in this edge case.

certik commented 2 years ago

It seems it prints 1 for this:

program x
real :: b(0)
call gotcha(b)

contains

subroutine gotcha(a)
  real, intent(in) :: a(42:)
  print *, lbound(a, dim=1)
end subroutine

end

And 42 for any other size of b.

nncarlson commented 2 years ago

Wow, I was not aware of this bizarre special case behavior of lbound until now. What on earth was the motivation? I often use the dim argument (I find it a real nuisance that lbound returns an array for a rank-1 array) assuming that it did the sensible thing. I've apparently just been lucky so far, but am wiser now.

klausler commented 2 years ago

LBOUND() without DIM= also substitutes 1 for an explicit lower bound on an empty dimension.

certik commented 2 years ago

I find it a real nuisance that lbound returns an array for a rank-1 array

The same here. It just doesn't seem worth it, so I just use the default lower bound 1 in most of my procedures.

Regarding the motivation for the above behavior, this program:

program x

    real :: b(0)

    call gotcha(b)

contains

subroutine gotcha(a)
  real, intent(in) :: a(42:)
  print *, lbound(a, dim=1)
  print *, ubound(a, dim=1)
end subroutine

end

Prints:

           1
           0

So if you loop from lbound to ubound, the loop will be empty (as it should). So that works. Probably it would have been better if the program above printed:

42
41

Or something like that.