re PR fortran/70397 (ice while allocating ultimate polymorphic)
authorAndre Vehreschild <vehre@gcc.gnu.org>
Tue, 29 Mar 2016 16:54:24 +0000 (18:54 +0200)
committerAndre Vehreschild <vehre@gcc.gnu.org>
Tue, 29 Mar 2016 16:54:24 +0000 (18:54 +0200)
gcc/fortran/ChangeLog:

2016-03-29  Andre Vehreschild  <vehre@gcc.gnu.org>

PR fortran/70397
* trans-expr.c (gfc_class_len_or_zero_get): Add function to return a
constant zero tree, when the class to get the _len component from is
not unlimited polymorphic.
(gfc_copy_class_to_class): Use the new function.
* trans.h: Added interface of new function gfc_class_len_or_zero_get.

gcc/testsuite/ChangeLog:

2016-03-29  Andre Vehreschild  <vehre@gcc.gnu.org>

PR fortran/70397
* gfortran.dg/unlimited_polymorphic_25.f90: New test.
* gfortran.dg/unlimited_polymorphic_26.f90: New test.

From-SVN: r234528

gcc/fortran/ChangeLog
gcc/fortran/trans-expr.c
gcc/fortran/trans.h
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/unlimited_polymorphic_25.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/unlimited_polymorphic_26.f90 [new file with mode: 0644]

index cf95d6ffc95949caa6a4154bfaf98fff39be5f0c..5ab7d3ff285368e11d50cd0801a7fffb7c84ec87 100644 (file)
@@ -1,3 +1,12 @@
+2016-03-29  Andre Vehreschild  <vehre@gcc.gnu.org>
+
+       PR fortran/70397
+       * trans-expr.c (gfc_class_len_or_zero_get): Add function to return a
+       constant zero tree, when the class to get the _len component from is
+       not unlimited polymorphic.
+       (gfc_copy_class_to_class): Use the new function.
+       * trans.h: Added interface of new function gfc_class_len_or_zero_get.
+
 2016-03-28  Alessandro Fanfarillo  <fanfarillo.gcc@gmail.com>
 
        * trans-decl.c (gfc_build_builtin_function_decls):
index 4baadc84ef0b07baa364c45e44058fcc97442aec..8d039a670b56b7da084e64eb274385afe827dc65 100644 (file)
@@ -173,6 +173,29 @@ gfc_class_len_get (tree decl)
 }
 
 
+/* Try to get the _len component of a class.  When the class is not unlimited
+   poly, i.e. no _len field exists, then return a zero node.  */
+
+tree
+gfc_class_len_or_zero_get (tree decl)
+{
+  tree len;
+  /* For class arrays decl may be a temporary descriptor handle, the vptr is
+     then available through the saved descriptor.  */
+  if (TREE_CODE (decl) == VAR_DECL && DECL_LANG_SPECIFIC (decl)
+      && GFC_DECL_SAVED_DESCRIPTOR (decl))
+    decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
+  if (POINTER_TYPE_P (TREE_TYPE (decl)))
+    decl = build_fold_indirect_ref_loc (input_location, decl);
+  len = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (decl)),
+                          CLASS_LEN_FIELD);
+  return len != NULL_TREE ? fold_build3_loc (input_location, COMPONENT_REF,
+                                            TREE_TYPE (len), decl, len,
+                                            NULL_TREE)
+                         : integer_zero_node;
+}
+
+
 /* Get the specified FIELD from the VPTR.  */
 
 static tree
@@ -250,6 +273,7 @@ gfc_vptr_size_get (tree vptr)
 
 #undef CLASS_DATA_FIELD
 #undef CLASS_VPTR_FIELD
+#undef CLASS_LEN_FIELD
 #undef VTABLE_HASH_FIELD
 #undef VTABLE_SIZE_FIELD
 #undef VTABLE_EXTENDS_FIELD
@@ -1120,7 +1144,7 @@ gfc_copy_class_to_class (tree from, tree to, tree nelems, bool unlimited)
   if (unlimited)
     {
       if (from != NULL_TREE && unlimited)
-       from_len = gfc_class_len_get (from);
+       from_len = gfc_class_len_or_zero_get (from);
       else
        from_len = integer_zero_node;
     }
index add0ceaa3db93e264ea6a3139eb86414a04d45a0..512615ab1e4cc60d65fa7ac444a19b9326fbb0ce 100644 (file)
@@ -365,6 +365,7 @@ tree gfc_class_set_static_fields (tree, tree, tree);
 tree gfc_class_data_get (tree);
 tree gfc_class_vptr_get (tree);
 tree gfc_class_len_get (tree);
+tree gfc_class_len_or_zero_get (tree);
 gfc_expr * gfc_find_and_cut_at_last_class_ref (gfc_expr *);
 /* Get an accessor to the class' vtab's * field, when a class handle is
    available.  */
index f9b4b001c791b77f66164393668d39aa948e8377..b7335a842d5cf688be8e0d2a1ac4f2e4569f9a54 100644 (file)
@@ -1,3 +1,9 @@
+2016-03-29  Andre Vehreschild  <vehre@gcc.gnu.org>
+
+       PR fortran/70397
+       * gfortran.dg/unlimited_polymorphic_25.f90: New test.
+       * gfortran.dg/unlimited_polymorphic_26.f90: New test.
+
 2016-03-29  Thomas Schwinge  <thomas@codesourcery.com>
 
        PR testsuite/64177
diff --git a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_25.f90 b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_25.f90
new file mode 100644 (file)
index 0000000..d0b2a2e
--- /dev/null
@@ -0,0 +1,40 @@
+! { dg-do run }
+!
+! Test contributed by Valery Weber  <valeryweber@hotmail.com>
+
+module mod
+
+  TYPE, PUBLIC :: base_type
+  END TYPE base_type
+
+  TYPE, PUBLIC :: dict_entry_type
+     CLASS( * ), ALLOCATABLE :: key
+     CLASS( * ), ALLOCATABLE :: val
+  END TYPE dict_entry_type
+
+
+contains
+
+  SUBROUTINE dict_put ( this, key, val )
+    CLASS(dict_entry_type), INTENT(INOUT)     :: this
+    CLASS(base_type), INTENT(IN)             :: key, val
+    INTEGER                                  :: istat
+    ALLOCATE( this%key, SOURCE=key, STAT=istat )
+  end SUBROUTINE dict_put
+end module mod
+
+program test
+  use mod
+  type(dict_entry_type) :: t
+  type(base_type) :: a, b
+  call dict_put(t, a, b)
+
+  if (.NOT. allocated(t%key)) call abort()
+  select type (x => t%key)
+    type is (base_type)
+    class default
+      call abort()
+  end select
+  deallocate(t%key)
+end
+
diff --git a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_26.f90 b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_26.f90
new file mode 100644 (file)
index 0000000..1300069
--- /dev/null
@@ -0,0 +1,47 @@
+! { dg-do run }
+!
+! Test contributed by Valery Weber  <valeryweber@hotmail.com>
+
+module mod
+
+  TYPE, PUBLIC :: dict_entry_type
+     CLASS( * ), ALLOCATABLE :: key
+     CLASS( * ), ALLOCATABLE :: val
+  END TYPE dict_entry_type
+
+
+contains
+
+  SUBROUTINE dict_put ( this, key, val )
+    CLASS(dict_entry_type), INTENT(INOUT)     :: this
+    CLASS(*), INTENT(IN)                     :: key, val
+    INTEGER                                  :: istat
+    ALLOCATE( this%key, SOURCE=key, STAT=istat )
+    ALLOCATE( this%val, SOURCE=val, STAT=istat )
+  end SUBROUTINE dict_put
+end module mod
+
+program test
+  use mod
+  type(dict_entry_type) :: t
+  call dict_put(t, "foo", 42)
+
+  if (.NOT. allocated(t%key)) call abort()
+  select type (x => t%key)
+    type is (CHARACTER(*))
+      if (x /= "foo") call abort()
+    class default
+      call abort()
+  end select
+  deallocate(t%key)
+
+  if (.NOT. allocated(t%val)) call abort()
+  select type (x => t%val)
+    type is (INTEGER)
+      if (x /= 42) call abort()
+    class default
+      call abort()
+  end select
+  deallocate(t%val)
+end
+