- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page