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

--- Comment #19 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Uroš Bizjak from comment #18)
> (In reply to Uroš Bizjak from comment #17)
> > (In reply to Mat Cross from comment #14)
> > > For the record, perhaps it is of interest for me to note that we are 
> > > running
> > > into this (cf. PR64230 comment 9) on code like
> > > 
> > > Program test
> > >   Implicit None
> > >   Type :: t1
> > >     Integer, Allocatable :: i
> > >   End Type
> > >   Type :: t2
> > >     Integer, Allocatable :: i
> > >   End Type
> > >   Type, Extends (t1) :: t3
> > >     Type (t2) :: j
> > >   End Type
> > >   Type, Extends (t3) :: t4
> > >     Integer, Allocatable :: k
> > >   End Type
> > >   Call s
> > >   Print *, 'ok'
> > > Contains
> > >   Subroutine s
> > >     Class (t1), Allocatable :: x
> > >     Allocate (t4 :: x)
> > >   End Subroutine
> > > End Program
> > > 
> > > Since the crash is in bad compiler-generated finalization code (since 
> > > 4.9),
> > > and given that (if I recall correctly) gfortran is using the Fortran 2008
> > > semantics for entities declared in a main program being implicitly saved,
> > > this is why removing the Deallocate (in the comment 12 example) works - 
> > > the
> > > finalizer is never called then.
> > 
> > No wonder this test crashes. Tree-optimizers (-O2) on x86_64 produce:
> 
> [...]
> 
> I was able to trace dumps down to _.fre2 tree dump, where we have:
> 
>   <bb 12>:
>   # idx_104 = PHI <0(11), idx_122(16)>
>   offset_115 = 0;
>   ptr2_119 = (struct t3 *) offset_115;
>   _120 = &ptr2_119->j;

This isn't a dereference, it's just an address computation.  Iff j
is not at offset zero then of course...

  if (_120 != 0B)
    goto <bb 19>;
  else
    goto <bb 22>;

  <bb 19>:
  _121 = ptr2_119->j.i;

we'll crash right here.

So the question is whether the frontend emits the correct test against zero:

                    offset = offset * byte_stride;
                    D.3466 = (void *) array->data;
                    D.3467 = D.3466;
                    D.3465 = 8;
                    D.3469 = 8;
                    __builtin_memcpy ((void *) &transfer.4, (void *) &D.3467,
(unsigned long) MAX_EXPR <MIN_EXPR <D.3469, D.3465>, 0>);
                    ptr2 = (struct t4 *) (transfer.4 + offset);
                    if (ptr2 != 0B)
                      {
                        {
                          integer(kind=4) stat.5;

                          if (ptr2->k == 0B)

to me it looks like if we really want to test transfer.4 (array->data) against
zero.  We do

   0x0000000000400b26 <+502>:   cmp    $0xfffffffffffffff8,%r15
   0x0000000000400b2a <+506>:   je     0x400b42 <test+530>
=> 0x0000000000400b2c <+508>:   mov    0x8(%r15),%rdi

and %r15 is zero, so offset is _not_ zero here (but ends up constant
propagated and we "optimize" the compare - offset seems to be 8).

> This can't be right, we have a dereference from zero. If the frontend
> produced correct code, then tree-optimization passes made a mess here.
> 
> CC Richi.

Reply via email to