Hi all,

attached patch fixes a regression introduced by my previous patch on handling
_vptr's more consistently. The patch gets the _vptr only of a derived or
class type now and not of every type.

Regression tested ok on x86_64-pc-linux-gnu / Fedora 39. Ok for mainline?

Regards,
        Andre

PS. This patch was made with all of my other pending patches on the same
branch. So it may not apply clean to master.
--
Andre Vehreschild * Email: vehre ad gmx dot de
From 4b19d871a3f5a4cdaf0fef6200ddaf51d6c8a8c4 Mon Sep 17 00:00:00 2001
From: Andre Vehreschild <ve...@gcc.gnu.org>
Date: Fri, 9 Aug 2024 16:19:23 +0200
Subject: [PATCH] [Fortran] Fix ICE in build_function_decl [PR116292]

Fix ICE by getting the vtype only when a derived or class type is
prevent.  Also take care about the _len component for unlimited
polymorphics.

gcc/fortran/ChangeLog:

	PR fortran/116292

	* trans-intrinsic.cc (conv_intrinsic_move_alloc): Get the vtab
	only for derived types and classes and adjust _len for class
	types.

gcc/testsuite/ChangeLog:

	* gfortran.dg/move_alloc_19.f90: New test.
---
 gcc/fortran/trans-intrinsic.cc              | 20 ++++++++++--
 gcc/testsuite/gfortran.dg/move_alloc_19.f90 | 34 +++++++++++++++++++++
 2 files changed, 51 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/move_alloc_19.f90

diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index 34115c2679b..0ecb0439778 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -12774,9 +12774,12 @@ conv_intrinsic_move_alloc (gfc_code *code)
 	  gfc_symbol *vtab;
 	  from_tree = from_se.expr;

-	  vtab = gfc_find_vtab (&from_expr->ts);
-	  gcc_assert (vtab);
-	  from_se.expr = gfc_get_symbol_decl (vtab);
+	  if (to_expr->ts.type == BT_CLASS)
+	    {
+	      vtab = gfc_find_vtab (&from_expr->ts);
+	      gcc_assert (vtab);
+	      from_se.expr = gfc_get_symbol_decl (vtab);
+	    }
 	}
       gfc_add_block_to_block (&block, &from_se.pre);

@@ -12821,6 +12824,15 @@ conv_intrinsic_move_alloc (gfc_code *code)
 	  gfc_class_set_vptr (&block, to_se.expr, from_se.expr);
 	  if (from_is_class)
 	    gfc_reset_vptr (&block, from_expr);
+	  if (UNLIMITED_POLY (to_expr))
+	    {
+	      tree to_len = gfc_class_len_get (to_se.class_container);
+	      tmp = from_expr->ts.type == BT_CHARACTER && from_se.string_length
+		      ? from_se.string_length
+		      : size_zero_node;
+	      gfc_add_modify_loc (input_location, &block, to_len,
+				  fold_convert (TREE_TYPE (to_len), tmp));
+	    }
 	}

       if (from_is_scalar)
@@ -12835,6 +12847,8 @@ conv_intrinsic_move_alloc (gfc_code *code)
 		  input_location, &block, from_se.string_length,
 		  build_int_cst (TREE_TYPE (from_se.string_length), 0));
 	    }
+	  if (UNLIMITED_POLY (from_expr))
+	    gfc_reset_len (&block, from_expr);

 	  return gfc_finish_block (&block);
 	}
diff --git a/gcc/testsuite/gfortran.dg/move_alloc_19.f90 b/gcc/testsuite/gfortran.dg/move_alloc_19.f90
new file mode 100644
index 00000000000..d23d9809ba1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/move_alloc_19.f90
@@ -0,0 +1,34 @@
+!{ dg-do run }
+
+! Check PR 116292 is fixed.
+
+! Contributed by Harald Anlauf  <anl...@gcc.gnu.org>
+!                Sam James  <sja...@gcc.gnu.org>
+
+program move_alloc_19
+  character, allocatable :: buffer, dummy, dummy2
+  class(*), allocatable :: poly
+
+  dummy = 'C'
+  dummy2 = 'A'
+  call s()
+  if (allocated (dummy)) stop 1
+  if (allocated (dummy2)) stop 2
+  if (.not. allocated (buffer)) stop 3
+  if (.not. allocated (poly)) stop 4
+  if (buffer /= 'C') stop 5
+  select type (poly)
+    type is (character(*))
+      if (poly /= 'A') stop 6
+      if (len (poly) /= 1) stop 7
+    class default
+      stop 8
+  end select
+  deallocate (poly, buffer)
+contains
+  subroutine s
+    call move_alloc (dummy, buffer)
+    call move_alloc (dummy2, poly)
+  end
+end
+
--
2.46.0

Reply via email to