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

Bug/ICE with argument association / dummy argument with pointer attribute

Harald1
New Contributor II
941 Views

Hello,

the following issue points to a possibly not (properly) implemented Fortran feature:

program bug
  integer, pointer :: p(:), q
  allocate (p(3))
  p = [1, 42, 3]
  ! Argument association which works:
  call s1 (p(2))
  ! This is explained in F2018:15.5.2.7 clause 2 (or F2023:15.5.2.8):
  ! "... the actual argument shall be a pointer or a valid target
  !  for the dummy pointer in a pointer assignment statement. ..."
  q => p(2)      ! q is a pointer, p(2) is a valid target
  call s2 (q)    ! q is a pointer
  call s2 (p(2)) ! p(2) is still a valid target
  ! (wrong code with ifort / ICE with ifx)
contains
  subroutine s1 (x)
    integer, target              :: x
    print *, "s1: x=", x
  end subroutine s1
  subroutine s2 (x)
    integer, pointer, intent(in) :: x
    print *, "s2: associated(x)=", associated (x)
    print *, "s2: x=", x
  end subroutine s2
end program bug

 ifort 2021.9.0 compiles the code, but crashes at runtime:

 s1: x=          42
 s2: associated(x)= T
 s2: x=          42
 s2: associated(x)= T
forrtl: severe (174): SIGSEGV, segmentation fault occurred
Image              PC                Routine            Line        Source             
libpthread-2.31.s  000014731B1638C0  Unknown               Unknown  Unknown
a.out              0000000000403A69  bug_IP_s2_                 22  ifort-pointer-dummy.f90
a.out              00000000004038B4  MAIN__                     12  ifort-pointer-dummy.f90
a.out              000000000040366D  Unknown               Unknown  Unknown
libc-2.31.so       000014731AF8624D  __libc_start_main     Unknown  Unknown
a.out              000000000040359A  Unknown               Unknown  Unknown

 ifx 2023.1 crashes with an ICE, pointing to:

ifort-pointer-dummy.f90(12): error #5623: **Internal compiler error: internal abort** Please report this error along with the circumstances in which it occurred in a Software Problem Report.  Note: File and line given may not be explicit cause of this error.
  call s2 (p(2)) ! p(2) is still a valid target
-------^
compilation aborted for ifort-pointer-dummy.f90 (code 3)

 Note that NAG and gfortran handle the code just fine.

Thanks,

Harald

 

1 Solution
Ron_Green
Moderator
813 Views

Thanks to those involved in this interesting issue.

I created a bug report for this issue. CMPLRLLVM-48202

We have passed code freeze for the next update, 2023.2.0 so it won't be in that update release. I will keep this thread posted with progress towards a fix and release.


View solution in original post

0 Kudos
14 Replies
jimdempseyatthecove
Honored Contributor III
923 Views

 

...
  integer, pointer :: p(:), q
...
  call s2 (p(2)) ! p(2) is still a .NOT. valid target
...
  subroutine s2 (x)
    integer, pointer, intent(in) :: x

 

In the call p(2) references a scalar integer within an array allocated and associated to a pointer to an array.

The called procedure s2 requires a pointer be passed.

Therefore, the argument, itself, is not a pointer (to an integer), thus the compiler was in error for not detecting this.

From Pointer Arguments:

...

A dummy argument that is a pointer can be associated only with an actual argument that is a pointer. 

...

The compiler should not have aborted. Thanks for pointing this out.

Jim Dempsey

 

0 Kudos
IanH
Honored Contributor II
908 Views

Fortran 2008 introduced the concept of "auto-targeting", where POINTER, INTENT(IN) dummy arguments can be associated with actual arguments with the TARGET attribute. This language feature is specified by the text referenced in the example posted by the OP.

All objects referenced by POINTERS have the TARGET attribute.  The code is conforming.

The text quoted from the compiler reference is incorrect/out of date.

0 Kudos
jimdempseyatthecove
Honored Contributor III
888 Views

IanH,

Then the IVF/IFX documentation needs to clarify this.

 

I can see when a dummy argument is POINTER, INTENT(IN), but the actual argument is not a pointer, that synthesizing a pointer (descriptor) would be benign from a safety/operational standpoint but this would be lexically incorrect as the argument was not a pointer.

This said, this ( provisional POINTER, INTENT(IN)), is somewhat analogous to passing a parameter or literal as an actual argument that does not specify INTENT(IN). IOW newer compilers create a temporary (on stack) then pass the reference to that. Thus permitting the called routine to modify the temporary (that being the intention of the programmer). A warning might be nice, as this may avoid a structural error in the program.

In the case of POINTER, INTENT(IN) with actual argument being not a pointer, is NULLIFY(ptr) acceptable (as you are not writing to the variable).

Jim Dempsey

0 Kudos
jimdempseyatthecove
Honored Contributor III
885 Views

As a historical node (or should I say hysterical note), the FORTRAN II compiler I used in college, would permit a subroutine called with a literal, to write to the literal, thus changing the value of the literal.

Jim Dempsey

0 Kudos
IanH
Honored Contributor II
842 Views

@jimdempseyatthecove wrote:
...

In the case of POINTER, INTENT(IN) with actual argument being not a pointer, is NULLIFY(ptr) acceptable (as you are not writing to the variable).


No, but this is regardless of the nature of the actual argument.  You may not modify the association status of an INTENT(IN) pointer.  This is why this new (F2008) feature "works".

You CAN modify the value of the variable associated with an INTENT(IN) pointer. 

For pointer dummy arguments, the intent attribute applies to the pointer nature of the dummy argument, not the thing pointed at.  This is explained in the standard on the section on the intent attribute in the standard (F2018 8.5.10 p2-4).

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
916 Views

I suspect the NAG compiler is in error, as the actual argument in your sample code was not a pointer (to integer).

IIF NAG synthesized a pointer, when actual argument is not a pointer, then that would contradict the interface.

Maybe Steve L can jump in here as he sits on the Fortran Standards committee.

 

Jim Dempsey

 

0 Kudos
Ron_Green
Moderator
897 Views

While we wait and I review the Standards, I will point out that the upcoming 2023.2.0 ifx no longer gets an ICE.  Rather, it behaves like ifort.  ifx gives a runtime fault, just like ifort.

0 Kudos
Steve_Lionel
Honored Contributor III
877 Views

As best as I can tell, the OP's program is valid F2008. The issue here is the call to S2. As @IanH says, F2008 added the feature of passing a non-pointer to an INTENT(IN) pointer, as long as the actual would be a valid target in a pointer assignment. That is satisfied in this case (especially noting that line 10 was accepted.)

0 Kudos
jimdempseyatthecove
Honored Contributor III
828 Views

>>You may not modify the association status of an INTENT(IN) pointer. ...

>>You CAN modify the value of the variable associated with an INTENT(IN) pointer. 

Then this would be equivalent to removing ", POINTER, INTENT(IN)" from the dummy declaration.

IOW passing the reference to the pointee with either no INTENT or with INTENT(INOUT).

I suppose the only benefit (important one) is the pointer permits an association status to be tested as an analogy to present for optional argument.

 

Jim Dempsey

0 Kudos
Harald1
New Contributor II
799 Views

@jimdempseyatthecove wrote:

>>You may not modify the association status of an INTENT(IN) pointer. ...

>>You CAN modify the value of the variable associated with an INTENT(IN) pointer. 

Then this would be equivalent to removing ", POINTER, INTENT(IN)" from the dummy declaration.

IOW passing the reference to the pointee with either no INTENT or with INTENT(INOUT).

I suppose the only benefit (important one) is the pointer permits an association status to be tested as an analogy to present for optional argument.

 

Jim Dempsey


One can pass a NULL() argument to S2, but not to S1.  I'd consider that a benefit.

 

0 Kudos
IanH
Honored Contributor II
790 Views

With a sufficient compiler quality-of-implementation it is also a method to enforce that the actual argument, one level up the procedure call chain at least, has the target attribute  This can help prevent pointers that get associated with the actual argument and that outlive the procedure from becoming undefined when the procedure terminates.

  implicit none
  
  type :: wrapper
    integer, pointer :: ptr
  end type wrapper
  
  type(wrapper) :: wrap
  
  integer, target :: has_target
  integer :: not_target
  
  has_target = 1
  not_target = 2
  
  wrap = good_wrap(has_target)
  print *, wrap % ptr             ! ok
  
  !wrap = good_wrap(not_target)    ! compile time error
  
  wrap = bad_wrap(not_target)
  print *, wrap % ptr             ! Uh oh - wrap%ptr is undefined, 
                                  ! but we get no warning!
contains
  function good_wrap(targ)
    integer, intent(in), pointer :: targ
    type(wrapper) :: good_wrap
    good_wrap % ptr => targ
  end function good_wrap
  
  function bad_wrap(targ)
    integer, intent(in), target :: targ
    type(wrapper) :: bad_wrap
    bad_wrap % ptr => targ
  end function bad_wrap
end
Ron_Green
Moderator
814 Views

Thanks to those involved in this interesting issue.

I created a bug report for this issue. CMPLRLLVM-48202

We have passed code freeze for the next update, 2023.2.0 so it won't be in that update release. I will keep this thread posted with progress towards a fix and release.


0 Kudos
Ron_Green
Moderator
344 Views

this bug is fixed in the 2024.0 release


0 Kudos
Harald1
New Contributor II
336 Views

Yes, this looks good now.

Thanks for fixing this!

 

0 Kudos
Reply