Bound checking for empty arrays: behavior of various compilers

Update 20210914: Absoft support confirms that the behavior of af95 / af90 described below is unintended and indeed a bug. Absoft developers will work to resolve it. The other compilers act correctly in this regard. Thank everyone for the comments and suggestions.


I have the impression that Fortran is cool with arrays of size 0. However, with Absoft Pro 21.0, I encountered a (strange) error involving such arrays. In contrast, gfortran , ifort , nagfor , pgfortran , sunf95 , and g95 are all happy with the same piece of code.

Below is a minimal working example.

! testempty.f90

!!!!!! A module that offends AF90/AF95 !!!!!!!!!!!!!!!!!!!!!!!!
module empty_mod

implicit none
private
public :: foo

contains

subroutine foo(n)
implicit none
integer, intent(in) :: n
integer :: a(0)
integer :: b(n - 1)
integer, allocatable :: c(:)                                                                                                       
allocate (c(n - 1))                                                                                                                
call bar(c)  ! Update: AF90/AF95 is happy with this line.     
call bar(a)  ! AF90/AF95 is happy with this line.
call bar(b)  ! AF90/AF95 is angry with this line.
end subroutine foo

subroutine bar(x)
implicit none
integer, intent(out) :: x(:)
x = 1  ! BAR(B) annoys AF90/AF95 regardless of this line.
end subroutine bar

end module empty_mod
!!!!!! Module ends !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


!!!!!! Main program !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
program testempty

use empty_mod, only : foo

implicit none

call foo(2)  ! AF90/AF95 is happy with this line.
call foo(1)  ! AF90/AF95 is angry with this line.
write (*, *) 'Succeed!'  ! Declare victory when arriving here.

end program testempty
!!!!!! Main program ends !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Name this piece of code as testempty.f90. Then run

$ af95 -no-pie -et -Rb -g -O0 -o atest testempty.f90
$ ./atest

This is what happened on my machine (Ubuntu 20.04, linux 5.4.0-77-generic, x86_64):

./atest
? FORTRAN Runtime Error:
? Subscript 1 is out of range for dimension 1 for array 
? B with bounds 1:
? File testempty.f90; Line 19
? atest, run-time exception on Mon Sep 13 14:08:41 2021
? Program counter: 000000001004324B
? Signal SIGABRT, Abort
? Traceback follows
OBJECT             PC                ROUTINE                LINE  SOURCE
libpthread.so.0    000000001004324B  raise                   N/A  N/A
atest              00000000004141F3  __abs_f90rerr           N/A  N/A
atest              000000000041CA81  _BOUNDS_ERROR           N/A  N/A
atest              00000000004097B4  __FOO.in.EMPTY_MO       N/A  N/A
atest              000000000040993A  MAIN__                   40  testempty.f90
atest              000000000042A209  main                    N/A  N/A
libc.so.6          000000000FD0C0B3  __libc_start_main       N/A  N/A
atest              000000000040956E  _start                  N/A  N/A

So af95 was annoyed by call bar(b). With af90, the result was the same.

I tested the same code using gfortran, ifort, nagfor, pgfortran, sunf95, and g95. All of them were quite happy with the code even though I imposed bound checking explicitly. Below is the Makefile for the tests.

# This Makefile tests the following compilers on empty arrays.
#
# af95: Absoft 64-bit Pro Fortran 21.0.0
# gfortran: GNU Fortran (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
# ifort: ifort (IFORT) 2021.2.0 20210228
# nagfor: NAG Fortran Compiler Release 7.0(Yurakucho) Build 7036
# pgfortran: pgfortran (aka nvfortran) 21.3-0 LLVM 64-bit x86-64
# sunf95: Oracle Developer Studio 12.6
# g95: G95 (GCC 4.0.3 (g95 0.94!) Jan 17 2013)
#
# Tested on Ubuntu 20.04 with Linux 5.4.0-77-generic x86_64

.PHONY: test clean

test:
	make -s gtest
	make -s itest
	make -s ntest
	make -s ptest
	make -s stest
	make -s 9test
	make -s atest

gtest: FC = gfortran -Wall -Wextra -fcheck=all
itest: FC = ifort -warn all -check all
ntest: FC = nagfor -C
ptest: FC = pgfortran -C -Mbounds
stest: FC = sunf95 -w3 -xcheck=%all -C
9test: FC = g95 -Wall -Wextra -fbounds-check
atest: FC = af95 -no-pie -et -Rb

%test: testempty.f90
	$(FC) -g -O0 -o $@ $<
	./$@

clean:
	rm -f *.o *.mod *.dbg *test

Questions:

  1. Is the behavior of af95 / af90 standard-conforming?
  2. Does my code contain anything that violates the Fortran standards?
  3. In general, is it considered dangerous to involve empty arrays in Fortran code? Sometimes they are inevitable given the fact data sizes are often undecidable before runtime.

By “standards”, I mean F2003, F2008, and F2018.

Thank you very much for any comment or criticism.

(The same question is posed on StackOverflow, and I hope it does not violate the rules here.)strong text

Regarding your questions:

ad 1.
As far as I can tell, your code is standard-conforming. Zero-size arrays are a very deliberate feature of Fortran and should work fine.
ad 2.
See 1.
ad 3.
No, zero-size arrays are completely acceptable, They work in the same way as other arrays. Here is a small program I posted in MoA Slack to illustrate that Fortran (like MoA) distinguishes different zero-size arrays:

! moa_empty_array.f90 –
! Empty arrays Ă  la MoA?
!
program moa_empty_array
implicit none

integer, dimension(:,:,:), allocatable :: array

allocate( array(0,0,3) )

write(*,*) 'Size: ', size(array)
write(*,*) 'Shape:', shape(array)

end program moa_empty_array

The output is exactly what you would expect.

My suggestion is that you file a bug report with Absoft.

2 Likes

@Arjen 's answer is correct, and this looks like a bug in the Absoft compiler. I will note, that it looks like the bug stems more from the “automatic shape” array, b. You might try making b allocatable, and allocating it to that size n-1 to see if the same problem occurs. Narrowing down these subtle details can greatly help the vendor isolate and fix the cause of the issue.

1 Like

Thank you, @everythingfunctional . I have updated my post. An allocatable array does not cause the problem.

@zaikunzhang ,

For whatever it’s worth, please find some additional comments to your questions:

  • Your questions 1 and 2 go together of course. I too am unable to find any standard conformance issues with your code in the original post. In this regard, please note a standard-conforming processor is indeed expected to process standard-conforming code.

  • Re: “… is it considered dangerous to involve empty arrays… ,” again note I find the standard trying its best to offer the semantics and syntax to support zero-size arrays which is a good thing for the practitioners. Thus the standard tries to make it safe and productive for you to proceed with them. As to the practical matter of finding compilers that deal with such arrays safely though, the mileage may vary unfortunately. You’re following the best approach under the circumstances: identifying the issues and reporting them to implementors to fix the problems for you. Hopefully you will find good support with such requests.

2 Likes

Thank you @FortranFan for your comments. It is indeed reassuring to know that zero-size arrays are considered safe and a good thing, as they are not unusual in my project.

I have contacted Absoft and get confirmed that the behavior of af95 / af90 in this regard is unintended and indeed a bug.

1 Like