`d` specifier in `ignore_tkr` directive - fortran

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.

Related

Avoid implicit conversion between float and integer for an array index

I am looking for a way to force the Fortran compiler to give an error message when I am using a real number in a situation where I should not.
For example,
Real :: i1,i2
Real :: A(1000,1000) , B(2000,2000)
A(i1:i2,:) =B(i1:i2,1:1000)
I had a code like this and I was not realizing my declarations of i1 and i2.
Sometimes I used to get problems because of that until I realized it. Apparently, Fortran makes an implicit conversion, which I would rather be informed about.
Is there no way a Fortran compiler can see that the array is not being referenced with expected indices?
The Fortran language specification requires an array subscript to be a (scalar) integer expression. Further, this is a part of the language that requires a valid Fortran compiler to be able to detect and report an attempt to violate this constraint.
Some compilers will choose to report this use of a real array index by default as an error. Others may accept it as an extension and possibly providing a diagnostic warning. The Intel compiler (currently) defaults to silently accepting this as an extension. Even in those cases where a diagnostic isn't made, there should be an option to enable such reporting (for the compiler to be conforming to the Fortran specification).
In the case of ifort, the option -stand:
warning #6187: Fortran 2008 requires an INTEGER data type in this context.
You can even combine this with -diag-error=6187 to upgrade the diagnostic to an error.

Is the "present()" intrinsic evaluated at compile time

When dealing with optional arguments in fortran I believe it's typical to branch using the present() intrinsic, i.e.:
subroutine foo(ii,jj)
implicit none
integer, intent(in) :: ii
integer, optional :: jj
if (present(jj)) then
! do something
else
! do something else
end if
end subroutine foo
My assumption (coming from a C++ world) is that present() is hopefully a compile-time construct, and that there won't be any associated runtime performance penalty. I expect that the compiler should be able to (should be required to?) optimise the if statement shown above away, depending on whether foo(ii) or foo(ii,jj) is called.
How is the present() intrinsic handled by compilers in practice? Does the fortran spec guarantee certain behaviour?
PRESENT is a runtime concept - to the extent that the presence of an argument may depend on aspects of the program that cannot be determined until runtime (based on input read from a file or similar).
The implementation of the equivalent of PRESENT in a C++ program would similarly be a runtime concept. Note that C++'s defaulted arguments feature is not quite the same concept as Fortran's optional arguments feature (though it could be part of an equivalent implementation).
Beyond compiler optimization cleverness, if you want compile time resolution of things similar to C++'s defaulted arguments or function overloading, then consider using multiple specific procedures behind a generic name, one variant of the specific with the "optional" argument, the other without.
That depends (what else did you expect? :-)
If you use gfortran with a recent version, and do a lot of work in at least one of the branches, and use LTO or put everything into one file, the compiler will clone the function for you (via constant propagation). Otherwise, probably not. If you want to find out if the procedure foo has been cloned, grep for foo.*constprop in the assembly file.
An alternative to one subroutine with an optional argument is two subroutines, one with the argument, and one without, sharing the same interface. I don't think there is a run-time cost for doing this as opposed to giving the two versions of the subroutine different names. Schematically, it looks like this:
interface foo
module procedure foo_1,foo_2
end interface foo
contains
subroutine foo_1(ii)
! some code
subroutine foo_2(ii,jj)
! some code

Difference between newer implementation and older implementations

I am a newbie to Fortran. Please look at the code below:
c main program
call foo(2)
print*, 2
stop
end
subroutine foo(x)
x = x + 1
return
end
In some implementations of Fortran IV, the above code would print a 3. Why is that? Can you suggest an explanation?
How do you suppose more recent Fortran implementations get around the problem?
Help is very much appreciated. Thank You.
The program breaks the language rules - the dummy argument x in the subroutine is modified via the line x = x + 1, but it is associated with something that is an expression (a simple constant). In general, values that result from expressions cannot be modified.
That specific code is still syntactically valid Fortran 2008. It remains a programming error in Fortran 2008 - as it was in Fortran IV/66. This isn't something that compilers are required to diagnose. Some may, perhaps with additional debugging options, and perhaps not till runtime.
Because the program breaks the language rules anything could happen when you run the program. Exactly what depends on the code generated by the compiler. Compilers may have set aside modifiable storage for the value that results from the expression such that it internally looks like a variable (the program might print three and the program carries on), that modifiable storage might be shared across the program for other instances of the constant 2 (suddenly the value of 2 becomes three everywhere!), the storage for the value of the constant might in non-modifiable memory (the program may crash), the compiler may issue an error message, the program may get upset and sulk in its bedroom, the program might declare war on a neighbouring nation - it is a programming error - what happens is unspecified.
As of Fortran 90, facilities were introduced into the language to allow programmers to write new code that is practical for compilers to check for errors such as these (and in some cases compilers are required to check for errors if they are to be regarded as standard conforming).
For the code as presented, the main program and the subroutine are to be regarded as separately compiled - the main program is unaware of the details of the subroutine and vice versa (it is possible that the subroutine could be compiled long after the main program, on a different machine, with the outputs of the two being linked together at some later stage - without fancy link time behaviour or static analysis it is therefore not possible to resolve errors such as this). Language rules are such that when compiling the main program the compiler must implicitly assume the details of the interface of the subroutine based only on the way the subroutine is referenced - inside the main program the subroutine has an implicit interface.
Fortran 90 introduced the concept of an explicit interface, where the compiler is explicitly told what the interface of the subroutine in various ways, and can then check that any reference to the subroutine is consistent with that interface. If a procedure is a module procedure, internal procedure or intrinsic procedure - that interface is automatically realized, alternatively for external subprograms, procedure pointers, etc, the programmer can explicitly describe the interface using an interface block.
In addition, Fortran 90 introduced the intent attribute - a characteristic of a dummy argument of a procedure that is also then a characteristic of the interface for a procedure. The intent of the argument indicates to the compiler whether the procedure may define the argument (it also may implications for default initialization and component allocation status) and hence whether an expression could be a valid actual argument. x in subroutine foo would typically be declared INTENT(INOUT).
Collectively these new language features provide a robust defence against this sort of programming error when using compilers with a basic level of implementation quality. If you are starting with the language then it is recommended that these new features become part of your standard approach - i.e. use implicit none, all procedures should generally be module procedures or internal procedures, use external procedures only when absolutely required, always specify dummy argument intent, use free form source.

gfortran - assign string to parameter

[NOTE: contains repetition of previous question but posted separately as separate issues]
I am compiling a program which is known to compile with ifort using gfortran. However the compiler fails on the line
PARAMETER (POS='^')
with the compile error:
conv_prof.mac:9.21:
Included at conv_prof.f:811:
PARAMETER (POS='^')
1
Error: Can't convert CHARACTER(1) to REAL(4) at (1)
make: *** [conv_prof.o] Error 1
As it turns out the POS parameter is not used (it is likely a legacy parameter) so I may simply uncomment this line to compile, but I would like to know if anyone might have any idea why this is an issue in gfortran and not ifort?
Cheers,
Derek
The Intel compiler is the descendant of a long line of Fortran compilers. Its ancestors implemented all sorts of non-standard behaviour and, in the true spirit of Fortran, the latest versions of the compiler ought to compile the most ancient codes. You can often tell ifort to warn of non-standard features in your codes by judicious use of compiler flags.
gfortran, on the other hand, does not (by default) accept much in the way of non-standard syntax, other than those forms of non-standard syntax which have been so widely used that many unsuspecting programmers think that they are standard forms (eg real*4 and the like).
Your snippet looks to me to come from the days prior to FORTRAN77 when the language didn't really acknowledge the existence of such new-fangled ideas as non-numeric variables. In this case I recommend that you follow gfortran in disallowing this code, rather than Intel Fortran.
The specific extension here is that ifort allows a program to "assign" a character value into a real object. Perhaps it was intended to use this extension - but a more likely explanation is that a type declaration statement for the parameter pos is missing prior to the PARAMETER statement.
Technically I don't think the standard requires a diagnostic in this case (this isn't a violation of the syntax rules or constraints of the standard - it is a violation of the requirements placed on the program in the body text), but you'll get a diagnostic from ifort if you turn on standards checking (/stand or -stand, depending on your platform).

Fortran: passing same array as two dummy arguments to subroutine

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)