-
Notifications
You must be signed in to change notification settings - Fork 61
Optional argument used before checking present #201
Description
The NAG compiler fails to build the D4 library with the error message
Runtime Error: ../../../LibSource/dftd4-3.4.0/src/dftd4/param.f90, line 526: Reference to OPTIONAL argument S9 which is not PRESENT
This is the due to the use of merge on optional arguments in the following routine:
523 real(wp), intent(in) :: s8, a1, a2
524 real(wp), intent(in), optional :: s6, alp
525 type(rational_damping_param) :: param
526 param = rational_damping_param(&
527 & s6=merge(s6, 1.0_wp, present(s6)), &
528 & s8=s8, a1=a1, a2=a2, &
529 & s9=merge(s9, 1.0_wp, present(s9)), &
530 & alp=merge(alp, 16.0_wp, present(alp)))
531 end function dftd_param
The nvidia compiler compiles this successfully, but crashes on a line using a similar construct:
0x00000000016ab37d in dftd4_param::get_rational_damping () at ../../../LibSource/dftd4-3.4.0/src/dftd4/param.f90:69
69 mbd = merge(s9 /= 0.0_wp, .true., present(s9))
According to this thread on the intel compiler forum, the merge statement may evaluate either or both of the source values and does not have to short circuit. This leads to the optional values being possibly evaluated, while being undefined and causing issues. The code should be replaced by a standard if else construct, eg
pure function dftd_param(s6, s8, a1, a2, alp) result(param)
real(wp), intent(in) :: s8, a1, a2
real(wp), intent(in), optional :: s6, alp
type(rational_damping_param) :: param
real(wp) :: s6_local, alp_local, s9_local
s6_local = 1.0_wp
if (present(s6)) s6_local = s6
s9_local = 1.0_wp
if (present(s9)) s9_local = s9
alp_local = 16.0_wp
if (present(alp)) alp_local = alp
param = rational_damping_param(&
& s6=s6_local &
& s8=s8, a1=a1, a2=a2, &
& s9=s9_local, &
& alp=alp_local,
end function dftd_param
and similarly for other cases where merge is used to check for "present"