Is my suspicion correct that the parameter /check:bounds is not applicable for allocated arrays? Is there a possibility to check that the bounds of allocated arrays are not violated, other than an allocation with bounds carefully selected?
Do you have an example?
PROGRAM check_bounds IMPLICIT NONE INTEGER, ALLOCATABLE :: array(:) ALLOCATE(array(5)) array(6) = 2 END PROGRAM check_bounds
>ifort /check:bounds /Od "2016-08-02 check-bounds.f90" && "2016-08-02 check-bounds.exe" Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 188.8.131.52 Build 20160415 Copyright (C) 1985-2016 Intel Corporation. All rights reserved. Microsoft (R) Incremental Linker Version 14.00.24210.0 Copyright (C) Microsoft Corporation. All rights reserved. "-out:2016-08-02 check-bounds.exe" -subsystem:console "2016-08-02 check-bounds.obj" forrtl: severe (408): fort: (10): Subscript #1 of the array ARRAY has value 6 which is greater than the upper bound of 5 Image PC Routine Line Source 2016-08-02 check- 00007FF65C9D49BE Unknown Unknown Unknown 2016-08-02 check- 00007FF65C9D125B Unknown Unknown Unknown 2016-08-02 check- 00007FF65C9FD76E Unknown Unknown Unknown 2016-08-02 check- 00007FF65C9FDFE5 Unknown Unknown Unknown KERNEL32.DLL 00007FF8E2B98102 Unknown Unknown Unknown ntdll.dll 00007FF8E4A8C5B4 Unknown Unknown Unknown
Sorry, the frantic search for an error which caused a debug interrupt in a complex project caused a temporary blindness for the obvious. Boundary violations are caught allright, also for allocated arrays, if the parameter /check:boundaries is set. IanH, please take my apologies for the extra work to answer my inconsiderate question.
Related to this topic: Below is an example where the use of an allocatable array and assignments out of allocated bounds do not seem to be detected by /check:bounds.
PROGRAM TestCheckBounds IMPLICIT NONE INTEGER(4),DIMENSION(6) :: z !INTEGER(4),DIMENSION(4) :: y !using this declaration (and commenting out line 10) leads the compiler to indicate an error: "The shapes of the array expressions do not conform." INTEGER(4),DIMENSION(:),ALLOCATABLE :: y z = [1,2,3,4,5,6] WRITE(*,*)," z 1: ", z ALLOCATE(y(4)) y = z !no error indicated during compilation/run time WRITE(*,*)," y: ", y z = y !no error indicated during compilation/run time WRITE(*,*)," z 2: ", z READ(*,*) !y(5) = z(5) !this line throws an error (as expected) END PROGRAM TestCheckBounds
In my opinion, the lines y = z and z = y (see comments in code) should cause an error.
The following is the command line used from within Visual Studio 2015 Community, Update 3:
/nologo /debug:full /Od /warn:interfaces /module:"Debug\\" /object:"Debug\\" /Fd"Debug\vc140.pdb" /traceback /check:pointer /check:bounds /check:uninit /check:format /check:output_conversion /check:stack /libs:dll /threads /dbglibs /c
I used the Intel(R) Visual Fortran Compiler 16.0 [IA-32].
Is it the expected "correct" behavior that an array size (bounds) mismatch is not detected here when an allocatable array 'y' is used - I find it rather surprising.
What you are asking for is shape checking, not really bounds checking. At present we don't do shape checking, so in the contexts where the shapes don't match whether or not you get a bounds error is unpredictable.
If you add the option /standard-semantics (Fortran > Language > Enable Fortran 2003 Semantics) then you'll get Fortran standard automatic reallocation on the allocatable array assignment to y. This (the reallocation on different shape) will be the default in version 17.
Some thoughts about shape checking. If you modify line 11 in post #4 of Andi to
y(1:6) = z(1:6)
a shape ckeck is done in run time and an error is thrown. This easy case could be covered in compile time, because the allocation is done with a fixed number, isn't it.
forrtl: severe (408): fort: (2): Subscript #1 of the array Y has value 5 which is greater than the up per bound of 4
Curiously the other way round (lhs index span smaller than rhs) is found at compile time (modified line 10 and 11):
ALLOCATE(y(6)) y(1:4) = z(1:6)
TestCheckBounds.f90(11): error #6366: The shapes of the array expressions do not conform.
1>compilation aborted for ... TestCheckBounds.f90 (code 1)
In some more complicated cases (index is a part of a user defined type), I've seen that shape checking works not every time. Unfortunately, I have no minimum working example. (PSXE 2016 up3, win32).
@Steve: Will the new default in 17 (including -assume realloc_lhs) have an impact on the performance in cases where the shapes do not changes, because there is a test in run time?
I was able to modify the code above to a case, where shape checking fails:
PROGRAM TestCheckBounds IMPLICIT NONE INTEGER(4),DIMENSION(6) :: z !INTEGER(4),DIMENSION(4) :: y !using this declaration (and commenting out line 10) leads the compiler to indicate an error: "The shapes of the array expressions do not conform." INTEGER(4),DIMENSION(:),ALLOCATABLE :: y type foo_t integer :: bar integer :: barbar end type foo_t type(foo_t) :: foo foo%bar = 1 foo%barbar = 4 z = [1,2,3,4,5,6] WRITE(*,*)," z 1: ", z ALLOCATE(y(6)) y(foo%bar:foo%barbar) = z(1:6) !no error indicated during compilation/run time WRITE(*,*)," y: ", y z = y !no error indicated during compilation/run time WRITE(*,*)," z 2: ", z READ(*,*) !y(5) = z(5) !this line throws an error (as expected) END PROGRAM TestCheckBounds
No compile time error is thrown, nor a run time error occurs hitting line 19. Is it a defect or are shapes only checked if the bounds are numbers and not variables?
What I said was that the compiler does not check shapes in the current version (except in the case for allocatable array assignment). (We're looking at this for development over the next year, but no promises.) You might get lucky with bounds checking enabled, but many times no error is reported.
Yes, there is overhead for checking the shape on allocatable array assignment when the shapes do conform. We try to keep this as low as possible. You can turn off the feature if you want, but we had many, many customers complain that our default didn't match the standard and, nowadays, most if not all other compilers out there do the reallocation by default.
I have a related question about the new array reallocation feature. Will it be possible to check that the reallocation was successful? When I explicitly allocate the array with ALLOCATE, I can check the output STAT variable to make sure that the allocation was successful.
The feature isn't new - it's been there for 15 years, but you had to ask for it with /assume:realloc_lhs (or /standard-semantics). The only thing changing is that the default is now realloc_lhs instead of norealloc_lhs.
The language does not provide a means to query the status of an implicit allocation. You're free to do it yourself (as you had to pre-F2003), and then the change in default makes no difference (other than a bit of overhead for the check.)
There actually is one more change, under the hood. Up through version 16, if you had realloc_lhs enabled the code to do the checking and allocation was all inline, which could sometimes inhibit optimization (since it was a lot of intermediate language). As of version 17 it's done in a library call for much less generated code and potentially better optimization. This also allowed us to clean up the compiler quite a bit, improving reliability.