The following program runs perfectly well up to (including) IF 2016. At the end of the program the array DEST contains 1 for indices 1 to 9 and 0 for all other indices. Now, with IF 2017 the program crashes (!) as it tries to assign all 80000 elements from SOURCE to DEST. I looked through the FORTRAN 95 standard but couldn't find a definite answer to that but IMHO either IF 2017 should reproduces the semantics of its predecessors or issue a compilation error but under no circumstances silently change the semantics and introduce a bug/runtime crash.
program Console2 implicit none integer*4 MAX_INDEX integer*4 DEST(80) integer*4 SOURCE(80000) MAX_INDEX = 9 SOURCE = 1 DEST = 0 DEST(1:MAX_INDEX)=SOURCE end program Console2
Sorry to say that, but the Intel-FORTRAN compilers keep introducing regressions in every new version (cf. e.g. https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/675911)
This does not have anything to do with a change in semantics. The program is not standard-compliant. The fact that it ran "correctly" with previous versions of the compiler does not mean it was correct.
The only thing you can accuse the compiler of is not flagging the problem at compile time.
Array assignment assume that the left-hand side has the same number of elements as the right-hand side and that is clearly not the case here. While it is easy to spot the mismatch in this program, it is not in general. But for that you have compile options to check the array bounds.
It's worse than "not standards compliant", the program is simply wrong. Unfortunately, our compiler does not yet offer a "shape checking" option, but this is being looked at for a future release.
@Arjen: What compile-time option are you talking about? Since I've got to maintain several 100000 LOC it would be great to check for such non-standard constructs.(If I understood Steve comment correct, there doesn't exist such an option.)
It's not a "non-standard construct" - it's just wrong. You could try enabling bounds checking but it would probably not catch this.
The option /check:bounds - it checks whether the program gets beyond the boundaries of the entire array, but as Steve said, the compiler does not support checks on the _shape_ yet.
I totally agree that non-standard code is a bad thing, but what are then all the compatibility options for in the compiler if not trying to resemble some old non-standard behavior?
@Steve: I would really appreciate a warning in case the compiler can't guarantee the same shapes for an assignment
In this case, it was entirely random which side's shape it would pick for doing the transfer. There was no deliberate change and the result was unpredictable.
As I noted, we're working on adding optional run-time shape checking. In the code you showed here, the compiler really has no opportunity to catch this at compile-time.
Please also add a compiler warning in case of standard behavior can't be ensured. A run-time check is too late since my program then will be crashes on a customers computer.
No compiler warning in this case would be possible. The behavior is entirely dependent on the run-time value assigned to the array index.
I would hope that you do extensive in-house testing of your application. There are many, many things that cannot be checked at compile-time.
The problem is: I don't no where in the code such constructs are used.
And, of course a compiler (NOT runtime) warning can be issued, e.g.
warning: array-sizes are runtime-dependent, non-standard behavior may occur [file + line information]
I don't see the point in testing all the code for finding something, that the compiler could simply tell me.
Unless you turn optimization off, in the test code DEST is not used after the erroneous assignment statement, so the whole line can be skipped after optimization.
Compilers that focus on optimization, such as Intel Fortran, may not be sufficient tools for trapping errors such as yours. We should not expect that the behavior of non-conforming code remains unchanged with new releases of the compiler, or even with different compiler options.
It is not so obvious that the error in your code can be caught at compile time rather than run time. The subscript expression on the left depends on the variable MAX_INDEX, which was changed/set a few statements earlier. In general, it would be non-trivial for the compiler to know that on Line-11 the value of MAX_INDEX is the constant value that was assigned elsewhere (Line-7). What if MAX_INDEX was a module variable, or could have been changed in a subroutine call between the two lines concerned?
Silverfrost Fortran gave the following run-time message with your code:
Error: Nonconformant arraysmain - in file tobias.f90 at line 11 [+00cc]
@mecej4: Thanks for the detailed explanation. But the code above is just a minimal test-case, so optimization is not the point at all. What I want is simply a warning/information in exactly the case you described, namely when the compiler can't ensure the arrays on both side to have the same size.
What's wrong about demanding the compiler to help the programmer to produce standard conformant code in the first place in stead of blaming him in front of his customers by producing runtime-erros, since obviously the compiler knows that the code may be executed in a non-standard manner.
By the way: I wouldn't know any FORTRAN primitives to catch/handle such a runtime-error.
I am sympathetic to your point of view, but I think that you attribute powers to the compiler that it does not possess when you state
"obviously the compiler knows that ...".
In the case of your program, it could know that the two sides are of different sizes if it did a static whole program analysis, but static analysis is done by a dedicated program in Intel Parallel Studio.
I agree that, if checks are requested, the compiler should help you to spot such problems, preferably at compile time, or at least at run time. It would, however, be undesirable to expect or even let the compiler fix erroneous code by replacing it with correct code representing its notion of what the programmer intended.
We tried the NAG 6.1 compiler on your program with the -C option. It did not give any error messages at compile time, but did give a run-time error:
Runtime Error: tobias.f90, line 11: Rank 1 of SOURCE has extent 80000 instead of 9
Program terminated by fatal error
I don't want to insinuate the compiler holding back information. I only want the compiler to admit that it DOESN'T KNOW (whether the arrays sizes will always be equal) by printing out a warning/information.
A warning of that nature would be emitted for about half the lines in any reasonable Fortran program - a situation that would clearly be unacceptable to the majority of our customers. Even A=B+C might theoretically overflow or underflow - should the compiler warn about that too?
Realistically, this is what application testing is for. As I said earlier, run-time shape checking would catch this error. Some other Fortran compilers have this, we will eventually.
Tobias Loew wrote:
I only want the compiler to admit that it DOESN'T KNOW (whether the arrays sizes will always be equal) by printing out a warning/information.
As Donald Rumsfeld taught us, there are known unknowns and unknown unknowns. It is only the former class that the compiler can have a hope of catching.
If such a feature is available in a compiler, it should be activated only if a user requests it, because otherwise one may see annoyingly voluminous warnings/error messages.
@Steve: That's a fair point. Nevertheless, most of the arrays-sizes/subscript-triple are rather easy/short expressions which could be algebraic analyzed by a tool. So, my question is: do you know of any such tool, which can do such a static analysis of FORTRAN programs? Or if not, does there exists a tool which can produce an AST (abstract syntax tree) from a FORTRAN program? (Then I could write my own tools to analyze it.)
$ ifort -check -traceback tl.f90
forrtl: severe (408): fort: (10): Subscript #1 of the array DEST has value 81 wh
ich is greater than the upper bound of 80
Image PC Routine Line Source
tl.exe 00007FF72F224229 Unknown Unknown Unknown
tl.exe 00007FF72F2211D4 MAIN__ 11 tl.f90
tl.exe 00007FF72F24CA0E Unknown Unknown Unknown
tl.exe 00007FF72F24D2C5 Unknown Unknown Unknown
KERNEL32.DLL 00007FFF400813D2 Unknown Unknown Unknown
ntdll.dll 00007FFF424754E4 Unknown Unknown Unknown
Perhaps the wording could be improved. Feature request?
https://github.com/CodethinkLabs/ofc claims to be a Fortran parser useful for writing such tools. I've never heard of an existing tool that would recognize the issue you described here, and I'd think that you'd be overwhelmed with false-positives if you tried.