https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115260

Thomas Koenig <tkoenig at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |mikael at gcc dot gnu.org,
                   |                            |pault at gcc dot gnu.org

--- Comment #7 from Thomas Koenig <tkoenig at gcc dot gnu.org> ---
For the following, a bit simplified test case

program usegnufields
  implicit none
  type :: field_type
    real,    allocatable :: mydat(:)
  end type field_type
  type :: fieldholder
    type(field_type) :: fieldset(2,4)
  end type fieldholder
  type(fieldholder) :: myfields

  allocate(myfields%fieldset(2,1)%mydat(3))
  myfields%fieldset(2,1)%mydat = 1.0
!  print '(*(Z8.8:1X))',myfields%fieldset(2,1)%mydat

  call setfields (myfields%fieldset(2,1:4))
!  print *,'After calling setfields with fieldset(2,1:4)'
!  print '(*(Z8.8:1X))',myfields%fieldset(2,1)%mydat

contains
  subroutine setfields (fieldset)
    type(field_type), intent(inout) :: fieldset(1:4) ! corruption with -O
  end subroutine setfields
end

the tree generated below around the call is

      if (__builtin_expect ((integer(kind=8)) contiguous.9, 1, 52))
        {
          arg_ptr.8 = (struct field_type[4] * restrict) parm.11.data;
        }
      else
        {
          D.4728 = &myfields.fieldset;
                    typedef struct field_type [4];
          atmp.4.dtype = {.elem_len=64, .version=0, .rank=1, .type=5};
          atmp.4.dim[0].stride = 1;
          atmp.4.dim[0].lbound = 0;
          atmp.4.dim[0].ubound = 3;
          atmp.4.span = 64;
          atmp.4.data = (void * restrict) &A.5;
          atmp.4.offset = 0;
          {
            integer(kind=8) S.6;

            S.6 = 0;
            while (1)
              {
                if (S.6 > 3) goto L.2;
                (*(struct field_type[4] * restrict) atmp.4.data)[S.6] =
(*D.4728)[(S.6 + 1) * 2 + -1];
                S.6 = S.6 + 1;
              }
            L.2:;
          }
          arg_ptr.8 = (struct field_type[4] * restrict) atmp.4.data;
        }
      setfields (arg_ptr.8);
      if (__builtin_expect ((integer(kind=8)) !contiguous.9, 0, 52))
        {
          D.4739 = &myfields.fieldset;
          {
            integer(kind=8) S.7;

            D.4740 = -1;
            S.7 = 1;
            while (1)
              {
                if (S.7 > 4) goto L.3;
                {
                  struct field_type D.4742;

                  D.4742 = (*D.4739)[S.7 * 2 + -1];
                  (*D.4739)[S.7 * 2 + -1] = *((struct field_type *) atmp.4.data
+ (sizetype) ((S.7 + D.4740) * 64));
                  if ((real(kind=4)[0:] * restrict) D.4742.mydat.data != 0B)
                    {
                      __builtin_free ((void *) D.4742.mydat.data);
                      (real(kind=4)[0:] * restrict) D.4742.mydat.data = 0B;
                    }
                }
                S.7 = S.7 + 1;
              }
            L.3:;
          }
        }


which manipulates the allocatable components, which should not happen.
So the problem is in the way that gfc_conv_subref_array_arg handles
this case.

It does so by unconditionally calling gfc_trans_scalar_assign
at trans-expr.cc:5727 at current trunk, which results in the
deallocations.

Further up, for handling the input argument, it does

  if (intent != INTENT_OUT)
    {
      tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, false);
      gfc_add_expr_to_block (&body, tmp);
      gcc_assert (rse.ss == gfc_ss_terminator);
      gfc_trans_scalarizing_loops (&loop, &body);
    }
  else
    {
      /* Make sure that the temporary declaration survives by merging
       all the loop declarations into the current context.  */
      for (n = 0; n < loop.dimen; n++)
        {
          gfc_merge_block_scope (&body);
          body = loop.code[loop.order[n]];
        }
      gfc_merge_block_scope (&body);
    }

So, this seems to be a bug in gfc_conv_subref_array_arg, which was exposed by
my patch. I would expect that other uses of gfc_conv_subref_array_arg
(such as the CFI work) are also affected.

My scalarizer-fu is weak to none-existing. Would it be possible for
somebody to help out?

Reply via email to