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

Error with ALLOCATE

Robert_van_Amerongen
New Contributor III
870 Views

If an array is allocated with another array as the source, the bounds of the source array are used  for the bounds of the allocated array. This works fine for regular arrays. But the  Intel compiler comes in trouble if the source is not a regular array but a function result. In that case,  the size of the allocated array is correct, but the lower bound of the result array is set to 1. And that seems incorrect to me. (See MFE ed 2018, section 15.4.4) Our gfortran friends present the correct result.

 

I have added a reproducer  

 

Robert

0 Kudos
11 Replies
FortranFan
Honored Contributor II
855 Views

@Robert_van_Amerongen , if you have support subscription, please also submit a support request at Intel OSC (https://supporttickets.intel.com/servicecenter?lang=en-US) to get Intel Fortran team's direct attention and their response to your situation.

0 Kudos
FortranFan
Honored Contributor II
847 Views

@Robert_van_Amerongen , 

Here's my 2 cents' worth: per the Fortran standard, effectively the LBOUND along each dimension of a function result that is an array is always 1.  In your reproducer, that the variable of rank-1 array corresponding to the function result in the function subprogram has been defined therein with a lower bound of -5 is only relevant in that subprogram, the standard in essence states the lower bound not be retained once the function result is returned from the subprogram.

It's gfortran that appears not to conform to the standard in this case.

Note section 15.4.4 of "MFE" does not allude to the function result case.  Regardless, it's the standard that is ultimately the arbiter on such matters.

So I suggest you follow up with Intel Fortran team to get their feedback on this, especially with respect to what I state above.  Also, please consider a support request toward gfortran at GCC Bugzilla: https://gcc.gnu.org/bugzilla/ and you can link this comment to help that discussion.

0 Kudos
FortranFan
Honored Contributor II
844 Views

@Robert_van_Amerongen ,

In effect, the standard implies you should pursue other options for what you seek such as a subroutine subprogram perhaps:

  MODULE ta_mod
  IMPLICIT none
  PRIVATE
!
  PUBLIC :: subta
!
  CONTAINS
!
  subroutine subta( a )
  REAL,ALLOCATABLE, intent(out) :: a(:)
!
  ALLOCATE(a(-5:+5))
  a = 567.0
!
  write(*,*) 'bounds of a after ALLOCATE', LBOUND(a, DIM=1), UBOUND(a, DIM=1)
  RETURN
  END subroutine subta
!
  END MODULE ta_mod
!
!======================================
!
  PROGRAM ta
  USE ta_mod, ONLY : subta
  IMPLICIT none
!  
  REAL,ALLOCATABLE :: c(:)
!
  call subta( c )
  write(*,*) 'bounds of c after ALLOCATE', LBOUND(c, DIM=1), UBOUND(c, DIM=1)
!
  STOP
  END PROGRAM ta
C:\temp>ifort /standard-semantics ta.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.5.0 Build 20211109_000000
Copyright (C) 1985-2021 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.30.30706.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:ta.exe
-subsystem:console
ta.obj

C:\temp>ta.exe
 bounds of a after ALLOCATE -5 5
 bounds of c after ALLOCATE -5 5

C:\temp>

Separately, do note if you wish to work with lower bounds other than unity in your Fortran program(s), that is feasible but it does take effort and require very careful management across all your subprograms.

0 Kudos
andrew_4619
Honored Contributor III
835 Views
Separately, do note if you wish to work with lower bounds other than unity in your Fortran program(s), that is feasible but it does take effort and require very careful management across all your subprograms.

Indeed it is for such reasons that I pretty much never have anything other than the 1 lower bound and mange my data representations/problem formulation accordingly.  None the less, the inconsistency between a function return and a subroutine return in the examples shown is quite disturbing as it is counter intuitive. I would guess the standards writers were looking to avoid some other consequences (or complication) but if anyone knows the answer I would be interested to know.

0 Kudos
Steve_Lionel
Honored Contributor III
819 Views

A function result is an expression. If the result isn't a pointer (which carries its own bounds), the lower bound of an array expression is always 1.

0 Kudos
FortranFan
Honored Contributor II
785 Views
@Steve_Lionel writes:
.. If the result isn't a pointer (which carries its own bounds), the lower bound of an array expression is always 1.

Re: "If the result isn't a pointer (which carries its own bounds), the lower bound of an array expression is always 1," it is not correct.

There is a lot of convoluted logic vis-a-vis the wording in the standard that comes into play here.

In essence, what it boils down to is whether the source-expr is a whole array or not.  Following tortuous paths through the standard verbiage and several leaps with mind-numbing logic, one is forced to arrive at a point where the standard supposedly stipulates the lower bound of a source-expr is 1 unless the operand of a source-expr is a whole array in which it is the LBOUND intrinsic result of that whole array.  And given how a whole array is defined in the standard, a function result that is an array is not a whole array.

Consider the code below:

module m
   integer, allocatable :: dat(:)
contains
   function func() result(r)
      integer, allocatable :: r(:)
      allocate( r, source=dat )
   end function 
end module
   use m
   integer, allocatable :: x(:), y(:)
   allocate( dat(-1:1) ) ; dat = 0
   allocate( x, source=dat ) !<-- Here, source-expr is an array expression
   print *, "lbound(x) = ", lbound(x, dim=1)
   allocate( y, source=func() ) !<-- Here too, source-expr is an array expression
   print *, "lbound(y) = ", lbound(y, dim=1)
end 
C:\temp>ifort /standard-semantics c.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.5.0 Build 20211109_000000
Copyright (C) 1985-2021 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.30.30706.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:c.exe
-subsystem:console
c.obj

C:\temp>c.exe
 lbound(x) =  -1
 lbound(y) =  1

C:\temp>

 

The whole situation is so effed up with both the wordings in the standard and the compiler implementations there may be only compiler that can claim conformance to the standard now!  And that is IFORT!  This is because an Intel Fortran team rep had requested clarification a couple of years ago in a standard discussion context which had then led to a change in subsequent versions of IFORT.

There is likely only one person, the editor of the standard, who can convincingly claim accuracy in the standardese here and who can then make the leaps in "logic" required to arrive at the above point.  And this editor also happens to be the main developer of a commercial transpiler that itself does NOT conform to the standard in this case.  It too gives the same output as gfortran.  And with similar situations, there are other Fortran compilers that have nonconforming behavior .  Go figure!

 

 

0 Kudos
Steve_Lionel
Honored Contributor III
779 Views

Sorry, @FortranFan , I don't quite agree with you regarding my earlier statement. Perhaps I was insufficiently precise, and I fully agree that this is one of the more mind-numbingly obscure parts of the language.

You are correct to point to the description of LBOUND as the definition of what the lower bound should be here. The key wording is the definition of "whole array" which is "array component or array name without further qualification (9.5.2)" A function result does not qualify.

The point of difference is that an expression can simply be a variable, in which case its lower bounds are preserved. But if it's anything more complex than that, which is what I meant when I wrote "expression", then the lower bounds are always 1.

0 Kudos
jimdempseyatthecove
Honored Contributor III
757 Views

Steve, what does (supposed to) the following return for lbound of y?

 

program test
  real, allocatable :: y(:)
  y = foo(1.2)
  print *,lbound(y)
  contains
function foo(x) result(r)
  real:: x,r(-1:1)
  r = x
end function foo
end program test

 Jim Dempsey

0 Kudos
Steve_Lionel
Honored Contributor III
744 Views

1, as it does. The lower bounds of an array-valued non-pointer function return are always 1.

0 Kudos
Robert_van_Amerongen
New Contributor III
691 Views

Thank you all for your feedback. First, I found this example in a c-style environment and wanted to know how Fortran handles such a case. Based on my intuition, I expected the lower bound to be -5. If I am correct, Andrew feels the same.

 

But I am afraid that in this situation I must follow the advice here to use a subroutine in stead of a function (result) as FortranFan mentioned. And the fact that the two leading compilers in the field yield different result is an extra reason.

 

Robert

 

0 Kudos
andrew_4619
Honored Contributor III
687 Views

Indeed Robert, you have reached the same conclusions as to how to deal with this (i.e. avoid it!) as I did at some point in history!

 

0 Kudos
Reply