https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117302

            Bug ID: 117302
           Summary: merge + present generates invalid code
           Product: gcc
           Version: 14.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: fortran
          Assignee: unassigned at gcc dot gnu.org
          Reporter: gigor-ads at yandex dot ru
  Target Milestone: ---

Hi!

With the following code, GCC generates wrong code:


real(8) function test1(a) result(r)
    implicit none
    real(8), intent(in), optional :: a
    r = merge(a, 1.0_8, present(a))
end function test1


With gfortran -O3 it is just 


test1_:
        movsd   xmm0, QWORD PTR [rdi]
        ret


So, it does not check that present(a) may be false and it put possible
inaccessible value a into r, then it leads to SegFaults if a was not present.

This code should be semantically as the following:


real(8) function test2(a) result(r)
    implicit none
    real(8), intent(in), optional :: a
    if (present(a)) then
      r = a
    else
      r = 1.0_8
    end if
end function test2


that has a proper assembler with check of present(a):

test2_:
        movsd   xmm0, QWORD PTR .LC0[rip]
        test    rdi, rdi
        je      .L3
        movsd   xmm0, QWORD PTR [rdi]
.L3:
        ret
.LC0:
        .long   0
        .long   1072693248


Just note that in some cases, it would be better to set values only after check
without setting default value (for simple types it is OK, but not for
user-defined).


See an example at godbolt: https://godbolt.org/z/969vr763M

Reply via email to