- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
...
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@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).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
this bug is fixed in the 2024.0 release
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, this looks good now.
Thanks for fixing this!
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page