I am attempting to compile the following on intel MacOS 10.14.6 with what I think is the latest version of the ifort intel compiler.
$ cat cte.f90
use iso_fortran_env, only: compiler_options, compiler_version
character(*), parameter :: compiled_by = compiler_version()
character(*), parameter :: compiled_with = compiler_options()
end
$ ifort --version
ifort (IFORT) 2021.6.0 20220226
Copyright (C) 1985-2022 Intel Corporation. All rights reserved.
$ ifort -c cte.f90
cte.f90(2): error #6263: This intrinsic function is invalid in constant expressions. [COMPILER_VERSION]
character(*), parameter :: compiled_by = compiler_version()
-----------------------------------------^
cte.f90(3): error #6263: This intrinsic function is invalid in constant expressions. [COMPILER_OPTIONS]
character(*), parameter :: compiled_with = compiler_options()
-------------------------------------------^
compilation aborted for cte.f90 (code 1)
This is almost identical to an example in Modern Fortran Explained. These intrinsic functions were introduced in f2008, so Iām not pushing any limits regarding new features. Iām wondering, is this a problem with my code, or with the compiler, or what?
Edit: With respect to the inquiry re: a bug in Intel Fortran in the original post, please see this comment post further below in this thread.
The operative word is āalmostā: you have the answer in the error message, āThis intrinsic function is invalid in constant expressions.ā The standard is rather limiting when it comes to what is allows in constant expressions and the standard defined functions from the intrinsic module ISO_FORTRAN_ENV are not among the permitted ones.
You can try this out first where the restrictions of constant expressions with defining named constants do not apply:
use iso_fortran_env, only: compiler_version
character(len=:), allocatable :: compiled_by
compiled_by = compiler_version()
print *, compiled_by
end
C:\temp>ifort /standard-semantics p.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.6.0 Build 20220226_000000
Copyright (C) 1985-2022 Intel Corporation. All rights reserved.
Microsoft (R) Incremental Linker Version 14.30.30706.0
Copyright (C) Microsoft Corporation. All rights reserved.
-out:p.exe
-subsystem:console
p.obj
C:\temp>p.exe
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel
(R) 64, Version 2021.6.0 Build 20220226_000000
The only difference in my code and the MFE code is that theirs is in a module. I just put the same statements into a four line main program when I posted it here. MFE says āThese functions may be used in initialization expressions, for exampleā¦ā and then they show their code.
This sentence is in both the f2008 and the f2018 version of MFE. So if it was a mistake, they had 10 years to correct it and they failed to change it.
Can you tell me where in the f2018 standard to look for the list of included/excluded intrinsic functions?
It looks like that bug was fixed in the version of the compiler that Iām using. If it is a bug in the compiler, and not my code, then perhaps they are related bugs.
On a related question, in that example the trim() function was used. Iāve been assuming that the return values for those two functions are already in their trimmed form. At least for the versions of gfortran that Iāve tried where this code works, that has been the case. trim() is easy enough to add, but is it necessary? Are there any known compilers that do not returned trimmed values for those two intrinsic functions?
My take earlier was that the standard states, āThe types and procedures defined in standard intrinsic modules are not themselves intrinsic.ā And thus compiler_version and compiler_option functions are not themselves intrinsic. Then in the section on constant expressions, the standard permits all transformational functions that are āstandard intrinsic functionsā in constant expressions. But it fails to spike out compiler_version and compiler_option functions as being allowed, so I had felt Intel Fortran was right to issue the diagnostic it did since anything that is not listed as allowed is by definition disallowed per the standard when it comes to constant expressions.
But since OP mentions the example in MFE, I am thinking there might be another āoutā for these two functions to appear in constant expressions that Intel Fortran and I have not discovered yet. This is what I will try to check when I have a bit more time.
The standard says the length of the returned values are āprocessor dependentā so the trim() seems prudent even if all the current implementations return it trimmed (not that I know if they do or not).
At least two compilers replace the function call with a fixed string value, which would avoid any problem with using it for initialization:
Confirmed this is a bug in Intel Fortran. A support request has been filed with their software team.
The standard states in the section on Specification Expression, āA specification inquiry is a reference to ā¦ the COMPILER_VERSION or COMPILER_OPTIONS function from the intrinsic module ISO_FORTRAN_ENV (16.10.2.6, 16.10.2.7).ā
The use of a specification inquiry with constant expression arguments are allowed in a constant expression, among other things. There are no parameters to the compiler_version and compiler_options functions, so they are covered.
Thus the use of compiler_version and compiler_options in the definition of a named constant is permitted and Intel Fortran compiler is incorrect in issuing the error diagnostic.
I found a workaround for the Intel bug on compiler_version and compiler_options: putting the function result into an allocatable character scalar because you donāt know in advance how long it will be.
However an Intel oddity remains, as indicated in the comment lines at the beginning of my test program. I donāt know if that is an Intel bug.
! OK in gfortran and ifort. Note: gfortran starts printing the version on
! the same line as 'Compiler version using ' but ifort starts a new line for
! the version if you use neither (2A) nor //. With both the length is chosen
! by the compiler. Analogous results with options instead of version.
program test
use iso_fortran_env, only: compiler_version
character(:), allocatable:: version
version = compiler_version()
print *,'Compiler_version() length =',len(version)
print *,'Compiler_version() using , is ', version
print *,'Compiler_version() using // is '//version
print "(2A)",'Compiler_version() using , is ',version
print "(2A)",'Compiler_version() using // is '//version
end program test
Yes, the intel compiler functions work alright when the functions appear in executable statements. The bug is when they appear in initialization statements such as for character parameters.
Regarding the newline, that is a feature of list-directed i/o. The compiler has great freedom to add spaces and new lines and to choose field widths. If you want to nail down how the output looks, then use some kind of explicit format.
Thank you Ron. I had not realised that list-directed io was free to put a newline between two character variables separated only by a comma. But an additional test made me suspect an ifort bug. The following program wonāt compile with ifort but it compiles and runs if the len in it is replaced by len_trim .
program test3
use iso_fortran_env, only: compiler_version
character(:),allocatable:: stuff
stuff = repeat('%',len(compiler_version()))
print *,'percent = ',stuff
print *,'version = ',compiler_version()
end program test3
The error message:
test3.f90(4): error #6264: This operator is invalid in a constant expression evaluation. [LEN]
stuff = repeat('%',len(compiler_version()))
---------------------^
compilation aborted for test3.f90 (code 1)
I do not see why len is invalid in that executable statement. Gfortran allows it.
By the way ifortās error message, which I had put between triple back-quotes, was truncated by Fortran Discourse. After āexpressionā the first line continued with āevaluation. [LEN]ā
I think the original code is correct, and ifort has a bug.
program test3
use iso_fortran_env, only: compiler_version
character(:),allocatable:: stuff
stuff = repeat('%',len(compiler_version()//''))
print *,'percent = ',stuff
print *,'version = ',compiler_version()
end program test3
The above also works alright with ifort. Note that a zero-length character string is appended to the function result. That appears to be enough for ifort to dig itself out of whatever hole it was in.
$ ifort test3.f90 && a.out
percent =
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
version =
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel
(R) 64, Version 2021.7.0 Build 20220726_000000
Notice how ifort inserts new lines even within the character strings. That is allowed by list-directed i/o.