This patch is relatively trivial and represents my first foray into
gitland. Thus far, it has been... well, "interesting" compared with
svn.

Class components of derived types are initialized by calls to
trans-array.c(gfc_trans_deferred_array) from
trans-decl.c(gfc_trans_deferred_vars). The components are nullified in
trans-array.c(structure_alloc_comps). The 'same_type_as' intrinsic
requires that nullified class components either point to the declared
type vtable or, in the case of unlimited polymorphic components, the
vptr should be null. See Note 16.28 in the F2018 standard. The
attached patch implements that requirement.

Regtested on FC31/x86_64 - OK for head?

Paul

2020-02-23  Paul Thomas  <pa...@gcc.gnu.org>

    PR fortran/57710
    * trans-array.c (structure_alloc_comps): When nullifying class
    components, the vptr must point to the declared type or, in the
    case of unlimited polymorphic components, it should be null.

2020-02-23  Paul Thomas  <pa...@gcc.gnu.org>

    PR fortran/57710
    * gfortran.dg/same_type_as_3.f03 : New test.
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 66598161fd8..0449d281bf7 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -8827,7 +8827,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
 
 	  cdesc = gfc_create_var (cdesc, "cdesc");
 	  DECL_ARTIFICIAL (cdesc) = 1;
-  
+
 	  gfc_add_modify (&tmpblock, gfc_conv_descriptor_dtype (cdesc),
 	  		  gfc_get_dtype_rank_type (1, tmp));
 	  gfc_conv_descriptor_lbound_set (&tmpblock, cdesc,
@@ -8838,7 +8838,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
 					  gfc_index_one_node);
 	  gfc_conv_descriptor_ubound_set (&tmpblock, cdesc,
 					  gfc_index_zero_node, ubound);
-  
+
 	  if (attr->dimension)
 	    comp = gfc_conv_descriptor_data_get (comp);
 	  else
@@ -9116,10 +9116,14 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
 	      && (CLASS_DATA (c)->attr.allocatable
 		  || CLASS_DATA (c)->attr.class_pointer))
 	    {
+	      tree vptr_decl;
+
 	      /* Allocatable CLASS components.  */
 	      comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
 				      decl, cdecl, NULL_TREE);
 
+	      vptr_decl = gfc_class_vptr_get (comp);
+
 	      comp = gfc_class_data_get (comp);
 	      if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp)))
 		gfc_conv_descriptor_data_set (&fnblock, comp,
@@ -9131,6 +9135,24 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
 					 build_int_cst (TREE_TYPE (comp), 0));
 		  gfc_add_expr_to_block (&fnblock, tmp);
 		}
+
+	      /* The dynamic type of a disassociated pointer or unallocated
+		 allocatable variable is its declared type. An unlimited
+		 polymorphic entity has no declared type.  */
+	      if (!UNLIMITED_POLY (c))
+		{
+		  vtab = gfc_find_derived_vtab (c->ts.u.derived);
+		  if (!vtab->backend_decl)
+		     gfc_get_symbol_decl (vtab);
+		  tmp = gfc_build_addr_expr (NULL_TREE, vtab->backend_decl);
+		}
+	      else
+		tmp = build_int_cst (TREE_TYPE (vptr_decl), 0);
+
+	      tmp = fold_build2_loc (input_location, MODIFY_EXPR,
+					 void_type_node, vptr_decl, tmp);
+	      gfc_add_expr_to_block (&fnblock, tmp);
+
 	      cmp_has_alloc_comps = false;
 	    }
 	  /* Coarrays need the component to be nulled before the api-call
diff --git a/gcc/testsuite/gfortran.dg/same_type_as_3.f03 b/gcc/testsuite/gfortran.dg/same_type_as_3.f03
new file mode 100644
index 00000000000..3a81e749763
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/same_type_as_3.f03
@@ -0,0 +1,27 @@
+! { dg-do run }
+!
+! Test the fix for PR57710.
+!
+! Contributed by Tobias Burnus  <bur...@gcc.gnu.org>
+!
+module m
+  type t
+  end type t
+  type t2
+    integer :: ii
+    class(t), allocatable :: x
+  end type t2
+contains
+  subroutine fini(x)
+     type(t) :: x
+  end subroutine fini
+end module m
+
+use m
+block
+  type(t) :: z
+  type(t2) :: y
+  y%ii = 123
+  if (.not. same_type_as(y%x, z)) call abort ()
+end block
+end

Reply via email to