[Bug fortran/64921] [4.9/5/6 Regression] FAIL: gfortran.dg/class_allocate_18.f90
rguenth at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Mon Jul 27 07:57:00 GMT 2015
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.
More information about the Gcc-bugs
mailing list