Avoid implicit conversion between float and integer for an array index - fortran

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.

Related

`d` specifier in `ignore_tkr` directive

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 "-flax-vector-conversions" exactly mean for ARM compiler?

I am tring to write a xxx.toolchain.cmake from arm-linux-gnueabihf gcc/g++ compiler.
What confused me is, whether should I use -flax-vector-conversions compilation flag or not. I read the doc/man page of the compiler, and it tells:
-flax-vector-conversions
Allow implicit conversions between vectors with differing numbers of elements and/or incompatible element types. This option should not be used for new code.
(via https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html)
My two confusions:
What does "vectors" mean in this explanation? Is there any example illustrate this?
What does "new code" mean? Why "new code" should not use with this compilation option?
GCC offers vector extensions that are meant to provide a way to access SIMD instructions in a machine-independent way (as opposed to intrinsics). This involves special vector types defined with __attribute__((vector_size(n))) to help the compiler understand the packed multiple-element data types that SIMD instructions use. Note that this has nothing to do with C++'s std::vector container.
Consider the following code:
typedef short eight_short __attribute__((vector_size(16)));
typedef int four_int __attribute__((vector_size(16)));
eight_short v1;
four_int v2;
void foo(void) {
v2 = v1;
}
Here four_int and eight_short are vectors of the corresponding number of elements and types. They are both 16 bytes and thus suitable to store in a 128-bit SIMD register. Assigning one to the other is clearly meant to "reinterpret" (aka bit-cast), but it also violates type safety. Presumably older versions of the compiler used to accept such code, and there may be code like this out there, but the compiler authors want to discourage it. So such code now causes an error by default, but they provide the option -flax-vector-conversions that you can use when compiling old code like this to suppress the error.
"New code" means code you are writing for the first time, where you have a choice as to how to write it. For such code you are most likely expected to use v2 = reinterpret_cast<four_int>(v1);, and not use -flax-vector-conversions. Then the compiler will flag any place where you forgot to cast (since it could be a bug where you actually meant something else).
If you're compiling legacy code, your best bet would be to first try building without this option. If it builds successfully, then the option is not needed, so don't use it. If it gets errors about conversions of vector types, you could consider using this option, or else rewrite the code with explicit casts where needed.

gfortran Error: Function 'inint' at (1) has no IMPLICIT type

I am using gfortran (from gcc-4.8.1) to compile a .f90 source file, and encountered an error that says:
Error: Function 'inint' at (1) has no IMPLICIT type
I did a bit of search and found that a GNU website says [ININT]
This intrinsic is not yet implemented. The name is, however, reserved
as an intrinsic.
In a SGI documentation, it is said
ININT returns the nearest INTEGER*2 to its REAL*4 argument.
My questions are:
Is ININT a Fortran77/90/95/2003 standard function?
In gfortran, what's the proper/standard-compliant way of writing a replacement function for INIT?
I have never used ININT before, and it probably is not of any standard. Instead, I would recommend to use NINT (FORTRAN 77), which takes an optional KIND argument (Fortran 90):
RESULT = NINT(A [, KIND])
(Taken from the GCC docs)
Choose KIND to reflect INTEGER*2, whatever that is for your specific compiler... But while you're at it, try SELECTED_INT_KIND.

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).