In the documentation of the GNU Fortran compiler, for a specific intrinsic function, there is a standard. For example, CPU_TIME is an intrinsic procedure for which it is indicated that the standard is Fortran 95 and later. My question is about the meaning of this.
I understand the Fortran standard to be like a set of rules to follow for your code to be defined as standard-compliant (to Fortran 77,90,95,2003 or 2008). Does this mean that CPU_TIME can only be used with Fortran 95+? Actually, I already know the answer, I can use CPU_TIME within a Fortran 77 file with the .f extension without the compiler to complain, compiling with a Gfortran version > 5. Is that because the compiler is able to treat any standard encountered in a code? I am aware of the -std flag but how can I be sure that for instance a Fortran 77 code uses only intrinsic procedures for Fortran 77?
Short answer, you can not distinguish standard below f95 with gnu compilers. From f95 and above, you can use the option -std to force the compiler to consider features of standard above as errors.
Long answer:
The documentation of gnu compiler says this:
-std=std
Specify the standard to which the program is expected to conform, which may be one of ‘f95’, ‘f2003’, ‘f2008’, ‘gnu’, or ‘legacy’. The
default value for std is ‘gnu’, which specifies a superset of the
Fortran 95 standard that includes all of the extensions supported by
GNU Fortran, although warnings will be given for obsolete extensions
not recommended for use in new code. The ‘legacy’ value is equivalent
but without the warnings for obsolete extensions, and may be useful
for old non-standard programs. The ‘f95’, ‘f2003’ and ‘f2008’ values
specify strict conformance to the Fortran 95, Fortran 2003 and Fortran
2008 standards, respectively; errors are given for all extensions
beyond the relevant language standard, and warnings are given for the
Fortran 77 features that are permitted but obsolescent in later
standards. ‘-std=f2008ts’ allows the Fortran 2008 standard including
the additions of the Technical Specification (TS) 29113 on Further
Interoperability of Fortran with C and TS 18508 on Additional Parallel
Features in Fortran.
- `-std=f95` will consider features above f95 as errors
- `-std=f2003` will consider features above f2003 as errors
- `-std=f2008` will consider features above f2008 as errors
- etc.
You might want to check with other compilers.
Easy verification:, compile the following program (courtesy of Fortran wiki) with and without the option -std=f95 and see what happens.
module class_Circle
implicit none
private
real :: pi = 3.1415926535897931d0 ! Class-wide private constant
type, public :: Circle
real :: radius
contains
procedure :: area => circle_area
procedure :: print => circle_print
end type Circle
contains
function circle_area(this) result(area)
class(Circle), intent(in) :: this
real :: area
area = pi * this%radius**2
end function circle_area
subroutine circle_print(this)
class(Circle), intent(in) :: this
real :: area
area = this%area() ! Call the type-bound function
print *, 'Circle: r = ', this%radius, ' area = ', area
end subroutine circle_print
end module class_Circle
program circle_test
use class_Circle
implicit none
type(Circle) :: c ! Declare a variable of type Circle.
c = Circle(1.5) ! Use the implicit constructor, radius = 1.5.
call c%print ! Call the type-bound subroutine
end program circle_test
Related
Internet has a lot of open source code written in the Fortran programming language. Sometimes the 'intrinsic' keyword can be met in a code. I saw that the 'intrinsic' keyword can be used with 'use' keyword. Here is an example:
program main
use, intrinsic :: iso_fortran_env, only : int8, int16, int32, int64
implicit none
!
! Some code
!
end program main
I would like to understand better and more correctly the purpose of the application of this keyword in this context.
I have this old code
module foo
interface
subroutine bar(A)
!dir$ ignore_tkr(trd) A
DOUBLE COMPLEX, DIMENSION(*) :: A
end subroutine
end interface
end module foo
This is compiled fine by nvfortan and gfortran compilers. Yet, LLVM Flang cannot even parse it, because it doesn't know what d in the ignore_tkr means.
I assume, it means "ignore dimension". But I couldn't google anything up about it.
Could someone please send something to read about it and/or explain in details this thing?
Compiler directives are compiler specific. Note that for a standard Fortran compiler without any extensions they are just comments and will be ignored. The fact that it compiles with many compilers may just mean that those compilers ignore that directive altogether.
Some compilers will understand
!DIR$
other will understand
!DEC$
or
!GCC$
Gfortran, for example. has no obligation to understand directives specific to other compilers and will just ignore the directive you have shown.
For example, gfortran understand these directives https://gcc.gnu.org/onlinedocs/gfortran/GNU-Fortran-Compiler-Directives.html
For directives supported by Flang, consult the documentation https://releases.llvm.org/12.0.0/tools/flang/docs/Directives.html
Note that !dir$ ignore_tkr (tkr) var-list is supported by Flang and will omit checking the type, kind and/or rank of arguments passed to the procedure.
You specify the desired checks in the (tkr). You use all of t, k, and r if you want to disable all three. The letter d is not among the possible letters to use and hence is erroneous. If you want to disable the checks for the number of dimensions of the array, use r for rank.
Rank is the correct word that is used for the number of dimensions of an array in the Fortran standard.
The same syntax holds for nvfortran, see section 4.4 in https://docs.nvidia.com/hpc-sdk/archive/20.7/compilers/pdf/hpc207ref.pdf The only admissible parameters are t, k or r. No, d is not allowed. It does not mean anything in this context for these compilers.
The programmer may have used d instead of r inadvertently and the nvfortran compiler may ignore that or may even silently convert that to d. Such behaviour would only be specific to that compiler. I would just convert the d into r if it makes sense in that context.
4.4.1. IGNORE_TKR Directive Syntax
The syntax for the IGNORE_TKR directive is this:
!DIR$ IGNORE_TKR [ [(<letter>) <dummy_arg>] ... ]
<letter> is one or any combination of the following:
T – type
K – kind
R – rank
For example, KR indicates to ignore both kind and rank rules and
TKR indicates to ignore the type, kind, and rank arguments
In nvfortran, the d specifier to the ignore_tkr directive tells the compiler to ignore the presence or absence of the device attribute in argument matching when compiling CUDA Fortran codes.
What does it mean when the intrinsic keyword is added to the use statement for a module, as in the following example?
use, intrinsic :: iso_c_binding
(From
7.1 Overview of Fortran interface, FFTW 3.3.6-pl1)
Does it specify that a module of that name provided with the compiler should be used, even if there is another module of the same name written by the user?
With use, intrinsic :: ... the intrinsic module is indeed chosen.
There is perhaps a slight subtlety in the question worth addressing. With regards to "a module of that name provided with the compiler should be used", this "should" doesn't indicate a preference but a strong requirement. That is, if there's no such intrinsic module then compilation cannot succeed. This shouldn't be a problem with iso_c_binding but compilers often offer their own non-standard intrinsic modules.
There is no way to say "use the intrinsic module if it's available, but the user-provided one if not".
The source code I am working with was originally written for the Intel Fortran compiler so it has preprocessor directives such as
!DEC$ATTRIBUTES DLLEXPORT::MYDLL
!DEC$ATTRIBUTES STDCALL::MYSUBROUTINE
!DEC$ATTRIBUTES ALIAS: 'MYENTRYPOINT'::MYSUBROUTINE
How do I convert this to work with gfortran.
Mainly I want to be able to define and name entry points. Right now when I compile with gfortran every subroutine gets exposed as an entry point. Also the entry point name are all lower case with a underscore at the end.
If you place your routines into a module and put the statement PRIVATE at the top of the module, then PUBLIC :: name1, name2, only the procedures name1 and name2 will be visible outside of the module. This should follow through to a library into which you place object code containing the module. This has been supported since Fortran 90.
As already answered by #janneb, you can use the bind (C,name=X) approach to take complete control of the externally visible name of a procedure, overriding the Fortran name of the procedure. This is part of Fortran 2003 and is supported by numerous compilers for years. A possible issue with the bind(C) approach that it specifies that the calling convention of the routine should be that of C. If this is different from that Fortran and you wish to call these routines from Fortran the complexity increases. Then you would have to specify an interface to inform the calling Fortran routines that they are calling what looks like a C routine. Since people rarely care about the name visible to the linker unless they are calling from C, you might want the C calling convention?
Examples at Private function in Fortran and C/C++, FORTRAN, underscores, and GNU Autotools
GFortran supports some attributes, see
http://gcc.gnu.org/onlinedocs/gfortran/GNU-Fortran-Compiler-Directives.html#GNU-Fortran-Compiler-Directives
For changing the symbol name, you can use the bind(C, name=) specifier of ISO_C_BINDING, see e.g.
http://gcc.gnu.org/onlinedocs/gfortran/Interoperable-Subroutines-and-Functions.html#Interoperable-Subroutines-and-Functions
http://gcc.gnu.org/onlinedocs/gfortran/Interoperable-Global-Variables.html#Interoperable-Global-Variables
Suppose I have a subroutine which accepts two arrays as input. One is given intent(in) and the other is given intent(out). The latter is derived from the former in an arbitrary manner. However, what if I pass through the same actual argument for both dummy arguments? In general, the result will not be what was intended by the subroutine. See code snippet below.
The problem is, the compiler doesn't seem to care, even though I've given intent flags. I'm using Intel Visual Fortran Composer 12, with all diagnostics. Is there a better way of coding the subroutine, or some compiler option I'm missing, to make the code safer?
module foo
contains
subroutine sub_a()
implicit none
real::array(10,10)
call sub_b(array,array)
end subroutine
subroutine sub_b(array1,array2)
implicit none
real,intent(in)::array1(10,10)
real,intent(out)::array2(10,10)
!array2 is derived from array1 somehow
end subroutine
end module foo
This is called aliasing -- referring to the same item by two different names. In most cases this is not allowed in Fortran. Your example is not legal Fortran -- see http://software.intel.com/en-us/blogs/2009/07/10/doctor-fortran-in-ive-come-here-for-an-argument-side-2/, which has this specific case, of aliasing via the same actual argument used for two dummy arguments. Fortran compilers are not required to diagnose all violations of the rules of the language and this appears to be an example that the compiler is not recognizing.
Edit: aliasing is permitted. What is forbidden is changing the value of the dummy argument through the alias, here the other dummy argument. The rules are less restrictive for pointer and target arguments. The specific rules are described in "The Fortran 2003 Handbook" by Adams et al.
Putting parentheses around the argument that is intent(in) makes the code legal since you are effectively passing a copy:
call sub_b((array),array)