Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Array assignment semantics changed in IF 2017

Tobias_Loew
Novice
603 Views

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)

0 Kudos
30 Replies
Arjen_Markus
Honored Contributor I
425 Views

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.

0 Kudos
Steven_L_Intel1
Employee
425 Views

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. 

0 Kudos
Tobias_Loew
Novice
425 Views

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

0 Kudos
Steven_L_Intel1
Employee
425 Views

It's not a "non-standard construct" - it's just wrong. You could try enabling bounds checking but it would probably not catch this.

0 Kudos
Arjen_Markus
Honored Contributor I
425 Views

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.

0 Kudos
Tobias_Loew
Novice
425 Views

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

0 Kudos
Steven_L_Intel1
Employee
425 Views

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.

0 Kudos
Tobias_Loew
Novice
425 Views

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.
 

0 Kudos
Steven_L_Intel1
Employee
425 Views

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.

0 Kudos
Tobias_Loew
Novice
425 Views

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.

0 Kudos
mecej4
Honored Contributor III
425 Views

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:

Run-time Error
Error: Nonconformant arrays
 main -  in file tobias.f90 at line 11 [+00cc]
0 Kudos
Tobias_Loew
Novice
425 Views

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

0 Kudos
mecej4
Honored Contributor III
425 Views

Tobias,

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

0 Kudos
Tobias_Loew
Novice
425 Views

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.

0 Kudos
Steven_L_Intel1
Employee
425 Views

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.

0 Kudos
mecej4
Honored Contributor III
425 Views

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.

0 Kudos
Tobias_Loew
Novice
425 Views

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

0 Kudos
TimP
Honored Contributor III
425 Views

$ ifort -check -traceback tl.f90

$ ./tl
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?

 

0 Kudos
Steven_L_Intel1
Employee
425 Views

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.

0 Kudos
jimdempseyatthecove
Honored Contributor III
370 Views

Maybe you can roll your own:

! Use -fpp to compile
#define TestAndCopy(a,b) IF(size(a) .ne. size(b)) call ReportBug(__FILE__,__LINE__);a=b

program Console2
implicit none
integer*4 MAX_INDEX
integer*4 DEST(80)
integer*4 SOURCE(80000)

MAX_INDEX = 9
SOURCE = 1
DEST = 0

TestAndCopy(DEST(1:MAX_INDEX),SOURCE)

  
end program Console2

Jim Dempsey

0 Kudos
Reply