if (!derived1 || !derived2)
gfc_internal_error ("gfc_compare_derived_types: invalid derived type");
+ if (derived1->attr.unlimited_polymorphic
+ && derived2->attr.unlimited_polymorphic)
+ return true;
+
+ if (derived1->attr.unlimited_polymorphic
+ != derived2->attr.unlimited_polymorphic)
+ return false;
+
/* Compare UNION types specially. */
if (derived1->attr.flavor == FL_UNION || derived2->attr.flavor == FL_UNION)
return compare_union_types (derived1, derived2);
&& strcmp (derived1->module, derived2->module) == 0)
return true;
- /* Compare type via the rules of the standard. Both types must have
- the SEQUENCE or BIND(C) attribute to be equal. STRUCTUREs are special
- because they can be anonymous; therefore two structures with different
- names may be equal. */
+ /* Compare type via the rules of the standard. Both types must have the
+ SEQUENCE or BIND(C) attribute to be equal. We also compare types
+ recursively if they are class descriptors types or virtual tables types.
+ STRUCTUREs are special because they can be anonymous; therefore two
+ structures with different names may be equal. */
/* Compare names, but not for anonymous types such as UNION or MAP. */
if (!is_anonymous_dt (derived1) && !is_anonymous_dt (derived2)
if (!(derived1->attr.sequence && derived2->attr.sequence)
&& !(derived1->attr.is_bind_c && derived2->attr.is_bind_c)
+ && !(derived1->attr.is_class && derived2->attr.is_class)
+ && !(derived1->attr.vtype && derived2->attr.vtype)
&& !(derived1->attr.pdt_type && derived2->attr.pdt_type))
return false;
/* Nothing more to do for unlimited polymorphic entities. */
if (data->ts.u.derived->attr.unlimited_polymorphic)
- return true;
+ {
+ add_dt_to_dt_list (sym);
+ return true;
+ }
else if (vptr->ts.u.derived == NULL)
{
gfc_symbol *vtab = gfc_find_derived_vtab (data->ts.u.derived);
! { dg-do run }
+! { dg-additional-options "-fdump-tree-dse-details" }
!
! Check that pointer assignments allowed by F2003:C717
! work and check null initialization of CLASS(*) pointers.
!
program main
interface
- subroutine foo(z)
+ subroutine foo_bc(z)
class(*), pointer, intent(in) :: z
- end subroutine foo
+ end subroutine foo_bc
+ subroutine foo_sq(z)
+ class(*), pointer, intent(in) :: z
+ end subroutine foo_sq
end interface
+ type, bind(c) :: bc
+ integer :: i
+ end type bc
type sq
sequence
- integer :: i
+ integer :: k
end type sq
+ type(bc), target :: w
type(sq), target :: x
class(*), pointer :: y, z
- x%i = 42
+ w%i = 23
+ y => w
+ z => y ! unlimited => unlimited allowed
+ call foo_bc(z)
+ x%k = 42
y => x
z => y ! unlimited => unlimited allowed
- call foo (z)
+ call foo_sq(z)
call bar
contains
subroutine bar
end program main
-
-subroutine foo(tgt)
+subroutine foo_bc(tgt)
use iso_c_binding
class(*), pointer, intent(in) :: tgt
- type, bind(c) :: s
- integer (c_int) :: k
- end type s
- type t
+ type, bind(c) :: bc
+ integer (c_int) :: i
+ end type bc
+ type(bc), pointer :: ptr1
+ ptr1 => tgt ! bind(c) => unlimited allowed
+ if (ptr1%i .ne. 23) STOP 2
+end subroutine foo_bc
+
+subroutine foo_sq(tgt)
+ class(*), pointer, intent(in) :: tgt
+ type sq
sequence
integer :: k
- end type t
- type(s), pointer :: ptr1
- type(t), pointer :: ptr2
- ptr1 => tgt ! bind(c) => unlimited allowed
- if (ptr1%k .ne. 42) STOP 2
+ end type sq
+ type(sq), pointer :: ptr2
ptr2 => tgt ! sequence type => unlimited allowed
if (ptr2%k .ne. 42) STOP 3
-end subroutine foo
+end subroutine foo_sq
+
+! PR fortran/103662
+! We used to produce multiple independant types for the unlimited polymorphic
+! descriptors (types for class(*)) which caused stores to them to be seen as
+! useless.
+! { dg-final { scan-tree-dump-not "Deleted dead store: z._data = &w" "dse1" } }
+! { dg-final { scan-tree-dump-not "Deleted dead store: z._data = &x" "dse1" } }