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.

Reply via email to