Bug 64921 - [4.9/5/6 Regression] FAIL: gfortran.dg/class_allocate_18.f90
Summary: [4.9/5/6 Regression] FAIL: gfortran.dg/class_allocate_18.f90
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 5.0
: P4 normal
Target Milestone: 4.9.4
Assignee: Mikael Morin
URL:
Keywords:
: 64849 (view as bug list)
Depends on:
Blocks:
 
Reported: 2015-02-03 15:41 UTC by H.J. Lu
Modified: 2015-08-05 17:03 UTC (History)
10 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2015-02-16 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description H.J. Lu 2015-02-03 15:41:57 UTC
On x86-32, r220369 gave

FAIL: gfortran.dg/class_allocate_18.f90   -O0  execution test
FAIL: gfortran.dg/class_allocate_18.f90   -O1  execution test
FAIL: gfortran.dg/class_allocate_18.f90   -O2  execution test
FAIL: gfortran.dg/class_allocate_18.f90   -O3 -fomit-frame-pointer  execution test
FAIL: gfortran.dg/class_allocate_18.f90   -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions  execution test
FAIL: gfortran.dg/class_allocate_18.f90   -O3 -fomit-frame-pointer -funroll-loops  execution test
FAIL: gfortran.dg/class_allocate_18.f90   -O3 -g  execution test
FAIL: gfortran.dg/class_allocate_18.f90   -Os  execution test

when -fPIC is used.  r220364 is OK.
Comment 1 Jakub Jelinek 2015-02-03 16:03:52 UTC
r220371 generates identical code to r220350 on this testcase.
Do you mean libgfortran.so has been miscompiled?
But then really -fPIC shouldn't matter here, as libgfortran is built with -fpic, and I've certainly bootstrapped/regtested my patch on both i686-linux and x86_64-linux.
Comment 2 H.J. Lu 2015-02-03 17:22:13 UTC
I got

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0xF763FACE
#1  0xF763EBDE
#2  0xF773CBBF
#3  0x8048BA5 in __final_main_T2.3337 at class_allocate_18.f90:?
#4  0x8048D68 in __final_main_T3.3328 at class_allocate_18.f90:?
#5  0x8048A59 in MAIN__ at class_allocate_18.f90:?
FAIL: gfortran.dg/class_allocate_18.f90   -O1  execution test

But I couldn't reproduce it on another machine. I will keep an eye on it.
Comment 3 H.J. Lu 2015-02-03 17:32:53 UTC
gfortran.dg/class_allocate_18.f90 seems to fail at random on trunk
and 4.9 branch:

https://gcc.gnu.org/ml/gcc-testresults/2015-02/msg00308.html

It is caused by r220191.
Comment 4 Paul Thomas 2015-02-03 21:30:45 UTC
(In reply to H.J. Lu from comment #3)
> gfortran.dg/class_allocate_18.f90 seems to fail at random on trunk
> and 4.9 branch:
> 
> https://gcc.gnu.org/ml/gcc-testresults/2015-02/msg00308.html
> 
> It is caused by r220191.

HJ,

I'll take a look at this tomorrow night. I find it to be enormously surprising that r220191 is causing this regression. I rather think that I have exposed another underlying bug.

Thanks

Paul
Comment 5 Ramana Radhakrishnan 2015-02-04 03:00:21 UTC
(In reply to Paul Thomas from comment #4)
> (In reply to H.J. Lu from comment #3)
> > gfortran.dg/class_allocate_18.f90 seems to fail at random on trunk
> > and 4.9 branch:
> > 
> > https://gcc.gnu.org/ml/gcc-testresults/2015-02/msg00308.html
> > 
> > It is caused by r220191.
> 
> HJ,
> 
> I'll take a look at this tomorrow night. I find it to be enormously
> surprising that r220191 is causing this regression. I rather think that I
> have exposed another underlying bug.
> 
> Thanks
> 
> Paul

I've been seeing this test fail in cross-testing on arm-linux-gnueabi{hf} too. However native testresults from gcc-testresults don't show this coming up often. Not sure what's going on here.

Ramana
Comment 6 Paul Thomas 2015-02-04 18:21:36 UTC
(In reply to H.J. Lu from comment #2)
> I got
> 
> Program received signal SIGSEGV: Segmentation fault - invalid memory
> reference.
> 
> Backtrace for this error:
> #0  0xF763FACE
> #1  0xF763EBDE
> #2  0xF773CBBF
> #3  0x8048BA5 in __final_main_T2.3337 at class_allocate_18.f90:?
> #4  0x8048D68 in __final_main_T3.3328 at class_allocate_18.f90:?
> #5  0x8048A59 in MAIN__ at class_allocate_18.f90:?
> FAIL: gfortran.dg/class_allocate_18.f90   -O1  execution test
> 
> But I couldn't reproduce it on another machine. I will keep an eye on it.

Hi HJ,

Given that the error is sporadic, are you sure that the offending revisions are not 220125 and 220130 - PR64230. The error messages that you are getting are remarkably similar to the original report for this PR.

In the case of PR62044, the fix only applies to allocation with MOLD = derived type. class_allocate_18.f90 involves a CLASS entity and does not use MOLD = anything.

I will investigate if there is not some horrible kludge that is spoofing up the allocate expression in class_allocate_18.f90 by passing the typespec through a hidden MOLD expression. If this is not the case, there is nothing that I can do.

I'll come back to you in about twenty minutes. I have put Janus in copy.

Cheers

Paul
Comment 7 H.J. Lu 2015-02-04 18:31:44 UTC
(In reply to Paul Thomas from comment #6)
> (In reply to H.J. Lu from comment #2)
> > I got
> > 
> > Program received signal SIGSEGV: Segmentation fault - invalid memory
> > reference.
> > 
> > Backtrace for this error:
> > #0  0xF763FACE
> > #1  0xF763EBDE
> > #2  0xF773CBBF
> > #3  0x8048BA5 in __final_main_T2.3337 at class_allocate_18.f90:?
> > #4  0x8048D68 in __final_main_T3.3328 at class_allocate_18.f90:?
> > #5  0x8048A59 in MAIN__ at class_allocate_18.f90:?
> > FAIL: gfortran.dg/class_allocate_18.f90   -O1  execution test
> > 
> > But I couldn't reproduce it on another machine. I will keep an eye on it.
> 
> Hi HJ,
> 
> Given that the error is sporadic, are you sure that the offending revisions
> are not 220125 and 220130 - PR64230. The error messages that you are getting
> are remarkably similar to the original report for this PR.
> 

I don't know for sure.  This failure seems more consistent on 4.9 branch
than on trunk.
Comment 8 Paul Thomas 2015-02-04 18:45:26 UTC
(In reply to H.J. Lu from comment #7)
> (In reply to Paul Thomas from comment #6)
> > (In reply to H.J. Lu from comment #2)
> > > I got
> > > 
> > > Program received signal SIGSEGV: Segmentation fault - invalid memory
> > > reference.
> > > 
> > > Backtrace for this error:
> > > #0  0xF763FACE
> > > #1  0xF763EBDE
> > > #2  0xF773CBBF
> > > #3  0x8048BA5 in __final_main_T2.3337 at class_allocate_18.f90:?
> > > #4  0x8048D68 in __final_main_T3.3328 at class_allocate_18.f90:?
> > > #5  0x8048A59 in MAIN__ at class_allocate_18.f90:?
> > > FAIL: gfortran.dg/class_allocate_18.f90   -O1  execution test
> > > 
> > > But I couldn't reproduce it on another machine. I will keep an eye on it.
> > 
> > Hi HJ,
> > 
> > Given that the error is sporadic, are you sure that the offending revisions
> > are not 220125 and 220130 - PR64230. The error messages that you are getting
> > are remarkably similar to the original report for this PR.
> > 
> 
> I don't know for sure.  This failure seems more consistent on 4.9 branch
> than on trunk.

Dear HJ,

I can confirm that the part of resolve.c modified in r220191 is not visited by the compilation of class_allocate_18.f90.

If I have understood correctly, -fPIC is not supported on x86_64 and so, unless I am mistaken, I cannot help you further.

Please let me know if there is anything that I can do to help.

Best regards

Paul
Comment 9 Dominique d'Humieres 2015-02-04 19:00:53 UTC
> If I have understood correctly, -fPIC is not supported on x86_64 and so,
> unless I am mistaken, I cannot help you further.

This is not how I understand comment 1.

Note that if I compile with -fsanitize=address, the executable crashes with

 allocated!
=================================================================
==73209==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000e040 at pc 0x000103b59dbd bp 0x7fff5c0a6fa0 sp 0x7fff5c0a6f98
READ of size 8 at 0x60200000e040 thread T0
    #0 0x103b59dbc  (/Users/dominiq/Documents/Fortran/g95bench/win/f90/bug/a.out+0x100001dbc)
    #1 0x103b595aa  (/Users/dominiq/Documents/Fortran/g95bench/win/f90/bug/a.out+0x1000015aa)
    #2 0x103b59889  (/Users/dominiq/Documents/Fortran/g95bench/win/f90/bug/a.out+0x100001889)
    #3 0x103b5a7a6  (/Users/dominiq/Documents/Fortran/g95bench/win/f90/bug/a.out+0x1000027a6)
    #4 0x7fff8fd1e5c8  (/usr/lib/system/libdyld.dylib+0x35c8)
    #5 0x0  (<unknown module>)

0x60200000e040 is located 0 bytes to the right of 16-byte region [0x60200000e030,0x60200000e040)
allocated by thread T0 here:
    #0 0x103b8d1fa  (/opt/gcc/gcc4.10w/lib/libasan.2.dylib+0x2f1fa)
    #1 0x103b59642  (/Users/dominiq/Documents/Fortran/g95bench/win/f90/bug/a.out+0x100001642)
    #2 0x103b5a7a6  (/Users/dominiq/Documents/Fortran/g95bench/win/f90/bug/a.out+0x1000027a6)
    #3 0x7fff8fd1e5c8  (/usr/lib/system/libdyld.dylib+0x35c8)
    #4 0x0  (<unknown module>)

SUMMARY: AddressSanitizer: heap-buffer-overflow ??:0 ??
Shadow bytes around the buggy address:
  0x1c0400001bb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c0400001bc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c0400001bd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c0400001be0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c0400001bf0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa 01 fa
=>0x1c0400001c00: fa fa 00 fa fa fa 00 00[fa]fa 07 fa fa fa 07 fa
  0x1c0400001c10: fa fa 06 fa fa fa 00 06 fa fa 00 00 fa fa 03 fa
  0x1c0400001c20: fa fa 00 06 fa fa 00 07 fa fa 00 fa fa fa 00 00
  0x1c0400001c30: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 00 00
  0x1c0400001c40: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 00 00
  0x1c0400001c50: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 00 00

I see this for r220302, r220156, r220109, and r219830 (i.e., all the revisions I have tested).

Note that Janus has removed the -fsanitize=undefined option at r220181, while it worked for me provided I ran the test after install.
Comment 10 Dominique d'Humieres 2015-02-04 19:03:00 UTC
This is probably a duplicate of pr64849.
Comment 11 Dominique d'Humieres 2015-02-16 13:40:05 UTC
*** Bug 64849 has been marked as a duplicate of this bug. ***
Comment 12 Dominique d'Humieres 2015-02-16 13:48:26 UTC
If I comment the line

  Deallocate (t)

the test compiled with -fsanitize=address runs without error. This is also the case for the following variant

Program main
  Implicit None
  Type :: t1
  End Type
  Type, Extends (t1) :: t2
    Integer, Allocatable :: i
  End Type
  Type, Extends (t2) :: t3
    Integer, Allocatable :: j
  End Type
  Class (t1), Allocatable :: t
  Allocate (t3 :: t)
  if (allocated(t)) then
    print *,"allocated!"
    select type (t)
      type is (t1)
        print *, "type is t1"
      type is (t2)
        print *, "type is t2"
      type is (t3)
        print *, "type is t3"
        t%i = 42
        t%j = 99
        print *, t%i, t%j
        Deallocate (t%i, t%j)
    end select
!    deallocate (t)
  else
    call abort ()
  end if
End

which outputs at run time

 allocated!
 type is t3
          42          99
Comment 13 Jerry DeLisle 2015-04-16 01:38:54 UTC
I still see this failure on trunk. 6.0
Comment 14 Mat Cross 2015-04-27 12:26:16 UTC
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.

In the interim, does anyone have any bright ideas for a reasonable (few-line) workaround?

Thanks.
Comment 15 Jakub Jelinek 2015-06-26 19:56:26 UTC
GCC 4.9.3 has been released.
Comment 16 ktkachov 2015-07-07 15:29:39 UTC
I see this execution fail on aarch64-linux-gnu and arm-none-linux-gnueabihf on the GCC 5 branch
Comment 17 Uroš Bizjak 2015-07-25 13:31:19 UTC
(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:

--cut here--
test ()
{
  integer(kind=8)[0:D.4089] * restrict sizes;
  integer(kind=8)[0:D.4068] * restrict sizes;
  void * _13;
  integer(kind=4) * _63;
  integer(kind=4) * _121;

  <bb 2>:
  _13 = __builtin_malloc (24);
  if (_13 == 0B)
    goto <bb 3>;
  else
    goto <bb 4>;

  <bb 3>:
  _gfortran_os_error (&"Allocation would exceed memory limit"[1]{lb: 1 sz: 1});

  <bb 4>:
  MEM[(c_char * {ref-all})_13] = MEM[(c_char * {ref-all})&__def_init_test_T4];
  sizes_22 = __builtin_malloc (8);
  MEM[(integer(kind=8)[0:D.3483] *)sizes_22][0] = 1;
  _63 = MEM[(struct t4 *)_13].k;
  if (_63 == 0B)
    goto <bb 6>;
  else
    goto <bb 5>;

  <bb 5>:
  __builtin_free (_63);

  <bb 6>:
  sizes_79 = __builtin_malloc (8);
  _121 ={v} MEM[(struct t3 *)0B].j.i;
  __builtin_trap ();

}
--cut here--

The <bb 6>: part reads from address 0x0+, and if this doesn't crash, trap insn surely crashes program.
Comment 18 Uroš Bizjak 2015-07-25 15:12:53 UTC
(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 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.
Comment 19 Richard Biener 2015-07-27 07:57:17 UTC
(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.
Comment 20 Mikael Morin 2015-07-27 18:45:41 UTC
(In reply to Richard Biener from comment #19)
> 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.

transfer.4 + offset calculates the address of an element of an array.
I believe that if that code is executed, array.data is non-zero, and  of course array.data + offset as well.

I think the the test should check for ptr2%j's nullness before deallocating ptr2%j, instead of testing ptr2.

With a patch like this:

diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
index 218973d..1ff7437 100644
--- a/gcc/fortran/class.c
+++ b/gcc/fortran/class.c
@@ -967,7 +967,7 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
       cond->block->expr1->ts.kind = gfc_default_logical_kind;
       cond->block->expr1->value.function.isym = gfc_intrinsic_function_by_id (GFC_ISYM_ASSOCIATED);
       cond->block->expr1->value.function.actual = gfc_get_actual_arglist ();
-      cond->block->expr1->value.function.actual->expr = gfc_copy_expr (expr);
+      cond->block->expr1->value.function.actual->expr = gfc_copy_expr (e);
       cond->block->expr1->value.function.actual->next = gfc_get_actual_arglist ();
       cond->block->next = dealloc;
 

Unfortunately, it doesn't seem to fix the problem.
Comment 21 rguenther@suse.de 2015-07-27 19:44:00 UTC
On July 27, 2015 8:45:41 PM GMT+02:00, "mikael at gcc dot gnu.org" <gcc-bugzilla@gcc.gnu.org> wrote:
>https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64921
>
>Mikael Morin <mikael at gcc dot gnu.org> changed:
>
>           What    |Removed                     |Added
>----------------------------------------------------------------------------
>              CC|                            |mikael at gcc dot gnu.org
>
>--- Comment #20 from Mikael Morin <mikael at gcc dot gnu.org> ---
>(In reply to Richard Biener from comment #19)
>> 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.
>
>transfer.4 + offset calculates the address of an element of an array.
>I believe that if that code is executed, array.data is non-zero, and 
>of course
>array.data + offset as well.

Yes but if transfer.4 is null then transfer.4 + offset does not have to be.

Transfer.4 _is_ null in the case we segfault.  So the guard us clearly wrong.

>I think the the test should check for ptr2%j's nullness before
>deallocating
>ptr2%j, instead of testing ptr2.
>
>With a patch like this:
>
>diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
>index 218973d..1ff7437 100644
>--- a/gcc/fortran/class.c
>+++ b/gcc/fortran/class.c
>@@ -967,7 +967,7 @@ finalize_component (gfc_expr *expr, gfc_symbol
>*derived,
>gfc_component *comp,
>       cond->block->expr1->ts.kind = gfc_default_logical_kind;
> cond->block->expr1->value.function.isym = gfc_intrinsic_function_by_id
>(GFC_ISYM_ASSOCIATED);
> cond->block->expr1->value.function.actual = gfc_get_actual_arglist ();
>-      cond->block->expr1->value.function.actual->expr = gfc_copy_expr
>(expr);
>+      cond->block->expr1->value.function.actual->expr = gfc_copy_expr
>(e);
>cond->block->expr1->value.function.actual->next =
>gfc_get_actual_arglist
>();
>       cond->block->next = dealloc;
>
>
>Unfortunately, it doesn't seem to fix the problem.
Comment 22 Mikael Morin 2015-07-28 12:07:44 UTC
(In reply to rguenther@suse.de from comment #21)
> Transfer.4 _is_ null in the case we segfault.  So the guard us clearly wrong.
> 
OK, let's try something else.
Are you positive transfer.4 is null?
I don't see anything that would make it so.

If it is transfer.10 that is  null, I can see the call to __final_main_T2 that is suspicious; it seems to pass a descriptorless array to an argument expecting a descriptor.

Draft patch, seems to fix it

diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
index 218973d..7a9e275 100644
--- a/gcc/fortran/class.c
+++ b/gcc/fortran/class.c
@@ -1599,6 +1599,7 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
   final->ts.type = BT_INTEGER;
   final->ts.kind = 4;
   final->attr.artificial = 1;
+  final->attr.always_explicit = 1;
   final->attr.if_source = expr_null_wrapper ? IFSRC_IFBODY : IFSRC_DECL;
   if (ns->proc_name->attr.flavor == FL_MODULE)
     final->module = ns->proc_name->name;
Comment 23 rguenther@suse.de 2015-07-28 12:31:53 UTC
On Tue, 28 Jul 2015, mikael at gcc dot gnu.org wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64921
> 
> --- Comment #22 from Mikael Morin <mikael at gcc dot gnu.org> ---
> (In reply to rguenther@suse.de from comment #21)
> > Transfer.4 _is_ null in the case we segfault.  So the guard us clearly wrong.
> > 
> OK, let's try something else.
> Are you positive transfer.4 is null?
> I don't see anything that would make it so.

From inspecting registers and the assembly.  The debugger cannot get
at the artificial decls.

> If it is transfer.10 that is  null, I can see the call to __final_main_T2 that
> is suspicious; it seems to pass a descriptorless array to an argument expecting
> a descriptor.
> 
> Draft patch, seems to fix it
> 
> diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
> index 218973d..7a9e275 100644
> --- a/gcc/fortran/class.c
> +++ b/gcc/fortran/class.c
> @@ -1599,6 +1599,7 @@ generate_finalization_wrapper (gfc_symbol *derived,
> gfc_namespace *ns,
>    final->ts.type = BT_INTEGER;
>    final->ts.kind = 4;
>    final->attr.artificial = 1;
> +  final->attr.always_explicit = 1;
>    final->attr.if_source = expr_null_wrapper ? IFSRC_IFBODY : IFSRC_DECL;
>    if (ns->proc_name->attr.flavor == FL_MODULE)
>      final->module = ns->proc_name->name;

even better
Comment 24 Uroš Bizjak 2015-07-28 12:43:33 UTC
(In reply to Mikael Morin from comment #22)
> (In reply to rguenther@suse.de from comment #21)
> > Transfer.4 _is_ null in the case we segfault.  So the guard us clearly wrong.
> > 
> OK, let's try something else.
> Are you positive transfer.4 is null?
> I don't see anything that would make it so.

I can confirm that this patch fixes "Invalid read of size 8" valgrind memory error for gfortran.dg/class_allocate_18.f90.
Comment 25 Mikael Morin 2015-08-03 10:04:27 UTC
Author: mikael
Date: Mon Aug  3 10:03:55 2015
New Revision: 226493

URL: https://gcc.gnu.org/viewcvs?rev=226493&root=gcc&view=rev
Log:
Fix random class_allocate_18.f90 failure

	PR fortran/64921
gcc/fortran/
	* class.c (generate_finalization_wrapper): Set finalization
	procedure symbol's always_explicit attribute.
gcc/testsuite/
	* gfortran.dg/class_allocate_20.f90: New.


Added:
    trunk/gcc/testsuite/gfortran.dg/class_allocate_20.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/class.c
    trunk/gcc/testsuite/ChangeLog
Comment 26 Mikael Morin 2015-08-05 15:42:02 UTC
I'm preparing the backports.
Comment 27 Mikael Morin 2015-08-05 16:16:11 UTC
Author: mikael
Date: Wed Aug  5 16:15:40 2015
New Revision: 226636

URL: https://gcc.gnu.org/viewcvs?rev=226636&root=gcc&view=rev
Log:
Fix random class_allocate_18.f90 failure

	PR fortran/64921
gcc/fortran/
	* class.c (generate_finalization_wrapper): Set finalization
	procedure symbol's always_explicit attribute.
gcc/testsuite/
	* gfortran.dg/class_allocate_20.f90: New.


Added:
    branches/gcc-5-branch/gcc/testsuite/gfortran.dg/class_allocate_20.f90
Modified:
    branches/gcc-5-branch/gcc/fortran/ChangeLog
    branches/gcc-5-branch/gcc/fortran/class.c
    branches/gcc-5-branch/gcc/testsuite/ChangeLog
Comment 28 Mikael Morin 2015-08-05 16:42:31 UTC
Author: mikael
Date: Wed Aug  5 16:42:00 2015
New Revision: 226639

URL: https://gcc.gnu.org/viewcvs?rev=226639&root=gcc&view=rev
Log:
Fix random class_allocate_18.f90 failure

	PR fortran/64921
gcc/fortran/
	* class.c (generate_finalization_wrapper): Set finalization
	procedure symbol's always_explicit attribute.
gcc/testsuite/
	* gfortran.dg/class_allocate_20.f90: New.


Added:
    branches/gcc-4_9-branch/gcc/testsuite/gfortran.dg/class_allocate_20.f90
Modified:
    branches/gcc-4_9-branch/gcc/fortran/ChangeLog
    branches/gcc-4_9-branch/gcc/fortran/class.c
    branches/gcc-4_9-branch/gcc/testsuite/ChangeLog
Comment 29 Mikael Morin 2015-08-05 17:03:55 UTC
Fixed for 6.0, 5.3 and 4.9.4, closing.