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

IFX 2025 throws exception error when optional argument is missing

avinashs
New Contributor I
668 Views

I am trying to switch to IFX 2025 (after many years of IFORT usage). There are some errors coming up that were not encountered in IFORT. One such error is included here (minimum reproducible example attached). A subroutine has an optional argument. If that argument is missing, then statements referencing that argument throw an exception error. In the example below, if sub1 is called with missing n3, the merge function throws an exception error. This error does not occur in IFORT or gfortran. Since I use this liberally in several subroutines, it will be difficult to rewrite the code. Any help as always is appreciated. Would also appreciate some background on whether this use of an optional argument is incorrect according to the Fortran standard but is only being enforced in IFX 2025.

 

subroutine sub1(n, n1, n2, n3)
integer :: n1, n2
integer, optional :: n3
n = merge(n3, 2, present(n3))      .... this line throws an error
if (n == 3) then
n = n1 + n2 + n3
else
n = n1 + n2
end if
end subroutine sub1

0 Kudos
1 Solution
Mark_Lewy
Valued Contributor I
592 Views

Your code looks like non-standard Fortran to me - the specification (from N2184 Fortran 202x  working draft 16.9.139) is

MERGE (TSOURCE, FSOURCE, MASK)
TSOURCE may be of any type.
FSOURCE shall be of the same type and type parameters as TSOURCE.
MASK shall be of type logical.

As TSOURCE is not an optional argument, passing an optional value to it is non-standard

I suppose you have been lucky with IFORT and GNU Fortran ignoring the non-present argument and IFX is strictly following the standard.

View solution in original post

8 Replies
Mark_Lewy
Valued Contributor I
593 Views

Your code looks like non-standard Fortran to me - the specification (from N2184 Fortran 202x  working draft 16.9.139) is

MERGE (TSOURCE, FSOURCE, MASK)
TSOURCE may be of any type.
FSOURCE shall be of the same type and type parameters as TSOURCE.
MASK shall be of type logical.

As TSOURCE is not an optional argument, passing an optional value to it is non-standard

I suppose you have been lucky with IFORT and GNU Fortran ignoring the non-present argument and IFX is strictly following the standard.

andrew_4619
Honored Contributor III
585 Views
Merge evaluates both Args irrespective of the present check so you code is invalid.
avinashs
New Contributor I
495 Views

Thanks for the responses and useful information. My conclusion from the responses is that IFORT, since MERGE became available, did not evaluate both arguments and as a result, Y = MERGE(OPTARG, DEFAULT_VALUE, PRESENT(OPTARG)) worked correctly without error even if OPTARG was absent. This appears to also be the case with gfortran since it does not throw an error either.

My suggestion for the documentation is that it be updated to specifically include situations such as the above and the fact that both arguments will be evaluated. Clearly, the standard does not specify that both arguments must be evaluated or else IFORT and gfortran are both in violation of the standard.

This is an example of the problems that are going to occur when porting from IFORT to IFX, especially for those dealing with large amounts of legacy code.

0 Kudos
andrew_4619
Honored Contributor III
417 Views

My experience is that ifort will crash just the same, maybe it depends on options like optimisation, standard -semantics etc. any which way you need to fix the code.

avinashs
New Contributor I
196 Views

I tried various options but IFORT seems to work fine (so does gfortran). However, based on the useful suggestions above, I created a wrapper routine to circumvent the problem. Now if mask is false for a missing argument checked with mask=present(arg), the corresponding missing argument t passed to my_merge is not assigned to the result. Using my_merge eliminates the error with IFX and IFORT is unaffected.

function my_merge(t, f, mask)
   integer :: my_merge
   integer, intent(in) :: t, f
   logical, intent(in) :: mask
   if (mask) then
       my_merge = t
   else
       my_merge = f
   end if
end function my_merge

The IFX implementation of merge appears to be something as below

function ifx_merge(t, f, mask)
   integer :: ifx_merge
   integer, intent(in) :: t, f
   logical, intent(in) :: mask
   integer :: a, b
   a = t                             ! throws an error if mask is false due to a missing argument
   b = f
   if (mask) then
       ifx_merge = a
   else
       ifx_merge = b
   end if
end function ifx_merge

0 Kudos
JohnNichols
Valued Contributor III
148 Views

Am I correct in thinking that merge (that I was not aware existed) is merely 

if(mask) pick t

else pick f

Why did anyone think we needed such a function? 

 

0 Kudos
andrew_4619
Honored Contributor III
117 Views

Whilst you can use 2 scalers it is designed to works with arrays on an element by element basis to in general mask is a logical array.

0 Kudos
Steve_Lionel
Honored Contributor III
94 Views

MERGE operates on arrays too, and that's where it's most useful. However, the Fortran 2023 conditional expression feature is really what one wants to use here. Unfortunately, ifx doesn't support it yet.

0 Kudos
Reply