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

non-allocated array for optional argument with cheks turned on

Bálint_A_
Beginner
956 Views

Dear all,

I think, the ifort compiler 16.0.0 and also previous ones behave strange, when turning on pointer checking ("-check pointers") and passing an unallocated array as actual argument to an optional array dummy argument in a subroutine. The code below compiles and runs fine without the "-check pointers" option, but triggers a false error during run-time when the option is turned on during the compilation.

Bálint

module testmod
  implicit none

contains

  subroutine testSub(aa, bb)
    integer, intent(in) :: aa(:)
    integer, intent(in), optional :: bb(:)

    print *, "AA:", aa
    if (present(bb)) then
      print *, "BB:", bb
    else
      print *, "BB NOT PRESENT"
    end if

  end subroutine testSub

end module testmod


program test
  use testmod
  implicit none

  integer, allocatable :: aa(:), bb(:)

  allocate(aa(2))
  aa(:) = -1
  call testSub(aa, bb=bb)
  allocate(bb(2))
  aa(:) = -2
  bb(:) = -4
  call testSub(aa, bb=bb)

end program test

 

0 Kudos
5 Replies
mecej4
Honored Contributor III
956 Views

Your example code touched upon some Fortran language rules that I had to educate myself about. The question I had was "can one distinguish between (i) a non-present optional allocatable argument, and (ii) a present optional unallocated argument?" I had to look up the Fortran Standard, and the following excerpt answers the question. The excerpt also shows (Restriction-3(1)) that your program is in error in that it references (on Line-12) the unallocated dummy argument bb in the first call to the subroutine.

pres.png

0 Kudos
FortranFan
Honored Contributor II
956 Views

mecej4 wrote:

Your example code touched upon some Fortran language rules that I had to educate myself about. The question I had was "can one distinguish between (i) a non-present optional allocatable argument, and (ii) a present optional unallocated argument?" I had to look up the Fortran Standard, and the following excerpt answers the question. The excerpt also shows (Restriction-3(1)) that your program is in error in that it references (on Line-12) the unallocated dummy argument bb in the first call to the subroutine ...

I don't think the above is correct.  Third bullet under point 1 from section 12.5.1.12 shown above makes it clear, "A dummy argument.. is not present if the dummy argument  .. does not have the ALLOCATABLE .. and corresponds to an actual argument that .. has the ALLOCATABLE attribute and is not allocated .."  This is indeed the case in the code shown in the original post, so mecej4's assessment "the program is in error" appears to be incorrect.

Note the current Fortran standard i.e, 2008 (my reference basis is WD 1539-1, J3/10-007r1 (F2008 Working Document), 24th November 2010 16:43) also says in the Introduction, "A null pointer or unallocated allocatable can be used to denote an absent nonallocatable nonpointer optional argument."

The issue here is that Intel Fortran does not have this particular Fortran 2008 feature implemented.

0 Kudos
mecej4
Honored Contributor III
956 Views

The word "present" can be quite confusing here. Most people would see "call sub(...,optarg=arg)" and think that optarg is "present" because it is there, in plain sight. The Fortran standard carves out an exception: optarg is not "present" in the Fortran sense in that call if arg happens to be allocatable and not allocated. In that case, the argument arg is present in the textual sense, but PRESENT(arg) yields the value .FALSE.

A null pointer or unallocated allocatable can be used to denote an absent nonallocatable nonpointer optional argument

Fine, but what does that say about a present, allocatable, but unallocated, optional argument (with "present" used in the sense of common parlance)? It seems to me that the standard is hinting that for such arguments ALLOCATED and PRESENT are equivalent, in which case my statement about referencing bb was wrong. However, it is a bit disquieting that PRESENT has different meanings depending upon the nature of its argument. While writing the subroutine body, I would not be able to tell if PRESENT(arg) is .FALSE. because arg was used in the call but is allocatable and unallocated, or because arg was left out of the argument list in the call.

Am I creating confusion where there was none?

0 Kudos
FortranFan
Honored Contributor II
956 Views

mecej4 wrote:

.. While writing the subroutine body, I would not be able to tell if PRESENT(arg) is .FALSE. because arg was used in the call but is allocatable and unallocated, or because arg was left out of the argument list in the call.

Am I creating confusion where there was none?

As someone who has to write a few subroutines with OPTIONAL dummy arguments, it has not mattered to me whether the "arg was used in the call but is allocatable and unallocated" or "arg was left out of the argument list in the call."   Both these situations are treated similarly to that of an absent dummy argument and that hasn't caused any confusion or issues, as far as I can tell!

Now, interpreting the Fortran standard is indeed highly subjective and one can never be sure if one got it right.  However from everything I've seen, the code in the original post is valid with respect to Fortran 2008 and I've come across some discussions with respect to gfortran elsewhere that are consistent with the above code being conformant, and an additional bit of validation is gfortran which does support the particular Fortran 2008 feature runs just fine on the original code:

 AA:          -1          -1
 BB NOT PRESENT
 AA:          -2          -2
 BB:          -4          -4

 

0 Kudos
Bálint_A_
Beginner
956 Views

According to MRCs Modern Fortran, that was the intended behavior. When calling a routine with several optional arguments, you could end up with a cascade of if statements, when several call combinations are possible depending on your program status. (This is exactly the case in the scientific code I am developing). With Fortran 2008, this is greatly simplified, as you just pass allocatable arrays, and those, which do not make sense in the current program status, are not allocated anyway, so passing them would still make the present() function on the dummy argument in the subroutine to deliver .false..

IMHO, the Intel compiler does exactly the right thing, when the '-check pointers' option is not used during compilation and behaves the same way as several other recent Fortran compilers I've tried. It is only disturbing, that you can not use that important checking facility any more, as it gives a false positive alarm during run-time.

0 Kudos
Reply