Stop code in variable? - fortran

Is it possible to stop or abort a fortran program with an error code/message in a variable? It seems it's not possible with the intrinsic STOP:
integer :: status = 1
character(len=3) :: err_msg = "err"
stop status
stop err_msg
Both stop calls throw syntax errors on compilation. Am I missing something, or do I have to call stop 1 directly, for example? Or write my own wrapper?

Up to Fortran 2003 the stop code can be either a scalar-char-constant or a sequence of up to 5 digits. A scalar-char-constant means what others might call a string, eg your "err" but not your err_msg.
In Fortran 2008 the stop code can be an expression which returns either a scalar-default-char-constant-expr or a scalar-int-constant-expr. If you had a Fortran 2008 compliant compiler then you could use a parameter (eg something declared as character(len=3), parameter :: err_msg = "err") as a stop code
Of course, the state of implementation of features introduced in the 2003 and 2008 standards varies from compiler to compiler and version to version. It looks as if your compiler version doesn't go beyond the Fortran 2003 standard.
And what your operating system does with the stop code is another matter.

Beyond requiring F2008 - no - not in a variable. In F2008 the stop code must be an integer or character constant expression. Variables are not constants - an expression that relies on the value of a variable is not a constant expression.
If you added the parameter attribute to the declarations of status and err_msg then they would be [named] constants, and could be used as a primary in the constant expression for a stop or error stop statement.

The current standards make no allowances for variables in stop codes. However, they have become more and more flexible as High Performance Mark already stated.
In the upcoming Fortran 2015 standard (working document from 2016/05/01, section 8.4) the stop code can be either a scalar-default-char-expr or a scalar-int-expr. So your code will work with a compliant compiler.
This feature of Fortran 2015 was added in version 7 of GCC.

Related

Why is the value of sum equal to 9 and not to 3 while trying to spawn threads and use them from a child process? [duplicate]

In fortran 95, if you assign a variable at declaration
integer :: var = 0
it is equivalent to
integer, save :: var = 0
and the variable is therefore preserved after routine execution (is equivalent to static in C speak) and does not get reinitialized when called again. What is the rationale/technical issue behind such (IMHO dangerous) behavior ?
I don't think that there is some rationale behind such behavior.
But as far as I know, Stefano, you used wrong terminology. In your code there is no assignment statement only variable (var) initialization using initialization expression (0).
integer :: var = 0 ! type declaration & initialization
integer :: var ! type declaration
var = 0 ! assignment
So it seems that it was just committee design decision. If we have such expression (with equality sign in type declaration statement) it is initialization not assignment. And initialization takes place only once during program (and not procedures) execution.
However there might be some historical reasons for such decision. Take a look at this thread.
Today such behavior is dangerous because many other widely used languages follows another conventions about initialization/assignment.
Many old FORTRAN 77 and earlier compilers statically allocated all variables. Many programmers relied upon this behavior -- this was technically a bug in their programs since unless they used the "SAVE" qualifier in the declaration (or added a plain SAVE statement to every procedure) the value of the variable was undefined upon reentry to a procedure. But since in those days programs tended to be tied to a particular platform and compiler for years, programmers got away with this. This is a very common "gotcha" in porting legacy FORTRAN 77 code to a modern Fortran >= 90 compilers. Most compilers provide compile-time switches to restore this behavior, such as the fno-automatic option of gfortran. Most likely the committee viewed variables that were initialized in their declaration as very likely to need the SAVE attribute -- in my opinion, a reasonable design decision. I think what is most different from other languages, and easiest to confuse the multi-lingual programmer, is that the initialization is done only once.

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.

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