gfortran - assign string to parameter - fortran

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

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.

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.

(v) is actually (*&v) since when?

Could C++ standards gurus please enlighten me:
Since which C++ standard version has this statement failed because (v) seems to be equivalent to (*&v)?
I.e. for example the code:
#define DEC(V) ( ((V)>0)? ((V)-=1) : 0 )
...{...
register int v=1;
int r = DEC(v) ;
...}...
This now produces warnings under -std=c++17 like:
cannot take address of register variable
left hand side of operand must be lvalue
Many C macros enclose ALL macro parameters in parentheses, of which the above is meant only to be a representative example.
The actual macros that produce warnings are for instance
the RTA_* macros in /usr/include/linux/rtnetlink.h.
Short of not using/redefining these macros in C++, is there any workaround?
If you look at the revision summary of the latest C++1z draft, you'd see this in [diff.cpp14.dcl.dcl]
[dcl.stc]
Change: Removal of register storage-class-specifier.
Rationale: Enable repurposing of deprecated keyword in future
revisions of this International Standard.
Effect on original feature: A valid C++ 2014 declaration utilizing the register
storage-class-specifier is ill-formed in this International Standard.
The specifier can simply be removed to retain the original meaning.
The warning may be due to that.
register is no longer a storage class specifier, you should remove it. Compilers may not be issuing the right error or warnings but your code should not have register to begin with
The following is a quote from the standard informing people about what they should do with regards to register in their code (relevant part emphasized), you probably have an old version of that file
C.1.6 Clause 10: declarations [diff.dcl]
Change: In C++, register is not a storage class specifier.
Rationale: The storage class specifier had no effect in C++.
Effect on original feature: Deletion of semantically well-defined feature.
Difficulty of converting: Syntactic transformation.
How widely used: Common.
Your worry is unwarranted since the file in question does not actually contain the register keyword:
grep "register" /usr/include/linux/rtnetlink.h
outputs nothing. Either way, you shouldn't be receiving the warning since:
System headers don't emit warnings by default, at least in GCC
It isn't wise to try to compile a file that belongs to a systems project like the linux kernel in C++ mode, as there may be subtle and nasty breaking changes
Just include the file normally or link the C code to your C++ binary. Report a bug if you really are getting a warning that should normally be suppressed to your compiler vendor.

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.

gfortran WRITE and FORMAT not appearing to need to conform on intel comiler

I am compiling a program which is known to compile with ifort using gfortran. However, the compiler fails on the line
WRITE (11,1325) ((IFILE,FILENAME(IFILE)),IFILE=1,IFILES)
with the compile error:
main_file.f:205.32:
WRITE (11,1325) ((IFILE,FILENAME(IFILE)),IFILE=1,IFILES)
1
Error: Expected PARAMETER symbol in complex constant at (1)
make: *** [main_file.o] Error 1
Changing this line to (note removal of '(' and ')')
WRITE (11,1480) (IFILE,FILENAME(IFILE),IFILE=1,IFILES)
to match the subsequent line
1480 FORMAT (1X,I1,' ',A40)
solves the problem, but I was wondering if anyone may know why is this mistake not captured by the Intel compiler. In this instance, it seems to be gfortran which is giving the correct behaviour. My compile flags are:
gfortran -fno-automatic -mcmodel=medium -O2 -ffast-math main_file.o -o main_file
As others have posted in the similar recent questions, due to its heritage the Intel compiler allows a number of extensions by default. The compiler will emit a diagnostic if you supply the appropriate standard check option (/stand on Windows, for example).
I'm not sure of the specific source of this particular extension, but it covers a somewhat occasional syntax misunderstanding, where people would put the "arguments" to the write or read "function" in parentheses...
READ (*,*) (not_valid_syntax)
(In a write statement an expression in parentheses is itself an expression, and that is a valid output list item - a few years back the Intel compiler would get a bit confused about that.)
Quite an interesting issue. It works only for arrays:
print *, ((1,["a","b"]),i=1,10)
end
works, but
print *, ((1,"a"),i=1,10)
end
fails with ifort:
: error #6063: An INTEGER or REAL data type is required in this context. ['a']
print *, ((1,"a"),i=1,10)
God knows what the parser thinks it is in the first working case, maybe an incomplete nested implied do? For sure it is not legal Fortran syntax and should by refused by compiler which requires standard Fortran. Intel may have reasons to accept this syntax.