diff mbox

[pr69011,fortran,v1,6,Regression,OOP] ICE in gfc_advance_chain for ALLOCATE with SOURCE

Message ID 20151229142126.5d6e9bba@vepi2
State New
Headers show

Commit Message

Andre Vehreschild Dec. 29, 2015, 1:21 p.m. UTC
Hi all, hi Thomas,

thanks for the fast review. Committed as r231992.

Regards,
	Andre

On Mon, 28 Dec 2015 18:31:32 +0100
Thomas Koenig <tkoenig@netcologne.de> wrote:

> Hi Andre,
> 
> > for bug pr69011 I like to propose the attached patch. The patch fixes
> > the ICE and furthermore makes sure, that for this case of referencing a
> > polymorphic object the correct vtype is selected. Previously the
> > declared vtype of the source=-expression was taken for the object(s) to
> > allocate. Now the actual vtype is taken, i.e., the vptr component of
> > source='s object is taken. This is important when source references a
> > subclass.
> >
> > Bootstrapped and regtested ok on x86_64-pc-linux-gnu/f23.
> >
> > Ok for trunk?
> 
> The patch also solves the original problem.
> 
> OK for trunk, and thanks a lot for the patch!
> 
> 
> 	Thomas
>
diff mbox

Patch

Index: gcc/fortran/ChangeLog
===================================================================
--- gcc/fortran/ChangeLog	(Revision 231990)
+++ gcc/fortran/ChangeLog	(Arbeitskopie)
@@ -1,3 +1,10 @@ 
+2015-12-29  Andre Vehreschild  <vehre@gcc.gnu.org>
+
+	PR fortran/69011
+	* trans-stmt.c (gfc_trans_allocate): Unwrap a NOP_EXPR to make sure
+	the actual type of the source=-expr is used when it is of class type.
+	Furthermore prevent an ICE.
+
 2015-12-18  Paul Thomas  <pault@gcc.gnu.org>
 
 	PR fortran/68196
Index: gcc/fortran/trans-stmt.c
===================================================================
--- gcc/fortran/trans-stmt.c	(Revision 231990)
+++ gcc/fortran/trans-stmt.c	(Arbeitskopie)
@@ -5377,7 +5377,20 @@ 
 	      if (code->ext.alloc.arr_spec_from_expr3 || code->expr3->rank != 0)
 		gfc_conv_expr_descriptor (&se, code->expr3);
 	      else
-		gfc_conv_expr_reference (&se, code->expr3);
+		{
+		  gfc_conv_expr_reference (&se, code->expr3);
+
+		  /* gfc_conv_expr_reference wraps POINTER_PLUS_EXPR in a
+		     NOP_EXPR, which prevents gfortran from getting the vptr
+		     from the source=-expression.  Remove the NOP_EXPR and go
+		     with the POINTER_PLUS_EXPR in this case.  */
+		  if (code->expr3->ts.type == BT_CLASS
+		      && TREE_CODE (se.expr) == NOP_EXPR
+		      && TREE_CODE (TREE_OPERAND (se.expr, 0))
+							   == POINTER_PLUS_EXPR)
+		      //&& ! GFC_CLASS_TYPE_P (TREE_TYPE (se.expr)))
+		    se.expr = TREE_OPERAND (se.expr, 0);
+		}
 	      /* Create a temp variable only for component refs to prevent
 		 having to go through the full deref-chain each time and to
 		 simplfy computation of array properties.  */
@@ -5494,7 +5507,6 @@ 
 	     expr3 may be a temporary array declaration, therefore check for
 	     GFC_CLASS_TYPE_P before trying to get the _vptr component.  */
 	  if (tmp != NULL_TREE
-	      && TREE_CODE (tmp) != POINTER_PLUS_EXPR
 	      && (e3_is == E3_DESC
 		  || (GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
 		      && (VAR_P (tmp) || !code->expr3->ref))
Index: gcc/testsuite/ChangeLog
===================================================================
--- gcc/testsuite/ChangeLog	(Revision 231990)
+++ gcc/testsuite/ChangeLog	(Arbeitskopie)
@@ -1,3 +1,8 @@ 
+2015-12-29  Andre Vehreschild  <vehre@gcc.gnu.org>
+
+	PR fortran/69011
+	* gfortran.dg/allocate_with_source_16.f90: New test.
+
 2015-12-28  Uros Bizjak  <ubizjak@gmail.com>
 
 	* gcc.target/i386/*.c: Remove extra braces from target selectors.
Index: gcc/testsuite/gfortran.dg/allocate_with_source_16.f90
===================================================================
--- gcc/testsuite/gfortran.dg/allocate_with_source_16.f90	(nicht existent)
+++ gcc/testsuite/gfortran.dg/allocate_with_source_16.f90	(Arbeitskopie)
@@ -0,0 +1,76 @@ 
+! { dg-do run }
+! Test the fix for pr69011, preventing an ICE and making sure
+! that the correct dynamic type is used.
+!
+! Contributed by Thomas Koenig  <tkoenig@gcc.gnu.org>
+!                Andre Vehreschild  <vehre@gcc.gnu.org>
+!
+ 
+module m1
+implicit none
+private
+public :: basetype
+
+type:: basetype
+  integer :: i
+  contains
+endtype basetype
+
+abstract interface
+endinterface
+
+endmodule m1
+
+module m2
+use m1, only : basetype
+implicit none
+integer, parameter :: I_P = 4
+
+private
+public :: factory, exttype
+
+type, extends(basetype) :: exttype
+  integer :: i2
+  contains
+endtype exttype
+
+type :: factory
+  integer(I_P) :: steps=-1 
+  contains
+    procedure, pass(self), public :: construct
+endtype factory
+contains
+
+  function construct(self, previous)
+  class(basetype), intent(INOUT) :: previous(1:)
+  class(factory), intent(IN) :: self
+  class(basetype), pointer :: construct
+  allocate(construct, source=previous(self%steps))
+  endfunction construct
+endmodule m2
+
+  use m2
+  use m1
+  class(factory), allocatable :: c1
+  class(exttype), allocatable :: prev(:)
+  class(basetype), pointer :: d
+
+  allocate(c1)
+  allocate(prev(2))
+  prev(:)%i = [ 2, 3]
+  prev(:)%i2 = [ 5, 6]
+  c1%steps= 1
+  d=> c1%construct(prev)
+
+  if (.not. associated(d) ) call abort()
+  select type (d)
+    class is (exttype)
+      if (d%i2 /= 5) call abort()
+    class default
+      call abort()
+  end select 
+  if (d%i /= 2) call abort()
+  deallocate(c1)
+  deallocate(prev)
+  deallocate(d)
+end