https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123899
Steve Kargl <kargl at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Ever confirmed|0 |1
CC| |kargl at gcc dot gnu.org
Last reconfirmed| |2026-01-31
Priority|P3 |P4
Status|UNCONFIRMED |NEW
--- Comment #3 from Steve Kargl <kargl at gcc dot gnu.org> ---
For the code that works and changing it to avoid a print statement,
% cat nc2.f90
integer y(0)
call sub(y) ! passing a 0-sized integer array
contains
subroutine sub(x)
integer x(..)
if (size(x) /= 0) stop 1
end subroutine
end
the -ftree-dump-original for the main program is
void MAIN__ ()
{
static void sub (struct array15_integer(kind=4) & restrict);
integer(kind=4) y[0];
{
struct array01_integer(kind=4) parm.3;
parm.3.span = 4;
parm.3.dtype = {.elem_len=4, .version=0, .rank=1, .type=1};
parm.3.dim[0].lbound = 1;
parm.3.dim[0].ubound = 0;
parm.3.dim[0].stride = 1;
parm.3.data = (void *) &y[0];
parm.3.offset = -1;
sub (&parm.3);
}
}
Note lbound=1 and ubound=0 is a zero-sized array. These values are
used in inlined code for SIZE(), which yields a value of 0.
Now, the problematic code. The zero-sized array constructor
and assumed-rank dummy argument generated zero-sized
temporary arrays:
% cat nc1.f90
call sub([integer::]) ! passing a 0-sized integer array
contains
subroutine sub(x)
integer x(..)
if (size(x) /= 0) stop 1
end subroutine
end
__attribute__((fn spec (". ")))
void MAIN__ ()
{
static void sub (struct array15_integer(kind=4) & restrict);
{
struct array01_integer(kind=4) atmp.3;
integer(kind=4) A.4[0];
struct array01_integer(kind=4) atmp.6;
integer(kind=4) A.7[0];
typedef integer(kind=4) [0];
atmp.3.dtype = {.elem_len=4, .version=0, .rank=1, .type=1};
atmp.3.dim[0].stride = 1;
atmp.3.dim[0].lbound = 0;
atmp.3.dim[0].ubound = -1;
atmp.3.span = 4;
atmp.3.data = (void * restrict) &A.4;
atmp.3.offset = 0;
typedef integer(kind=4) [0];
atmp.6.dtype = {.elem_len=4, .version=0, .rank=1, .type=1};
atmp.6.dim[0].stride = 1;
atmp.6.dim[0].lbound = 0;
atmp.6.dim[0].ubound = -1;
atmp.6.span = 4;
atmp.6.data = (void * restrict) &A.7;
atmp.6.offset = 0;
{
integer(kind=8) S.8;
S.8 = 0;
while (1)
{
if (S.8 >= 0) goto L.4;
(*(integer(kind=4)[0] * restrict) atmp.6.data)[S.8] =
(*(integer(kind=4)[0] * restrict) atmp.3.data)[S.8];
S.8 = S.8 + 1;
}
L.4:;
}
sub (&atmp.6);
}
}
On entering the while-loop, s.8 = 0 and so we jump to L.4. Here, the
temporary array has lbound=0 and ubound=-1, which is again a zero-sized
array. But, these values used in the inlined code for SIZE() yield
a value of -1. This is of course wrong.
I don't know if we should have a check in SIZE() for size < -1 and
then return 0; or, does gfortran assume a canonical form for a
zero-sized array with lbound = 1 and ubound = 0.