- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
the following testcase seems to exhibit an issue with argument evaluation prior to invocation of an elemental procedure:
program p
implicit none
integer, parameter :: n = 3
integer :: a = 0, b(n) = 0 ! counters for argument evaluation
integer :: c(n)
a = 0
b = 0
print *, merge (a, b, .true.) ! check: MERGE is elemental
print *, merge (b, a, .true.)
a = 0
b = 0
c = merge (g(a), g(b), .true.)
print *, "a=", a, " <- should be 1"
print *, "c=", c
a = 0
b = 0
c = merge (g(b), g(a), .false.)
print *, "a=", a, " <- should be 1"
print *, "c=", c
a = 0
b = 0
c = f(g(a), g(b)) ! g(a),g(b) should be evaluated just once
print *, "a=", a, " <- should be 1"
print *, "b=", b
print *, "c=", c
contains
elemental function f (x, y)
integer :: f
integer, intent(in) :: x, y
f = x+y
end function f
! Helper function for counting of argument evaluations
impure elemental integer function g (x)
integer, intent(inout) :: x
x = x+1
g = x
print *, "in g: x=", x
end function g
end program p
E.g. F2023, 15.5.3 (functions) and 15.5.4 (subroutine reference) explicitly state that actual arguments are to be evaluated before argument association. This means that g(a) and g(b) shall be invoked exactly once in each of the above cases when used as argument in a function reference.
I find this confirmed e.g. with the NAG compiler, which prints for the above:
0 0 0
0 0 0
in g: x= 1
in g: x= 1
in g: x= 1
in g: x= 1
a= 1 <- should be 1
c= 1 1 1
in g: x= 1
in g: x= 1
in g: x= 1
in g: x= 1
a= 1 <- should be 1
c= 1 1 1
in g: x= 1
in g: x= 1
in g: x= 1
in g: x= 1
a= 1 <- should be 1
b= 1 1 1
c= 2 2 2
However, with current ifort/ifx I get:
0 0 0
0 0 0
in g: x= 1
in g: x= 1
in g: x= 2
in g: x= 1
in g: x= 3
in g: x= 1
a= 3 <- should be 1
c= 1 2 3
in g: x= 1
in g: x= 1
in g: x= 1
in g: x= 2
in g: x= 1
in g: x= 3
a= 3 <- should be 1
c= 1 2 3
in g: x= 1
in g: x= 1
in g: x= 2
in g: x= 1
in g: x= 3
in g: x= 1
a= 3 <- should be 1
b= 1 1 1
c= 2 3 4
So neither the elemental intrinsic MERGE nor a user-defined elemental function case agree with NAG.
While the above may appear a little academic, it may be important for situations when the types involved are finalizable.
Thanks,
Harald
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I agree that it looks like a compiler problem to me. When function g(x) is passed a scaler the result should be a scaler temp which merge should promote/expand to a temporary array to match the size/shape of the other merge parameter.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you for reporting this. Again you submitted a great reproducer.
I filed a bug, CMPLRLLVM-48874. I will let you know when a fix is ready.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Harald1, this issue with both ifx and ifort is fixed in the compilers that were fixed earlier this week. Please try them!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Confirmed. This now works for me.
Thanks!
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page